diff options
| author | Android (Google) Code Review <android-gerrit@google.com> | 2009-07-27 18:08:32 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-07-27 18:08:32 -0700 |
| commit | 372554829200dfcc1e6c5895692ab9dd5d18a7b4 (patch) | |
| tree | 201e330cc55acb164d34c79b22d9ae504e2f2abf | |
| parent | 3d94ac1c8d959bfe339a8b108c39f74d2088e0ba (diff) | |
| parent | f5597e626ecf7949d249dea08c1a2964d890ec11 (diff) | |
| download | libcore-372554829200dfcc1e6c5895692ab9dd5d18a7b4.zip libcore-372554829200dfcc1e6c5895692ab9dd5d18a7b4.tar.gz libcore-372554829200dfcc1e6c5895692ab9dd5d18a7b4.tar.bz2 | |
Merge change 5582
* changes:
Integrate luni module (but not tests) to Harmony r772995.
404 files changed, 14348 insertions, 19699 deletions
diff --git a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java index eb2920e..d93c156 100644 --- a/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java +++ b/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java @@ -21,6 +21,7 @@ import dalvik.annotation.TestTargetClass; import dalvik.annotation.TestTargets; import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; +import dalvik.annotation.SideEffect; import java.math.BigInteger; import java.security.AlgorithmParameters; @@ -221,6 +222,7 @@ public class ExemptionMechanismTest extends TestCase { method = "finalize", args = {} ) + @SideEffect("Causes OutOfMemoryError to test finalization") public void test_finalize () { Mock_ExemptionMechanism mem = new Mock_ExemptionMechanism(null, null, "Name"); assertNotNull(mem); diff --git a/luni-kernel/src/main/java/java/lang/Class.java b/luni-kernel/src/main/java/java/lang/Class.java index 70ae3c1..6adf4db 100644 --- a/luni-kernel/src/main/java/java/lang/Class.java +++ b/luni-kernel/src/main/java/java/lang/Class.java @@ -440,7 +440,8 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @see ClassLoader#isSystemClassLoader() */ ClassLoader getClassLoaderImpl() { - return getClassLoader(this); + ClassLoader loader = getClassLoader(this); + return loader == null ? BootClassLoader.getInstance() : loader; } /* diff --git a/luni-kernel/src/main/java/java/lang/Thread.java b/luni-kernel/src/main/java/java/lang/Thread.java index 89d7ed6..484c258 100644 --- a/luni-kernel/src/main/java/java/lang/Thread.java +++ b/luni-kernel/src/main/java/java/lang/Thread.java @@ -79,10 +79,10 @@ public class Thread implements Runnable { private static class ParkState { /** park state indicating unparked */ private static final int UNPARKED = 1; - + /** park state indicating preemptively unparked */ private static final int PREEMPTIVELY_UNPARKED = 2; - + /** park state indicating parked */ private static final int PARKED = 3; } @@ -122,21 +122,21 @@ public class Thread implements Runnable { /** * The maximum priority value allowed for a thread. - * + * * @since Android 1.0 */ public final static int MAX_PRIORITY = 10; /** * The minimum priority value allowed for a thread. - * + * * @since Android 1.0 */ public final static int MIN_PRIORITY = 1; /** * The normal (default) priority value assigned to threads. - * + * * @since Android 1.0 */ public final static int NORM_PRIORITY = 5; @@ -200,7 +200,7 @@ public class Thread implements Runnable { /** the park state of the thread */ private int parkState = ParkState.UNPARKED; - + /** * Constructs a new {@code Thread} with no {@code Runnable} object and a * newly generated name. The new {@code Thread} will belong to the same @@ -208,7 +208,7 @@ public class Thread implements Runnable { * * @see java.lang.ThreadGroup * @see java.lang.Runnable - * + * * @since Android 1.0 */ public Thread() { @@ -219,14 +219,14 @@ public class Thread implements Runnable { * Constructs a new {@code Thread} with a {@code Runnable} object and a * newly generated name. The new {@code Thread} will belong to the same * {@code ThreadGroup} as the {@code Thread} calling this constructor. - * + * * @param runnable * a {@code Runnable} whose method <code>run</code> will be * executed by the new {@code Thread} * * @see java.lang.ThreadGroup * @see java.lang.Runnable - * + * * @since Android 1.0 */ public Thread(Runnable runnable) { @@ -237,13 +237,13 @@ public class Thread implements Runnable { * Constructs a new {@code Thread} with a {@code Runnable} object and name * provided. The new {@code Thread} will belong to the same {@code * ThreadGroup} as the {@code Thread} calling this constructor. - * + * * @param runnable * a {@code Runnable} whose method <code>run</code> will be * executed by the new {@code Thread} * @param threadName * the name for the {@code Thread} being created - * + * * @see java.lang.ThreadGroup * @see java.lang.Runnable * @@ -261,10 +261,10 @@ public class Thread implements Runnable { * Constructs a new {@code Thread} with no {@code Runnable} object and the * name provided. The new {@code Thread} will belong to the same {@code * ThreadGroup} as the {@code Thread} calling this constructor. - * + * * @param threadName * the name for the {@code Thread} being created - * + * * @see java.lang.ThreadGroup * @see java.lang.Runnable * @@ -282,7 +282,7 @@ public class Thread implements Runnable { * Constructs a new {@code Thread} with a {@code Runnable} object and a * newly generated name. The new {@code Thread} will belong to the {@code * ThreadGroup} passed as parameter. - * + * * @param group * {@code ThreadGroup} to which the new {@code Thread} will * belong @@ -298,7 +298,7 @@ public class Thread implements Runnable { * @see java.lang.Runnable * @see java.lang.SecurityException * @see java.lang.SecurityManager - * + * * @since Android 1.0 */ public Thread(ThreadGroup group, Runnable runnable) { @@ -308,7 +308,7 @@ public class Thread implements Runnable { /** * Constructs a new {@code Thread} with a {@code Runnable} object, the given * name and belonging to the {@code ThreadGroup} passed as parameter. - * + * * @param group * ThreadGroup to which the new {@code Thread} will belong * @param runnable @@ -325,7 +325,7 @@ public class Thread implements Runnable { * @see java.lang.Runnable * @see java.lang.SecurityException * @see java.lang.SecurityManager - * + * * @since Android 1.0 */ public Thread(ThreadGroup group, Runnable runnable, String threadName) { @@ -339,7 +339,7 @@ public class Thread implements Runnable { /** * Constructs a new {@code Thread} with no {@code Runnable} object, the * given name and belonging to the {@code ThreadGroup} passed as parameter. - * + * * @param group * {@code ThreadGroup} to which the new {@code Thread} will belong * @param threadName @@ -353,7 +353,7 @@ public class Thread implements Runnable { * @see java.lang.Runnable * @see java.lang.SecurityException * @see java.lang.SecurityManager - * + * * @since Android 1.0 */ public Thread(ThreadGroup group, String threadName) { @@ -367,7 +367,7 @@ public class Thread implements Runnable { /** * Constructs a new {@code Thread} with a {@code Runnable} object, the given * name and belonging to the {@code ThreadGroup} passed as parameter. - * + * * @param group * {@code ThreadGroup} to which the new {@code Thread} will * belong @@ -389,7 +389,7 @@ public class Thread implements Runnable { * @see java.lang.Runnable * @see java.lang.SecurityException * @see java.lang.SecurityManager - * + * * @since Android 1.0 */ public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) { @@ -528,9 +528,9 @@ public class Thread implements Runnable { /** * Returns the number of active {@code Thread}s in the running {@code * Thread}'s group and its subgroups. - * + * * @return the number of {@code Thread}s - * + * * @since Android 1.0 */ public static int activeCount() { @@ -542,14 +542,14 @@ public class Thread implements Runnable { * there's none installed, this method is a no-op. If there's a * SecurityManager installed, {@link SecurityManager#checkAccess(Thread)} is * called for that SecurityManager. - * + * * @throws SecurityException * if a SecurityManager is installed and it does not allow * access to the Thread. - * + * * @see java.lang.SecurityException * @see java.lang.SecurityManager - * + * * @since Android 1.0 */ public final void checkAccess() { @@ -564,12 +564,12 @@ public class Thread implements Runnable { /** * Returns the number of stack frames in this thread. - * + * * @return Number of stack frames * @deprecated The results of this call were never well defined. To make * things worse, it would depend on whether the Thread was * suspended or not, and suspend was deprecated too. - * + * * @since Android 1.0 */ @Deprecated @@ -581,7 +581,7 @@ public class Thread implements Runnable { * Returns the Thread of the caller, that is, the current Thread. * * @return the current Thread. - * + * * @since Android 1.0 */ public static Thread currentThread() { @@ -592,7 +592,7 @@ public class Thread implements Runnable { * Destroys the receiver without any monitor cleanup. * * @deprecated Not implemented. - * + * * @since Android 1.0 */ @Deprecated @@ -603,9 +603,9 @@ public class Thread implements Runnable { /** * Prints to the standard error stream a text representation of the current * stack for this Thread. - * + * * @see Throwable#printStackTrace() - * + * * @since Android 1.0 */ public static void dumpStack() { @@ -617,7 +617,7 @@ public class Thread implements Runnable { * receiver - and subgroups - into the array <code>threads</code> passed as * parameter. If the array passed as parameter is too small no exception is * thrown - the extra elements are simply not copied. - * + * * @param threads * array into which the Threads will be copied * @return How many Threads were copied over @@ -626,7 +626,7 @@ public class Thread implements Runnable { * {@link SecurityManager#checkAccess(Thread)} * @see java.lang.SecurityException * @see java.lang.SecurityManager - * + * * @since Android 1.0 */ public static int enumerate(Thread[] threads) { @@ -640,13 +640,13 @@ public class Thread implements Runnable { * Returns the stack traces of all the currently live threads and puts them * into the given map. * </p> - * + * * @return A Map of current Threads to StackTraceElement arrays. * @throws SecurityException * if the current SecurityManager fails the * {@link SecurityManager#checkPermission(java.security.Permission)} * call. - * + * * @since Android 1.0 */ public static Map<Thread, StackTraceElement[]> getAllStackTraces() { @@ -684,14 +684,14 @@ public class Thread implements Runnable { * </ol> * are satisfied, a security check for * <code>RuntimePermission("getClassLoader")</code> is performed first. - * + * * @return ClassLoader The context ClassLoader * @see java.lang.ClassLoader * @see #getContextClassLoader() - * + * * @throws SecurityException * if the aforementioned security check fails. - * + * * @since Android 1.0 */ public ClassLoader getContextClassLoader() { @@ -719,7 +719,7 @@ public class Thread implements Runnable { * * @return an {@link UncaughtExceptionHandler} or <code>null</code> if * none exists. - * + * * @since Android 1.0 */ public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() { @@ -731,9 +731,9 @@ public class Thread implements Runnable { * generated on thread creation, is unique to the thread, and doesn't change * during the lifetime of the thread; the ID may be reused after the thread * has been terminated. - * + * * @return the thread's ID. - * + * * @since Android 1.0 */ public long getId() { @@ -744,7 +744,7 @@ public class Thread implements Runnable { * Returns the name of the Thread. * * @return the Thread's name - * + * * @since Android 1.0 */ public final String getName() { @@ -756,7 +756,7 @@ public class Thread implements Runnable { * * @return the Thread's priority * @see Thread#setPriority - * + * * @since Android 1.0 */ public final int getPriority() { @@ -770,13 +770,13 @@ public class Thread implements Runnable { * The <code>RuntimePermission("getStackTrace")</code> is checked before * returning a result. * </p> - * + * * @return an array of StackTraceElements. * @throws SecurityException * if the current SecurityManager fails the * {@link SecurityManager#checkPermission(java.security.Permission)} * call. - * + * * @since Android 1.0 */ public StackTraceElement[] getStackTrace() { @@ -792,9 +792,9 @@ public class Thread implements Runnable { /** * Returns the current state of the Thread. This method is useful for * monitoring purposes. - * + * * @return a {@link State} value. - * + * * @since Android 1.0 */ public State getState() { @@ -805,7 +805,7 @@ public class Thread implements Runnable { // deletes the reference we won't run into a null reference later. VMThread thread = vmThread; if (thread != null) { - // If the Thread Object became invalid or was not yet started, + // If the Thread Object became invalid or was not yet started, // getStatus() will return -1. int state = thread.getStatus(); if(state != -1) { @@ -814,12 +814,12 @@ public class Thread implements Runnable { } return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW; } - + /** * Returns the ThreadGroup to which this Thread belongs. - * + * * @return the Thread's ThreadGroup - * + * * @since Android 1.0 */ public final ThreadGroup getThreadGroup() { @@ -835,9 +835,9 @@ public class Thread implements Runnable { * Returns the thread's uncaught exception handler. If not explicitly set, * then the ThreadGroup's handler is returned. If the thread is terminated, * then <code>null</code> is returned. - * + * * @return an {@link UncaughtExceptionHandler} instance or {@code null}. - * + * * @since Android 1.0 */ public UncaughtExceptionHandler getUncaughtExceptionHandler() { @@ -870,14 +870,14 @@ public class Thread implements Runnable { * their interrupt status set and return immediately. They don't receive an * exception in this case. * <ul> - * + * * @throws SecurityException * if <code>checkAccess()</code> fails with a SecurityException * @see java.lang.SecurityException * @see java.lang.SecurityManager * @see Thread#interrupted * @see Thread#isInterrupted - * + * * @since Android 1.0 */ public void interrupt() { @@ -898,12 +898,12 @@ public class Thread implements Runnable { * <code>currentThread()</code>) has a pending interrupt request (<code> * true</code>) or not (<code>false</code>). It also has the side-effect of * clearing the flag. - * + * * @return a <code>boolean</code> indicating the interrupt status * @see Thread#currentThread * @see Thread#interrupt * @see Thread#isInterrupted - * + * * @since Android 1.0 */ public static boolean interrupted() { @@ -915,10 +915,10 @@ public class Thread implements Runnable { * still runs code (hasn't died yet). Returns <code>false</code> either if * the receiver hasn't been started yet or if it has already started and run * to completion and died. - * + * * @return a <code>boolean</code> indicating the lifeness of the Thread * @see Thread#start - * + * * @since Android 1.0 */ public final boolean isAlive() { @@ -936,7 +936,7 @@ public class Thread implements Runnable { * * @return a <code>boolean</code> indicating whether the Thread is a daemon * @see Thread#setDaemon - * + * * @since Android 1.0 */ public final boolean isDaemon() { @@ -951,7 +951,7 @@ public class Thread implements Runnable { * @return a <code>boolean</code> indicating the interrupt status * @see Thread#interrupt * @see Thread#interrupted - * + * * @since Android 1.0 */ public boolean isInterrupted() { @@ -971,7 +971,7 @@ public class Thread implements Runnable { * the receiver while it was in the <code>join()</code> call * @see Object#notifyAll * @see java.lang.ThreadDeath - * + * * @since Android 1.0 */ public final void join() throws InterruptedException { @@ -997,7 +997,7 @@ public class Thread implements Runnable { * the receiver while it was in the <code>join()</code> call * @see Object#notifyAll * @see java.lang.ThreadDeath - * + * * @since Android 1.0 */ public final void join(long millis) throws InterruptedException { @@ -1015,7 +1015,7 @@ public class Thread implements Runnable { * the receiver while it was in the <code>join()</code> call * @see Object#notifyAll * @see java.lang.ThreadDeath - * + * * @since Android 1.0 */ public final void join(long millis, int nanos) throws InterruptedException { @@ -1067,12 +1067,12 @@ public class Thread implements Runnable { * suspended, or suspended and already resumed. If the receiver is * suspended, however, makes it resume to the point where it was when it was * suspended. - * + * * @throws SecurityException * if <code>checkAccess()</code> fails with a SecurityException * @see Thread#suspend() * @deprecated Used with deprecated method {@link Thread#suspend} - * + * * @since Android 1.0 */ @Deprecated @@ -1090,7 +1090,7 @@ public class Thread implements Runnable { * holds. If no Runnable is set, does nothing. * * @see Thread#start - * + * * @since Android 1.0 */ public void run() { @@ -1111,7 +1111,7 @@ public class Thread implements Runnable { * checkPermission call. * @see java.lang.ClassLoader * @see #getContextClassLoader() - * + * * @since Android 1.0 */ public void setContextClassLoader(ClassLoader cl) { @@ -1126,13 +1126,13 @@ public class Thread implements Runnable { /** * Set if the receiver is a daemon Thread or not. This can only be done * before the Thread starts running. - * + * * @param isDaemon * indicates whether the Thread should be daemon or not * @throws SecurityException * if <code>checkAccess()</code> fails with a SecurityException * @see Thread#isDaemon - * + * * @since Android 1.0 */ public final void setDaemon(boolean isDaemon) { @@ -1156,13 +1156,13 @@ public class Thread implements Runnable { * The <code>RuntimePermission("setDefaultUncaughtExceptionHandler")</code> * is checked prior to setting the handler. * </p> - * + * * @param handler * The handler to set or <code>null</code>. * @throws SecurityException * if the current SecurityManager fails the checkPermission * call. - * + * * @since Android 1.0 */ public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) { @@ -1197,7 +1197,7 @@ public class Thread implements Runnable { * @throws SecurityException if <code>checkAccess()</code> fails with a * SecurityException * @see Thread#getName - * + * * @since Android 1.0 */ public final void setName(String threadName) { @@ -1220,7 +1220,7 @@ public class Thread implements Runnable { * be the parameter that was passed - it will depend on the receiver's * ThreadGroup. The priority cannot be set to be higher than the receiver's * ThreadGroup's maxPriority(). - * + * * @param priority * new priority for the Thread * @throws SecurityException @@ -1229,7 +1229,7 @@ public class Thread implements Runnable { * if the new priority is greater than Thread.MAX_PRIORITY or * less than Thread.MIN_PRIORITY * @see Thread#getPriority - * + * * @since Android 1.0 */ public final void setPriority(int priority) { @@ -1256,12 +1256,12 @@ public class Thread implements Runnable { * Sets the uncaught exception handler. This handler is invoked in case this * Thread dies due to an unhandled exception. * </p> - * + * * @param handler * The handler to set or <code>null</code>. * @throws SecurityException * if the current SecurityManager fails the checkAccess call. - * + * * @since Android 1.0 */ public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) { @@ -1274,14 +1274,14 @@ public class Thread implements Runnable { * Causes the thread which sent this message to sleep for the given interval * of time (given in milliseconds). The precision is not guaranteed - the * Thread may sleep more or less than requested. - * + * * @param time * The time to sleep in milliseconds. * @throws InterruptedException * if <code>interrupt()</code> was called for this Thread while * it was sleeping * @see Thread#interrupt() - * + * * @since Android 1.0 */ public static void sleep(long time) throws InterruptedException { @@ -1292,7 +1292,7 @@ public class Thread implements Runnable { * Causes the thread which sent this message to sleep for the given interval * of time (given in milliseconds and nanoseconds). The precision is not * guaranteed - the Thread may sleep more or less than requested. - * + * * @param millis * The time to sleep in milliseconds. * @param nanos @@ -1301,7 +1301,7 @@ public class Thread implements Runnable { * if <code>interrupt()</code> was called for this Thread while * it was sleeping * @see Thread#interrupt() - * + * * @since Android 1.0 */ public static void sleep(long millis, int nanos) throws InterruptedException { @@ -1314,9 +1314,9 @@ public class Thread implements Runnable { * Thread calling <code>start()</code>). * * @throws IllegalThreadStateException if the Thread has been started before - * + * * @see Thread#run - * + * * @since Android 1.0 */ public synchronized void start() { @@ -1338,7 +1338,7 @@ public class Thread implements Runnable { * SecurityException * @deprecated because stopping a thread in this manner is unsafe and can * leave your application and the VM in an unpredictable state. - * + * * @since Android 1.0 */ @Deprecated @@ -1359,7 +1359,7 @@ public class Thread implements Runnable { * <code>null</code> * @deprecated because stopping a thread in this manner is unsafe and can * leave your application and the VM in an unpredictable state. - * + * * @since Android 1.0 */ @Deprecated @@ -1388,12 +1388,12 @@ public class Thread implements Runnable { * resume()</code> is sent to it. Suspend requests are not queued, which * means that N requests are equivalent to just one - only one resume * request is needed in this case. - * + * * @throws SecurityException * if <code>checkAccess()</code> fails with a SecurityException * @see Thread#resume() * @deprecated May cause deadlocks. - * + * * @since Android 1.0 */ @Deprecated @@ -1409,9 +1409,9 @@ public class Thread implements Runnable { /** * Returns a string containing a concise, human-readable description of the * Thread. It includes the Thread's name, priority, and group name. - * + * * @return a printable representation for the receiver. - * + * * @since Android 1.0 */ @Override @@ -1422,7 +1422,7 @@ public class Thread implements Runnable { /** * Causes the calling Thread to yield execution time to another Thread that * is ready to run. The actual scheduling is implementation-dependent. - * + * * @since Android 1.0 */ public static void yield() { @@ -1436,7 +1436,7 @@ public class Thread implements Runnable { * @param object the object to test for the monitor lock * @return true if the current thread has a monitor lock on the specified * object; false otherwise - * + * * @since Android 1.0 */ public static boolean holdsLock(Object object) { @@ -1448,7 +1448,7 @@ public class Thread implements Runnable { * terminated by an uncaught exception. Upon such termination, the handler * is notified of the terminating thread and causal exception. If there is * no explicit handler set then the thread's group is the default handler. - * + * * @since Android 1.0 */ public static interface UncaughtExceptionHandler { @@ -1459,7 +1459,7 @@ public class Thread implements Runnable { * * @param thread the thread that has an uncaught exception * @param ex the exception that was thrown - * + * * @since Android 1.0 */ void uncaughtException(Thread thread, Throwable ex); @@ -1482,7 +1482,7 @@ public class Thread implements Runnable { parkState = ParkState.PREEMPTIVELY_UNPARKED; return; } - + synchronized (vmt) { switch (parkState) { case ParkState.PREEMPTIVELY_UNPARKED: { @@ -1506,12 +1506,12 @@ public class Thread implements Runnable { } } } - + /** * Implementation of <code>parkFor()</code>. See {@link LangAccessImpl}. * This method must only be called when <code>this</code> is the current * thread. - * + * * @param nanos number of nanoseconds to park for */ /*package*/ void parkFor(long nanos) { @@ -1521,7 +1521,7 @@ public class Thread implements Runnable { // Running threads should always have an associated vmThread. throw new AssertionError(); } - + synchronized (vmt) { switch (parkState) { case ParkState.PREEMPTIVELY_UNPARKED: { @@ -1545,7 +1545,7 @@ public class Thread implements Runnable { */ if (parkState == ParkState.PARKED) { parkState = ParkState.UNPARKED; - } + } } break; } @@ -1553,7 +1553,7 @@ public class Thread implements Runnable { throw new AssertionError( "shouldn't happen: attempt to repark"); } - } + } } } @@ -1561,7 +1561,7 @@ public class Thread implements Runnable { * Implementation of <code>parkUntil()</code>. See {@link LangAccessImpl}. * This method must only be called when <code>this</code> is the current * thread. - * + * * @param time absolute milliseconds since the epoch to park until */ /*package*/ void parkUntil(long time) { @@ -1571,7 +1571,7 @@ public class Thread implements Runnable { // Running threads should always have an associated vmThread. throw new AssertionError(); } - + synchronized (vmt) { /* * Note: This conflates the two time bases of "wall clock" diff --git a/luni/src/main/java/java/io/BufferedInputStream.java b/luni/src/main/java/java/io/BufferedInputStream.java index 0b9afc3..22379dd 100644 --- a/luni/src/main/java/java/io/BufferedInputStream.java +++ b/luni/src/main/java/java/io/BufferedInputStream.java @@ -30,68 +30,49 @@ import java.util.logging.Logger; * drawback is that 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> * BufferedInputStream buf = new BufferedInputStream(new FileInputStream("file.java")); * </pre> - * + * * @see BufferedOutputStream - * - * @since Android 1.0 */ public class BufferedInputStream extends FilterInputStream { - // BEGIN android-changed - // The address of the buffer should not be cached in a register. - // This was changed to be more close to the RI. /** * The buffer containing the current bytes read from the target InputStream. - * - * @since Android 1.0 */ protected volatile byte[] buf; - // END android-changed /** * The total number of bytes inside the byte array {@code buf}. - * - * @since Android 1.0 */ protected int count; /** * The current limit, which when passed, invalidates the current mark. - * - * @since Android 1.0 */ protected int marklimit; /** * The currently marked position. -1 indicates no mark has been set or the * mark has been invalidated. - * - * @since Android 1.0 */ protected int markpos = -1; /** * The current position within the byte array {@code buf}. - * - * @since Android 1.0 */ protected int pos; - private boolean closed = false; - /** * Constructs a new {@code BufferedInputStream} on the {@link InputStream} * {@code in}. The default buffer size (8 KB) is allocated and all reads * can now be filtered through this stream. - * + * * @param in * the InputStream the buffer reads from. - * @since Android 1.0 */ public BufferedInputStream(InputStream in) { super(in); @@ -116,14 +97,13 @@ public class BufferedInputStream extends FilterInputStream { * Constructs a new {@code BufferedInputStream} on the {@link InputStream} * {@code in}. The buffer size is specified by the parameter {@code size} * and all reads are now filtered through this stream. - * + * * @param in * the input stream the buffer reads from. * @param size * the size of buffer to allocate. * @throws IllegalArgumentException * if {@code size < 0}. - * @since Android 1.0 */ public BufferedInputStream(InputStream in, int size) { super(in); @@ -138,43 +118,43 @@ public class BufferedInputStream extends FilterInputStream { * Returns the number of bytes that are available before this stream will * block. This method returns the number of bytes available in the buffer * plus those available in the source stream. - * + * * @return the number of bytes available before blocking. * @throws IOException * if this stream is closed. - * @since Android 1.0 */ @Override public synchronized int available() throws IOException { - if (buf == null) { + InputStream localIn = in; // 'in' could be invalidated by close() + if (buf == null || localIn == null) { // K0059=Stream is closed throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ } - return count - pos + in.available(); + return count - pos + localIn.available(); } /** * Closes this stream. The source stream is closed and any resources * associated with it are released. - * + * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ @Override - public synchronized void close() throws IOException { - if (null != in) { - super.close(); - in = null; - } + public void close() throws IOException { buf = null; - closed = true; + InputStream localIn = in; + in = null; + if (localIn != null) { + localIn.close(); + } } - private int fillbuf() throws IOException { + private int fillbuf(InputStream localIn, byte[] localBuf) + throws IOException { if (markpos == -1 || (pos - markpos >= marklimit)) { /* Mark position not set or exceeded readlimit */ - int result = in.read(buf); + int result = localIn.read(localBuf); if (result > 0) { markpos = -1; pos = 0; @@ -182,22 +162,25 @@ public class BufferedInputStream extends FilterInputStream { } return result; } - if (markpos == 0 && marklimit > buf.length) { - /* Increase buffer size to accomodate the readlimit */ - int newLength = buf.length * 2; + if (markpos == 0 && marklimit > localBuf.length) { + /* Increase buffer size to accommodate the readlimit */ + int newLength = localBuf.length * 2; if (newLength > marklimit) { newLength = marklimit; } byte[] newbuf = new byte[newLength]; - System.arraycopy(buf, 0, newbuf, 0, buf.length); - buf = newbuf; + System.arraycopy(localBuf, 0, newbuf, 0, localBuf.length); + // Reassign buf, which will invalidate any local references + // FIXME: what if buf was null? + localBuf = buf = newbuf; } else if (markpos > 0) { - System.arraycopy(buf, markpos, buf, 0, buf.length - markpos); + System.arraycopy(localBuf, markpos, localBuf, 0, localBuf.length + - markpos); } /* Set the new position and mark position */ pos -= markpos; count = markpos = 0; - int bytesread = in.read(buf, pos, buf.length - pos); + int bytesread = localIn.read(localBuf, pos, localBuf.length - pos); count = bytesread <= 0 ? pos : pos + bytesread; return bytesread; } @@ -209,12 +192,11 @@ public class BufferedInputStream extends FilterInputStream { * position if {@code readlimit} has not been surpassed. The underlying * buffer may be increased in size to allow {@code readlimit} number of * bytes to be supported. - * + * * @param readlimit * the number of bytes that can be read before the mark is * invalidated. * @see #reset() - * @since Android 1.0 */ @Override public synchronized void mark(int readlimit) { @@ -225,11 +207,10 @@ public class BufferedInputStream extends FilterInputStream { /** * Indicates whether {@code BufferedInputStream} supports the {@code mark()} * and {@code reset()} methods. - * + * * @return {@code true} for BufferedInputStreams. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -241,28 +222,39 @@ public class BufferedInputStream extends FilterInputStream { * range from 0 to 255. Returns -1 if the end of the source string has been * reached. If the internal buffer does not contain any available bytes then * it is filled from the source stream and the first byte is returned. - * + * * @return the byte read or -1 if the end of the source stream has been * reached. * @throws IOException * if this stream is closed or another IOException occurs. - * @since Android 1.0 */ @Override public synchronized int read() throws IOException { - if (in == null) { + // Use local refs since buf and in may be invalidated by an + // unsynchronized close() + byte[] localBuf = buf; + InputStream localIn = in; + if (localBuf == null || localIn == null) { // K0059=Stream is closed throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ } /* Are there buffered bytes available? */ - if (pos >= count && fillbuf() == -1) { + if (pos >= count && fillbuf(localIn, localBuf) == -1) { return -1; /* no, fill buffer */ } + // localBuf may have been invalidated by fillbuf + if (localBuf != buf) { + localBuf = buf; + if (localBuf == null) { + // K0059=Stream is closed + throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ + } + } /* Did filling the buffer fail with -1 (EOF)? */ if (count - pos > 0) { - return buf[pos++] & 0xFF; + return localBuf[pos++] & 0xFF; } return -1; } @@ -275,7 +267,7 @@ public class BufferedInputStream extends FilterInputStream { * mark has not been set and the requested number of bytes is larger than * the receiver's buffer size, this implementation bypasses the buffer and * simply places the results directly into {@code buffer}. - * + * * @param buffer * the byte array in which to store the bytes read. * @param offset @@ -291,12 +283,14 @@ public class BufferedInputStream extends FilterInputStream { * @throws IOException * if the stream is already closed or another IOException * occurs. - * @since Android 1.0 */ @Override public synchronized int read(byte[] buffer, int offset, int length) throws IOException { - if (closed) { + // Use local ref since buf may be invalidated by an unsynchronized + // close() + byte[] localBuf = buf; + if (localBuf == null) { // K0059=Stream is closed throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ } @@ -316,7 +310,9 @@ public class BufferedInputStream extends FilterInputStream { if (length == 0) { return 0; } - if (null == buf) { + InputStream localIn = in; + if (localIn == null) { + // K0059=Stream is closed throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ } @@ -324,9 +320,9 @@ public class BufferedInputStream extends FilterInputStream { if (pos < count) { /* There are bytes available in the buffer. */ int copylength = count - pos >= length ? length : count - pos; - System.arraycopy(buf, pos, buffer, offset, copylength); + System.arraycopy(localBuf, pos, buffer, offset, copylength); pos += copylength; - if (copylength == length || in.available() == 0) { + if (copylength == length || localIn.available() == 0) { return copylength; } offset += copylength; @@ -341,24 +337,33 @@ public class BufferedInputStream extends FilterInputStream { * If we're not marked and the required size is greater than the * buffer, simply read the bytes directly bypassing the buffer. */ - if (markpos == -1 && required >= buf.length) { - read = in.read(buffer, offset, required); + if (markpos == -1 && required >= localBuf.length) { + read = localIn.read(buffer, offset, required); if (read == -1) { return required == length ? -1 : length - required; } } else { - if (fillbuf() == -1) { + if (fillbuf(localIn, localBuf) == -1) { return required == length ? -1 : length - required; } + // localBuf may have been invalidated by fillbuf + if (localBuf != buf) { + localBuf = buf; + if (localBuf == null) { + // K0059=Stream is closed + throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ + } + } + read = count - pos >= required ? required : count - pos; - System.arraycopy(buf, pos, buffer, offset, read); + System.arraycopy(localBuf, pos, buffer, offset, read); pos += read; } required -= read; if (required == 0) { return length; } - if (in.available() == 0) { + if (localIn.available() == 0) { return length - required; } offset += read; @@ -367,13 +372,12 @@ public class BufferedInputStream extends FilterInputStream { /** * Resets this stream to the last marked location. - * + * * @throws IOException * if this stream is closed, no mark has been set or the mark is * no longer valid because more than {@code readlimit} bytes * have been read since setting the mark. * @see #mark(int) - * @since Android 1.0 */ @Override public synchronized void reset() throws IOException { @@ -383,7 +387,7 @@ public class BufferedInputStream extends FilterInputStream { * so it is preferable to avoid loading up the whole big set of * messages just for these cases. */ - if (closed) { + if (buf == null) { throw new IOException("Stream is closed"); } if (-1 == markpos) { @@ -397,24 +401,31 @@ public class BufferedInputStream extends FilterInputStream { * Skips {@code amount} number of bytes in this stream. Subsequent * {@code read()}'s will not return these bytes unless {@code reset()} is * used. - * + * * @param amount * the number of bytes to skip. {@code skip} does nothing and * returns 0 if {@code amount} is less than zero. * @return the number of bytes actually skipped. * @throws IOException * if this stream is closed or another IOException occurs. - * @since Android 1.0 */ @Override public synchronized long skip(long amount) throws IOException { - if (null == in) { + // Use local refs since buf and in may be invalidated by an + // unsynchronized close() + byte[] localBuf = buf; + InputStream localIn = in; + if (localBuf == null) { // K0059=Stream is closed throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ } if (amount < 1) { return 0; } + if (localIn == null) { + // K0059=Stream is closed + throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$ + } if (count - pos >= amount) { pos += amount; @@ -425,7 +436,7 @@ public class BufferedInputStream extends FilterInputStream { if (markpos != -1) { if (amount <= marklimit) { - if (fillbuf() == -1) { + if (fillbuf(localIn, localBuf) == -1) { return read; } if (count - pos >= amount - read) { @@ -437,9 +448,7 @@ public class BufferedInputStream extends FilterInputStream { pos = count; return read; } - markpos = -1; } - return read + in.skip(amount - read); + return read + localIn.skip(amount - read); } } - diff --git a/luni/src/main/java/java/io/BufferedOutputStream.java b/luni/src/main/java/java/io/BufferedOutputStream.java index 835d13f..6d52dee 100644 --- a/luni/src/main/java/java/io/BufferedOutputStream.java +++ b/luni/src/main/java/java/io/BufferedOutputStream.java @@ -30,40 +30,33 @@ import java.util.logging.Logger; * drawback is that some extra space is required to hold the buffer and that * copying takes place when flushing that buffer, but this is usually outweighed * by the performance benefits. - * + * * <p/>A typical application pattern for the class looks like this:<p/> - * + * * <pre> * BufferedOutputStream buf = new BufferedOutputStream(new FileOutputStream("file.java")); * </pre> - * + * * @see BufferedInputStream - * - * @since Android 1.0 */ public class BufferedOutputStream extends FilterOutputStream { /** * The buffer containing the bytes to be written to the target stream. - * - * @since Android 1.0 */ protected byte[] buf; /** * The total number of bytes inside the byte array {@code buf}. - * - * @since Android 1.0 */ protected int count; /** * Constructs a new {@code BufferedOutputStream} on the {@link OutputStream} * {@code out}. The buffer size is set to the default value of 8 KB. - * + * * @param out * the {@code OutputStream} for which write operations are * buffered. - * @since Android 1.0 */ public BufferedOutputStream(OutputStream out) { super(out); @@ -87,14 +80,13 @@ public class BufferedOutputStream extends FilterOutputStream { /** * Constructs a new {@code BufferedOutputStream} on the {@link OutputStream} * {@code out}. The buffer size is set to {@code size}. - * + * * @param out * the output stream for which write operations are buffered. * @param size * the size of the buffer in bytes. * @throws IllegalArgumentException * if {@code size <= 0}. - * @since Android 1.0 */ public BufferedOutputStream(OutputStream out, int size) { super(out); @@ -108,17 +100,13 @@ public class BufferedOutputStream extends FilterOutputStream { /** * Flushes this stream to ensure all pending data is written out to the * target stream. In addition, the target stream is flushed. - * + * * @throws IOException * if an error occurs attempting to flush this stream. - * @since Android 1.0 */ @Override public synchronized void flush() throws IOException { - if (count > 0) { - out.write(buf, 0, count); - } - count = 0; + flushInternal(); out.flush(); } @@ -128,7 +116,7 @@ public class BufferedOutputStream extends FilterOutputStream { * bytes, they are copied in. If not, the buffered bytes plus the bytes in * {@code buffer} are written to the target stream, the target is flushed, * and the buffer is cleared. - * + * * @param buffer * the buffer to be written. * @param offset @@ -144,7 +132,8 @@ public class BufferedOutputStream extends FilterOutputStream { * if an error occurs attempting to write to this stream. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 + * @throws ArrayIndexOutOfBoundsException + * If offset or count is outside of bounds. */ @Override public synchronized void write(byte[] buffer, int offset, int length) @@ -153,6 +142,13 @@ public class BufferedOutputStream extends FilterOutputStream { // K0047=buffer is null throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$ } + + if (length >= buf.length) { + flushInternal(); + out.write(buffer, offset, length); + return; + } + // BEGIN android-changed // Exception priorities (in case of multiple errors) differ from // RI, but are spec-compliant. @@ -163,32 +159,15 @@ public class BufferedOutputStream extends FilterOutputStream { throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$ } // END android-changed - if (count == 0 && length >= buf.length) { - out.write(buffer, offset, length); - return; - } - int available = buf.length - count; - if (length < available) { - available = length; - } - if (available > 0) { - System.arraycopy(buffer, offset, buf, count, available); - count += available; - } - if (count == buf.length) { - out.write(buf, 0, buf.length); - count = 0; - if (length > available) { - offset += available; - available = length - available; - if (available >= buf.length) { - out.write(buffer, offset, available); - } else { - System.arraycopy(buffer, offset, buf, count, available); - count += available; - } - } + + // flush the internal buffer first if we have not enough space left + if (length >= (buf.length - count)) { + flushInternal(); } + + // the length is always less than (buf.length - count) here so arraycopy is safe + System.arraycopy(buffer, offset, buf, count, length); + count += length; } /** @@ -197,12 +176,11 @@ public class BufferedOutputStream extends FilterOutputStream { * copied into the buffer and the count incremented. Otherwise, the buffer * plus {@code oneByte} are written to the target stream, the target is * flushed, and the buffer is reset. - * + * * @param oneByte * the byte to be written. * @throws IOException * if an error occurs attempting to write to this stream. - * @since Android 1.0 */ @Override public synchronized void write(int oneByte) throws IOException { @@ -212,4 +190,14 @@ public class BufferedOutputStream extends FilterOutputStream { } buf[count++] = (byte) oneByte; } + + /** + * Flushes only internal buffer. + */ + private void flushInternal() throws IOException { + if (count > 0) { + out.write(buf, 0, count); + } + count = 0; + } } diff --git a/luni/src/main/java/java/io/BufferedReader.java b/luni/src/main/java/java/io/BufferedReader.java index e82e538..875840c 100644 --- a/luni/src/main/java/java/io/BufferedReader.java +++ b/luni/src/main/java/java/io/BufferedReader.java @@ -30,16 +30,15 @@ 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("file.java")); * </pre> - * + * * @see BufferedWriter - * - * @since Android 1.0 + * @since 1.1 */ public class BufferedReader extends Reader { @@ -58,10 +57,9 @@ 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. - * @since Android 1.0 */ public BufferedReader(Reader in) { super(in); @@ -87,14 +85,13 @@ 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 * the size of the buffer to allocate. * @throws IllegalArgumentException * if {@code size <= 0}. - * @since Android 1.0 */ public BufferedReader(Reader in, int size) { super(in); @@ -109,10 +106,9 @@ 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. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -158,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. */ @@ -171,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. @@ -181,7 +177,6 @@ public class BufferedReader extends Reader { * if an error occurs while setting a mark in this reader. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public void mark(int readlimit) throws IOException { @@ -200,11 +195,10 @@ 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() - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -217,12 +211,11 @@ public class BufferedReader extends Reader { * character from the buffer. If there are no characters available in the * buffer, it fills the buffer and then returns a character. It returns -1 * if there are no more characters in the source reader. - * + * * @return the character read or -1 if the end of the source reader has been * reached. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -234,6 +227,7 @@ public class BufferedReader extends Reader { if (pos < count || fillbuf() != -1) { return buf[pos++]; } + markpos = -1; return -1; } } @@ -246,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 @@ -263,7 +257,6 @@ public class BufferedReader extends Reader { * {@code buffer}. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ @Override public int read(char[] buffer, int offset, int length) throws IOException { @@ -336,13 +329,13 @@ 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. - * + * not include the newline sequence. In EBCDIC systems, a new line can also + * be represented by the {@code \u0085} (NEL) character. + * * @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 * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ public String readLine() throws IOException { synchronized (lock) { @@ -355,7 +348,10 @@ public class BufferedReader extends Reader { } for (int charPos = pos; charPos < count; charPos++) { char ch = buf[charPos]; - if (ch > '\r') { + // BEGIN android-note + // a switch statement may be more efficient + // END android-note + if ((ch > '\r') && (ch != '\u0085')) { continue; } if (ch == '\n') { @@ -370,6 +366,11 @@ 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; } } @@ -393,8 +394,11 @@ public class BufferedReader extends Reader { } } for (int charPos = pos; charPos < count; charPos++) { + // BEGIN android-note + // use a local variable for buf[charPos] and a switch statement + // END android-note if (eol == '\0') { - if ((buf[charPos] == '\n' || buf[charPos] == '\r')) { + if ((buf[charPos] == '\n' || buf[charPos] == '\r') || (buf[charPos] == '\u0085')) { eol = buf[charPos]; } } else if (eol == '\r' && (buf[charPos] == '\n')) { @@ -424,7 +428,7 @@ public class BufferedReader extends Reader { /** * Indicates whether this reader is ready to be read without blocking. - * + * * @return {@code true} if this reader will not block when {@code read} is * called, {@code false} if unknown or blocking will occur. * @throws IOException @@ -432,7 +436,6 @@ public class BufferedReader extends Reader { * @see #read() * @see #read(char[], int, int) * @see #readLine() - * @since Android 1.0 */ @Override public boolean ready() throws IOException { @@ -448,12 +451,11 @@ 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) * @see #markSupported() - * @since Android 1.0 */ @Override public void reset() throws IOException { @@ -473,7 +475,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. @@ -484,7 +486,6 @@ public class BufferedReader extends Reader { * @see #mark(int) * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public long skip(long amount) throws IOException { diff --git a/luni/src/main/java/java/io/BufferedWriter.java b/luni/src/main/java/java/io/BufferedWriter.java index 761b9c5..86949fa 100644 --- a/luni/src/main/java/java/io/BufferedWriter.java +++ b/luni/src/main/java/java/io/BufferedWriter.java @@ -33,16 +33,14 @@ 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> * BufferedWriter buf = new BufferedWriter(new FileWriter("file.java")); * </pre> - * + * * @see BufferedReader - * - * @since Android 1.0 */ public class BufferedWriter extends Writer { @@ -59,10 +57,9 @@ public class BufferedWriter extends Writer { * Constructs a new {@code BufferedWriter} with {@code out} as the writer * for which to buffer write operations. The buffer size is set to the * default value of 8 KB. - * + * * @param out * the writer for which character writing is buffered. - * @since Android 1.0 */ public BufferedWriter(Writer out) { super(out); @@ -88,14 +85,13 @@ public class BufferedWriter extends Writer { * Constructs a new {@code BufferedWriter} with {@code out} as the writer * for which to buffer write operations. The buffer size is set to {@code * size}. - * + * * @param out * the writer for which character writing is buffered. * @param size * the size of the buffer in bytes. * @throws IllegalArgumentException * if {@code size <= 0}. - * @since Android 1.0 */ public BufferedWriter(Writer out, int size) { super(out); @@ -110,16 +106,15 @@ public class BufferedWriter extends Writer { * Closes this writer. The contents of the buffer are flushed, the target * writer is closed, and the buffer is released. Only the first invocation * of close has any effect. - * + * * @throws IOException * if an error occurs while closing this writer. - * @since Android 1.0 */ @Override public void close() throws IOException { synchronized (lock) { if (!isClosed()) { - flush(); + flushInternal(); out.close(); buf = null; out = null; @@ -130,10 +125,9 @@ public class BufferedWriter extends Writer { /** * Flushes this writer. The contents of the buffer are committed to the * target writer and it is then flushed. - * + * * @throws IOException * if an error occurs while flushing this writer. - * @since Android 1.0 */ @Override public void flush() throws IOException { @@ -141,17 +135,24 @@ public class BufferedWriter extends Writer { if (isClosed()) { throw new IOException(Msg.getString("K005d")); //$NON-NLS-1$ } - if (pos > 0) { - out.write(buf, 0, pos); - } - pos = 0; + flushInternal(); out.flush(); } } /** + * Flushes the internal buffer. + */ + private void flushInternal() throws IOException { + if (pos > 0) { + out.write(buf, 0, pos); + } + pos = 0; + } + + /** * Indicates whether this writer is closed. - * + * * @return {@code true} if this writer is closed, {@code false} otherwise. */ private boolean isClosed() { @@ -162,10 +163,9 @@ public class BufferedWriter extends Writer { * Writes a newline to this writer. A newline is determined by the System * property "line.separator". The target writer may or may not be flushed * when a newline is written. - * + * * @throws IOException * if an error occurs attempting to write to this writer. - * @since Android 1.0 */ public void newLine() throws IOException { write(lineSeparator, 0, lineSeparator.length()); @@ -176,7 +176,7 @@ public class BufferedWriter extends Writer { * {@code cbuf} to this writer. If {@code count} is greater than this * writer's buffer, then the buffer is flushed and the characters are * written directly to the target writer. - * + * * @param cbuf * the array containing characters to write. * @param offset @@ -189,7 +189,6 @@ public class BufferedWriter extends Writer { * {@code cbuf}. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ @Override public void write(char[] cbuf, int offset, int count) throws IOException { @@ -243,12 +242,11 @@ public class BufferedWriter extends Writer { * Writes the character {@code oneChar} to this writer. If the buffer * gets full by writing this character, this writer is flushed. Only the * lower two bytes of the integer {@code oneChar} are written. - * + * * @param oneChar * the character to write. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ @Override public void write(int oneChar) throws IOException { @@ -270,7 +268,7 @@ public class BufferedWriter extends Writer { * then this writer is flushed and the remaining characters are written * directly to the target writer. If count is negative no characters are * written to the buffer. This differs from the behavior of the superclass. - * + * * @param str * the non-null String containing characters to write. * @param offset @@ -283,7 +281,6 @@ public class BufferedWriter extends Writer { * @throws IndexOutOfBoundsException * if {@code offset < 0} or {@code offset + count} is greater * than the length of {@code str}. - * @since Android 1.0 */ @Override public void write(String str, int offset, int count) throws IOException { diff --git a/luni/src/main/java/java/io/ByteArrayInputStream.java b/luni/src/main/java/java/io/ByteArrayInputStream.java index 1564ca5..f0b7219 100644 --- a/luni/src/main/java/java/io/ByteArrayInputStream.java +++ b/luni/src/main/java/java/io/ByteArrayInputStream.java @@ -23,48 +23,38 @@ import org.apache.harmony.luni.util.Msg; /** * A specialized {@link InputStream } for reading the contents of a byte array. - * + * * @see ByteArrayOutputStream - * - * @since Android 1.0 */ public class ByteArrayInputStream extends InputStream { /** * The {@code byte} array containing the bytes to stream over. - * - * @since Android 1.0 */ protected byte[] buf; /** * The current position within the byte array. - * - * @since Android 1.0 */ protected int pos; /** - * The current mark position. - * - * @since Android 1.0 + * The current mark position. Initially set to 0 or the <code>offset</code> + * parameter within the constructor. */ protected int mark; /** * The total number of bytes initially available in the byte array * {@code buf}. - * - * @since Android 1.0 */ protected int count; /** * Constructs a new {@code ByteArrayInputStream} on the byte array * {@code buf}. - * + * * @param buf * the byte array to stream over. - * @since Android 1.0 */ public ByteArrayInputStream(byte buf[]) { this.mark = 0; @@ -76,14 +66,13 @@ public class ByteArrayInputStream extends InputStream { * Constructs a new {@code ByteArrayInputStream} on the byte array * {@code buf} with the initial position set to {@code offset} and the * number of bytes available set to {@code offset} + {@code length}. - * + * * @param buf * the byte array to stream over. * @param offset * the initial position in {@code buf} to start streaming from. * @param length * the number of bytes available for streaming. - * @since Android 1.0 */ public ByteArrayInputStream(byte[] buf, int offset, int length) { // BEGIN android-note @@ -99,9 +88,8 @@ public class ByteArrayInputStream extends InputStream { * Returns the number of bytes that are available before this stream will * block. This method returns the number of bytes yet to be read from the * source byte array. - * + * * @return the number of bytes available before blocking. - * @since Android 1.0 */ @Override public synchronized int available() { @@ -110,10 +98,9 @@ public class ByteArrayInputStream extends InputStream { /** * Closes this stream and frees resources associated with this stream. - * + * * @throws IOException * if an I/O error occurs while closing this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -124,12 +111,11 @@ public class ByteArrayInputStream extends InputStream { * Sets a mark position in this ByteArrayInputStream. The parameter * {@code readlimit} is ignored. Sending {@code reset()} will reposition the * stream back to the marked position. - * + * * @param readlimit * ignored. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public synchronized void mark(int readlimit) { @@ -140,11 +126,10 @@ public class ByteArrayInputStream extends InputStream { * Indicates whether this stream supports the {@code mark()} and * {@code reset()} methods. Returns {@code true} since this class supports * these methods. - * + * * @return always {@code true}. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -155,9 +140,8 @@ public class ByteArrayInputStream extends InputStream { * Reads a single byte from the source byte array and returns it as an * integer in the range from 0 to 255. Returns -1 if the end of the source * array has been reached. - * + * * @return the byte read or -1 if the end of this stream has been reached. - * @since Android 1.0 */ @Override public synchronized int read() { @@ -168,7 +152,7 @@ public class ByteArrayInputStream extends InputStream { * Reads at most {@code len} bytes from this stream and stores * them in byte array {@code b} starting at {@code offset}. This * implementation reads bytes from the source byte array. - * + * * @param b * the byte array in which to store the bytes read. * @param offset @@ -183,8 +167,7 @@ public class ByteArrayInputStream extends InputStream { * {@code offset + length} is greater than the size of * {@code b}. * @throws NullPointerException - * if {@code b} is null. - * @since Android 1.0 + * if {@code b} is {@code null}. */ @Override public synchronized int read(byte[] b, int offset, int length) { @@ -222,9 +205,8 @@ public class ByteArrayInputStream extends InputStream { * Resets this stream to the last marked location. This implementation * resets the position to either the marked position, the start position * supplied in the constructor or 0 if neither has been provided. - * + * * @see #mark(int) - * @since Android 1.0 */ @Override public synchronized void reset() { @@ -236,11 +218,10 @@ public class ByteArrayInputStream extends InputStream { * {@code read()}s will not return these bytes unless {@code reset()} is * used. This implementation skips {@code count} number of bytes in the * target stream. It does nothing and returns 0 if {@code n} is negative. - * + * * @param n * the number of bytes to skip. * @return the number of bytes actually skipped. - * @since Android 1.0 */ @Override public synchronized long skip(long n) { diff --git a/luni/src/main/java/java/io/ByteArrayOutputStream.java b/luni/src/main/java/java/io/ByteArrayOutputStream.java index 8c6fa05..4d5a738 100644 --- a/luni/src/main/java/java/io/ByteArrayOutputStream.java +++ b/luni/src/main/java/java/io/ByteArrayOutputStream.java @@ -24,23 +24,17 @@ import org.apache.harmony.luni.util.Msg; * (internal) byte array. As bytes are written to this stream, the byte array * may be expanded to hold more bytes. When the writing is considered to be * finished, a copy of the byte array can be requested from the class. - * + * * @see ByteArrayInputStream - * - * @since Android 1.0 */ public class ByteArrayOutputStream extends OutputStream { /** * The byte array containing the bytes written. - * - * @since Android 1.0 */ protected byte[] buf; /** * The number of bytes written. - * - * @since Android 1.0 */ protected int count; @@ -48,8 +42,6 @@ public class ByteArrayOutputStream extends OutputStream { * Constructs a new ByteArrayOutputStream with a default size of 32 bytes. * If more than 32 bytes are written to this instance, the underlying byte * array will expand. - * - * @since Android 1.0 */ public ByteArrayOutputStream() { super(); @@ -60,13 +52,12 @@ public class ByteArrayOutputStream extends OutputStream { * Constructs a new {@code ByteArrayOutputStream} with a default size of * {@code size} bytes. If more than {@code size} bytes are written to this * instance, the underlying byte array will expand. - * + * * @param size * initial size for the underlying byte array, must be * non-negative. * @throws IllegalArgumentException * if {@code size} < 0. - * @since Android 1.0 */ public ByteArrayOutputStream(int size) { super(); @@ -79,10 +70,9 @@ public class ByteArrayOutputStream extends OutputStream { /** * Closes this stream. This releases system resources used for this stream. - * + * * @throws IOException * if an error occurs while attempting to close this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -109,8 +99,6 @@ public class ByteArrayOutputStream extends OutputStream { * Resets this stream to the beginning of the underlying byte array. All * subsequent writes will overwrite any bytes previously stored in this * stream. - * - * @since Android 1.0 */ public synchronized void reset() { count = 0; @@ -118,9 +106,8 @@ public class ByteArrayOutputStream extends OutputStream { /** * Returns the total number of bytes written to this stream so far. - * + * * @return the number of bytes written to this stream. - * @since Android 1.0 */ public int size() { return count; @@ -130,9 +117,8 @@ public class ByteArrayOutputStream extends OutputStream { * Returns the contents of this ByteArrayOutputStream as a byte array. Any * changes made to the receiver after returning will not be reflected in the * byte array returned to the caller. - * + * * @return this stream's current contents as a byte array. - * @since Android 1.0 */ public synchronized byte[] toByteArray() { byte[] newArray = new byte[count]; @@ -144,9 +130,8 @@ public class ByteArrayOutputStream extends OutputStream { * Returns the contents of this ByteArrayOutputStream as a string. Any * changes made to the receiver after returning will not be reflected in the * string returned to the caller. - * + * * @return this stream's current contents as a string. - * @since Android 1.0 */ @Override @@ -161,13 +146,12 @@ public class ByteArrayOutputStream extends OutputStream { * {@code c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))}. This method is * deprecated and either {@link #toString()} or {@link #toString(String)} * should be used. - * + * * @param hibyte * the high byte of each resulting Unicode character. * @return this stream's current contents as a string with the high byte set * to {@code hibyte}. * @deprecated Use {@link #toString()}. - * @since Android 1.0 */ @Deprecated public String toString(int hibyte) { @@ -181,14 +165,13 @@ public class ByteArrayOutputStream extends OutputStream { /** * Returns the contents of this ByteArrayOutputStream as a string converted * according to the encoding declared in {@code enc}. - * + * * @param enc * a string representing the encoding to use when translating * this stream to a string. * @return this stream's current contents as an encoded string. * @throws UnsupportedEncodingException * if the provided encoding is not supported. - * @since Android 1.0 */ public String toString(String enc) throws UnsupportedEncodingException { return new String(buf, 0, count, enc); @@ -197,18 +180,19 @@ public class ByteArrayOutputStream extends OutputStream { /** * Writes {@code count} bytes from the byte array {@code buffer} starting at * offset {@code index} to this stream. - * + * * @param buffer * the buffer to be written. * @param offset * the initial position in {@code buffer} to retrieve bytes. * @param len * the number of bytes of {@code buffer} to write. + * @throws NullPointerException + * if {@code buffer} is {@code null}. * @throws IndexOutOfBoundsException * if {@code offset < 0} or {@code len < 0}, or if * {@code offset + len} is greater than the length of * {@code buffer}. - * @since Android 1.0 */ @Override public synchronized void write(byte[] buffer, int offset, int len) { @@ -239,28 +223,26 @@ public class ByteArrayOutputStream extends OutputStream { /** * Writes the specified byte {@code oneByte} to the OutputStream. Only the * low order byte of {@code oneByte} is written. - * + * * @param oneByte * the byte to be written. - * @since Android 1.0 */ @Override public synchronized void write(int oneByte) { if (count == buf.length) { expand(1); } - buf[count++] = (byte)oneByte; + buf[count++] = (byte) oneByte; } /** * Takes the contents of this stream and writes it to the output stream * {@code out}. - * + * * @param out * an OutputStream on which to write the contents of this stream. * @throws IOException * if an error occurs while writing to {@code out}. - * @since Android 1.0 */ public synchronized void writeTo(OutputStream out) throws IOException { out.write(buf, 0, count); diff --git a/luni/src/main/java/java/io/CharArrayReader.java b/luni/src/main/java/java/io/CharArrayReader.java index 95a8826..d2757f6 100644 --- a/luni/src/main/java/java/io/CharArrayReader.java +++ b/luni/src/main/java/java/io/CharArrayReader.java @@ -21,37 +21,27 @@ import org.apache.harmony.luni.util.Msg; /** * A specialized {@link Reader} for reading the contents of a char array. - * + * * @see CharArrayWriter - * - * @since Android 1.0 */ public class CharArrayReader extends Reader { /** * The buffer for characters. - * - * @since Android 1.0 */ protected char buf[]; /** * The current buffer position. - * - * @since Android 1.0 */ protected int pos; /** * The current mark position. - * - * @since Android 1.0 */ protected int markedPos = -1; /** * The ending index of the buffer. - * - * @since Android 1.0 */ protected int count; @@ -59,10 +49,9 @@ public class CharArrayReader extends Reader { * Constructs a CharArrayReader on the char array {@code buf}. The size of * the reader is set to the length of the buffer and the object to to read * from is set to {@code buf}. - * + * * @param buf * the char array from which to read. - * @since Android 1.0 */ public CharArrayReader(char[] buf) { super(buf); @@ -74,7 +63,7 @@ public class CharArrayReader extends Reader { * Constructs a CharArrayReader on the char array {@code buf}. The size of * the reader is set to {@code length} and the start position from which to * read the buffer is set to {@code offset}. - * + * * @param buf * the char array from which to read. * @param offset @@ -84,7 +73,6 @@ public class CharArrayReader extends Reader { * @throws IllegalArgumentException * if {@code offset < 0} or {@code length < 0}, or if * {@code offset} is greater than the size of {@code buf} . - * @since Android 1.0 */ public CharArrayReader(char[] buf, int offset, int length) { super(buf); @@ -92,7 +80,7 @@ public class CharArrayReader extends Reader { // Exception priorities (in case of multiple errors) differ from // RI, but are spec-compliant. // made implicit null check explicit, - // removed redundant check, used (offset | length) < 0 instead of + // removed redundant check, used (offset | length) < 0 instead of // (offset < 0) || (length < 0) to safe one operation if (buf == null) { throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$ @@ -103,6 +91,7 @@ public class CharArrayReader extends Reader { // END android-changed this.buf = buf; this.pos = offset; + this.markedPos = offset; /* This is according to spec */ this.count = this.pos + length < buf.length ? length : buf.length; @@ -112,8 +101,6 @@ public class CharArrayReader extends Reader { * This method closes this CharArrayReader. Once it is closed, you can no * longer read from it. Only the first invocation of this method has any * effect. - * - * @since Android 1.0 */ @Override public void close() { @@ -126,7 +113,7 @@ public class CharArrayReader extends Reader { /** * Indicates whether this reader is open. - * + * * @return {@code true} if the reader is open, {@code false} otherwise. */ private boolean isOpen() { @@ -135,7 +122,7 @@ public class CharArrayReader extends Reader { /** * Indicates whether this reader is closed. - * + * * @return {@code true} if the reader is closed, {@code false} otherwise. */ private boolean isClosed() { @@ -147,12 +134,11 @@ public class CharArrayReader extends Reader { * ignored for CharArrayReaders. Calling {@code reset()} will reposition the * reader back to the marked position provided the mark has not been * invalidated. - * + * * @param readLimit * ignored for CharArrayReaders. * @throws IOException * if this reader is closed. - * @since Android 1.0 */ @Override public void mark(int readLimit) throws IOException { @@ -167,11 +153,10 @@ public class CharArrayReader extends Reader { /** * Indicates whether this reader supports the {@code mark()} and * {@code reset()} methods. - * + * * @return {@code true} for CharArrayReader. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -182,12 +167,11 @@ public class CharArrayReader extends Reader { * Reads a single character from this reader and returns it as an integer * with the two higher-order bytes set to 0. Returns -1 if no more * characters are available from this reader. - * + * * @return the character read as an int or -1 if the end of the reader has * been reached. * @throws IOException * if this reader is closed. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -207,7 +191,7 @@ public class CharArrayReader extends Reader { * stores them at {@code offset} in the character array {@code buf}. * Returns the number of characters actually read or -1 if the end of reader * was encountered. - * + * * @param buffer * the character array to store the characters read. * @param offset @@ -223,7 +207,6 @@ public class CharArrayReader extends Reader { * {@code buffer}. * @throws IOException * if this reader is closed. - * @since Android 1.0 */ @Override public int read(char[] buffer, int offset, int len) throws IOException { @@ -264,12 +247,11 @@ public class CharArrayReader extends Reader { * {@code false} if this reader may or may not block when {@code read} is * called. The implementation in CharArrayReader always returns {@code true} * even when it has been closed. - * + * * @return {@code true} if this reader will not block when {@code read} is * called, {@code false} if unknown or blocking will occur. * @throws IOException * if this reader is closed. - * @since Android 1.0 */ @Override public boolean ready() throws IOException { @@ -286,10 +268,9 @@ public class CharArrayReader extends Reader { * Invocations of {@code read()} and {@code skip()} will occur from this new * location. If this reader has not been marked, it is reset to the * beginning of the string. - * + * * @throws IOException * if this reader is closed. - * @since Android 1.0 */ @Override public void reset() throws IOException { @@ -305,13 +286,12 @@ public class CharArrayReader extends Reader { * Skips {@code count} number of characters in this reader. Subsequent * {@code read()}s will not return these characters unless {@code reset()} * is used. This method does nothing and returns 0 if {@code n} is negative. - * + * * @param n * the number of characters to skip. * @return the number of characters actually skipped. * @throws IOException * if this reader is closed. - * @since Android 1.0 */ @Override public long skip(long n) throws IOException { diff --git a/luni/src/main/java/java/io/CharArrayWriter.java b/luni/src/main/java/java/io/CharArrayWriter.java index 7e58b2b..6b3fa39 100644 --- a/luni/src/main/java/java/io/CharArrayWriter.java +++ b/luni/src/main/java/java/io/CharArrayWriter.java @@ -24,33 +24,25 @@ import org.apache.harmony.luni.util.Msg; * char array. As bytes are written to this writer, the char array may be * expanded to hold more characters. When the writing is considered to be * finished, a copy of the char array can be requested from the class. - * + * * @see CharArrayReader - * - * @since Android 1.0 */ public class CharArrayWriter extends Writer { /** * The buffer for characters. - * - * @since Android 1.0 */ protected char[] buf; /** * The ending index of the buffer. - * - * @since Android 1.0 */ protected int count; /** - * Constructs a new CharArrayWriter which has a buffer allocated with the - * default size of 32 characters. This buffer is also used as the + * Constructs a new {@code CharArrayWriter} which has a buffer allocated + * with the default size of 32 characters. This buffer is also used as the * {@code lock} to synchronize access to this writer. - * - * @since Android 1.0 */ public CharArrayWriter() { super(); @@ -59,15 +51,14 @@ public class CharArrayWriter extends Writer { } /** - * Constructs a new CharArrayWriter which has a buffer allocated with the - * size of {@code initialSize} characters. The buffer is also used as the - * {@code lock} to synchronize access to this writer. - * + * Constructs a new {@code CharArrayWriter} which has a buffer allocated + * with the size of {@code initialSize} characters. The buffer is also used + * as the {@code lock} to synchronize access to this writer. + * * @param initialSize * the initial size of this CharArrayWriters buffer. * @throws IllegalArgumentException * if {@code initialSize < 0}. - * @since Android 1.0 */ public CharArrayWriter(int initialSize) { super(); @@ -79,9 +70,7 @@ public class CharArrayWriter extends Writer { } /** - * Closes this writer. The implementation in CharArrayWriter does nothing. - * - * @since Android 1.0 + * Closes this writer. The implementation in {@code CharArrayWriter} does nothing. */ @Override public void close() { @@ -94,15 +83,14 @@ public class CharArrayWriter extends Writer { return; } - char[] newbuf = new char[buf.length + (2 * i)]; + int newLen = Math.max(2 * buf.length, count + i); + char[] newbuf = new char[newLen]; System.arraycopy(buf, 0, newbuf, 0, count); buf = newbuf; } /** - * Flushes this writer. The implementation in CharArrayWriter does nothing. - * - * @since Android 1.0 + * Flushes this writer. The implementation in {@code CharArrayWriter} does nothing. */ @Override public void flush() { @@ -113,8 +101,6 @@ public class CharArrayWriter extends Writer { * Resets this writer. The current write position is reset to the beginning * of the buffer. All written characters are lost and the size of this * writer is set to 0. - * - * @since Android 1.0 */ public void reset() { synchronized (lock) { @@ -126,9 +112,8 @@ public class CharArrayWriter extends Writer { * Returns the size of this writer, that is the number of characters it * stores. This number changes if this writer is reset or when more * characters are written to it. - * + * * @return this CharArrayWriter's current size in characters. - * @since Android 1.0 */ public int size() { synchronized (lock) { @@ -140,9 +125,8 @@ public class CharArrayWriter extends Writer { * Returns the contents of the receiver as a char array. The array returned * is a copy and any modifications made to this writer after calling this * method are not reflected in the result. - * + * * @return this CharArrayWriter's contents as a new char array. - * @since Android 1.0 */ public char[] toCharArray() { synchronized (lock) { @@ -153,12 +137,11 @@ public class CharArrayWriter extends Writer { } /** - * Returns the contents of this CharArrayWriter as a string. The string - * returned is a copy and any modifications made to this writer after + * Returns the contents of this {@code CharArrayWriter} as a string. The + * string returned is a copy and any modifications made to this writer after * calling this method are not reflected in the result. - * + * * @return this CharArrayWriters contents as a new string. - * @since Android 1.0 */ @Override public String toString() { @@ -170,7 +153,7 @@ public class CharArrayWriter extends Writer { /** * Writes {@code count} characters starting at {@code offset} in {@code c} * to this writer. - * + * * @param c * the non-null array containing characters to write. * @param offset @@ -180,7 +163,6 @@ public class CharArrayWriter extends Writer { * @throws IndexOutOfBoundsException * if {@code offset < 0} or {@code len < 0}, or if * {@code offset + len} is bigger than the size of {@code c}. - * @since Android 1.0 */ @Override public void write(char[] c, int offset, int len) { @@ -210,10 +192,9 @@ public class CharArrayWriter extends Writer { * Writes the specified character {@code oneChar} to this writer. * This implementation writes the two low order bytes of the integer * {@code oneChar} to the buffer. - * + * * @param oneChar * the character to write. - * @since Android 1.0 */ @Override public void write(int oneChar) { @@ -226,7 +207,7 @@ public class CharArrayWriter extends Writer { /** * Writes {@code count} number of characters starting at {@code offset} from * the string {@code str} to this CharArrayWriter. - * + * * @param str * the non-null string containing the characters to write. * @param offset @@ -234,12 +215,11 @@ public class CharArrayWriter extends Writer { * @param len * the number of characters to retrieve and write. * @throws NullPointerException - * if {@code str} is null. + * if {@code str} is {@code null}. * @throws StringIndexOutOfBoundsException * if {@code offset < 0} or {@code len < 0}, or if * {@code offset + len} is bigger than the length of * {@code str}. - * @since Android 1.0 */ @Override public void write(String str, int offset, int len) { @@ -264,17 +244,16 @@ public class CharArrayWriter extends Writer { } /** - * Writes the contents of this CharArrayWriter to another Writer. The output - * is all the characters that have been written to the receiver since the - * last reset or since it was created. - * + * Writes the contents of this {@code CharArrayWriter} to another {@code + * Writer}. The output is all the characters that have been written to the + * receiver since the last reset or since it was created. + * * @param out - * the non-null Writer on which to write the contents. + * the non-null {@code Writer} on which to write the contents. * @throws NullPointerException - * if {@code out} is null. + * if {@code out} is {@code null}. * @throws IOException * if an error occurs attempting to write out the contents. - * @since Android 1.0 */ public void writeTo(Writer out) throws IOException { synchronized (lock) { @@ -283,13 +262,12 @@ public class CharArrayWriter extends Writer { } /** - * Appends a char {@code c} to the CharArrayWriter. The method works the - * same way as {@code write(c)}. - * + * Appends a char {@code c} to the {@code CharArrayWriter}. The method works + * the same way as {@code write(c)}. + * * @param c * the character appended to the CharArrayWriter. * @return this CharArrayWriter. - * @since Android 1.0 */ @Override public CharArrayWriter append(char c) { @@ -298,14 +276,14 @@ public class CharArrayWriter extends Writer { } /** - * Appends a CharSequence {@code csq} to the CharArrayWriter. The method + * Appends a {@code CharSequence} to the {@code CharArrayWriter}. The method * works the same way as {@code write(csq.toString())}. If {@code csq} is - * null, then it will be substituted with the string "null". - * + * {@code null}, then it will be substituted with the string {@code "null"}. + * * @param csq - * the CharSequence appended to the CharArrayWriter, may be null. + * the {@code CharSequence} appended to the {@code + * CharArrayWriter}, may be {@code null}. * @return this CharArrayWriter. - * @since Android 1.0 */ @Override public CharArrayWriter append(CharSequence csq) { @@ -318,26 +296,27 @@ public class CharArrayWriter extends Writer { } /** - * Append a subsequence of a CharSequence {@code csq} to the - * CharArrayWriter. The first and last characters of the subsequence are - * specified by the parameters {@code start} and {@code end}. The - * CharArrayWriter.append({@code csq}) works the same way as - * {@code CharArrayWriter.write(csq.subSequence(start, end).toString)}. If - * {@code csq} is null, then it will be substituted with the string "null". - * + * Append a subsequence of a {@code CharSequence} to the {@code + * CharArrayWriter}. The first and last characters of the subsequence are + * specified by the parameters {@code start} and {@code end}. A call to + * {@code CharArrayWriter.append(csq)} works the same way as {@code + * CharArrayWriter.write(csq.subSequence(start, end).toString)}. If {@code + * csq} is {@code null}, then it will be substituted with the string {@code + * "null"}. + * * @param csq - * the CharSequence appended to the CharArrayWriter, may be null. + * the {@code CharSequence} appended to the {@code + * CharArrayWriter}, may be {@code null}. * @param start - * the index of the first character in the CharSequence appended - * to the CharArrayWriter. + * the index of the first character in the {@code CharSequence} + * appended to the {@code CharArrayWriter}. * @param end - * the index of the character after the last one in the - * CharSequence appended to the CharArrayWriter. + * the index of the character after the last one in the {@code + * CharSequence} appended to the {@code CharArrayWriter}. * @return this CharArrayWriter. * @throws IndexOutOfBoundsException * if {@code start < 0}, {@code end < 0}, {@code start > end}, * or if {@code end} is greater than the length of {@code csq}. - * @since Android 1.0 */ @Override public CharArrayWriter append(CharSequence csq, int start, int end) { diff --git a/luni/src/main/java/java/io/CharConversionException.java b/luni/src/main/java/java/io/CharConversionException.java index 2247527..97dc186 100644 --- a/luni/src/main/java/java/io/CharConversionException.java +++ b/luni/src/main/java/java/io/CharConversionException.java @@ -19,8 +19,6 @@ package java.io; /** * The top level class for character conversion exceptions. - * - * @since Android 1.0 */ public class CharConversionException extends IOException { @@ -29,8 +27,6 @@ public class CharConversionException extends IOException { /** * Constructs a new {@code CharConversionException} with its stack trace * filled in. - * - * @since Android 1.0 */ public CharConversionException() { super(); @@ -39,10 +35,9 @@ public class CharConversionException extends IOException { /** * Constructs a new {@code CharConversionException} with its stack trace and * detail message filled in. - * + * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public CharConversionException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/Closeable.java b/luni/src/main/java/java/io/Closeable.java index 015b39a..94b6bd8 100644 --- a/luni/src/main/java/java/io/Closeable.java +++ b/luni/src/main/java/java/io/Closeable.java @@ -21,18 +21,15 @@ package java.io; * are not used any longer. This usually includes all sorts of * {@link InputStream}s and {@link OutputStream}s. Calling the {@code close} * method releases resources that the object holds. - * - * @since Android 1.0 */ public interface Closeable { /** * Closes the object and release any system resources it holds. If the * object has already been closed, then invoking this method has no effect. - * + * * @throws IOException * if any error occurs when closing the object. - * @since Android 1.0 */ public void close() throws IOException; }
\ No newline at end of file diff --git a/luni/src/main/java/java/io/DataInput.java b/luni/src/main/java/java/io/DataInput.java index a199d2f..02a28d9 100644 --- a/luni/src/main/java/java/io/DataInput.java +++ b/luni/src/main/java/java/io/DataInput.java @@ -23,13 +23,12 @@ package java.io; * {@link DataOutput}. Types that can be read include byte, 16-bit short, 32-bit * int, 32-bit float, 64-bit long, 64-bit double, byte strings, and MUTF-8 * strings. - * + * * <h3>MUTF-8 (Modified UTF-8) Encoding</h3> * <p> * When encoding strings as UTF, implementations of {@code DataInput} and * {@code DataOutput} use a slightly modified form of UTF-8, hereafter referred * to as MUTF-8. This form is identical to standard UTF-8, except: - * </p> * <ul> * <li>Only the one-, two-, and three-byte encodings are used.</li> * <li>Code points in the range <code>U+10000</code> … @@ -42,12 +41,9 @@ package java.io; * further information about character encoding. MUTF-8 is actually closer to * the (relatively less well-known) encoding <a * href="http://www.unicode.org/reports/tr26/">CESU-8</a> than to UTF-8 per se. - * </p> - * + * * @see DataInputStream * @see RandomAccessFile - * - * @since Android 1.0 */ public interface DataInput { /** @@ -59,7 +55,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeBoolean(boolean) - * @since Android 1.0 */ public abstract boolean readBoolean() throws IOException; @@ -72,7 +67,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeByte(int) - * @since Android 1.0 */ public abstract byte readByte() throws IOException; @@ -85,7 +79,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeChar(int) - * @since Android 1.0 */ public abstract char readChar() throws IOException; @@ -98,7 +91,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeDouble(double) - * @since Android 1.0 */ public abstract double readDouble() throws IOException; @@ -111,7 +103,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeFloat(float) - * @since Android 1.0 */ public abstract float readFloat() throws IOException; @@ -127,7 +118,6 @@ public interface DataInput { * if an I/O error occurs while reading. * @see DataOutput#write(byte[]) * @see DataOutput#write(byte[], int, int) - * @since Android 1.0 */ public abstract void readFully(byte[] buffer) throws IOException; @@ -149,7 +139,6 @@ public interface DataInput { * if an I/O error occurs while reading. * @see DataOutput#write(byte[]) * @see DataOutput#write(byte[], int, int) - * @since Android 1.0 */ public abstract void readFully(byte[] buffer, int offset, int count) throws IOException; @@ -163,7 +152,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeInt(int) - * @since Android 1.0 */ public abstract int readInt() throws IOException; @@ -179,7 +167,6 @@ public interface DataInput { * request can be satisfied. * @throws IOException * if an I/O error occurs while reading. - * @since Android 1.0 */ public abstract String readLine() throws IOException; @@ -192,7 +179,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeLong(long) - * @since Android 1.0 */ public abstract long readLong() throws IOException; @@ -205,7 +191,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeShort(int) - * @since Android 1.0 */ public abstract short readShort() throws IOException; @@ -218,7 +203,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeByte(int) - * @since Android 1.0 */ public abstract int readUnsignedByte() throws IOException; @@ -231,7 +215,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeShort(int) - * @since Android 1.0 */ public abstract int readUnsignedShort() throws IOException; @@ -244,7 +227,6 @@ public interface DataInput { * @throws IOException * if an I/O error occurs while reading. * @see DataOutput#writeUTF(java.lang.String) - * @since Android 1.0 */ public abstract String readUTF() throws IOException; @@ -258,7 +240,6 @@ public interface DataInput { * @return the number of bytes actually skipped. * @throws IOException * if a problem occurs during skipping. - * @since Android 1.0 */ public abstract int skipBytes(int count) throws IOException; } diff --git a/luni/src/main/java/java/io/DataInputStream.java b/luni/src/main/java/java/io/DataInputStream.java index 88b10a5..42e38a2 100644 --- a/luni/src/main/java/java/io/DataInputStream.java +++ b/luni/src/main/java/java/io/DataInputStream.java @@ -21,38 +21,38 @@ import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.Util; /** - * Wraps an existing {@link InputStream} and reads typed data from it. + * Wraps an existing {@link InputStream} and reads typed data from it. * Typically, this stream has been written by a DataOutputStream. Types that can * be read include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long, * 64-bit double, byte strings, and strings encoded in * {@link DataInput modified UTF-8}. - * + * * @see DataOutputStream - * - * @since Android 1.0 */ public class DataInputStream extends FilterInputStream implements DataInput { + byte[] buff; + /** * Constructs a new DataInputStream on the InputStream {@code in}. All * reads are then filtered through this stream. Note that data read by this * stream is not in a human readable format and was most likely created by a * DataOutputStream. - * + * * @param in * the source InputStream the filter reads from. * @see DataOutputStream * @see RandomAccessFile - * @since Android 1.0 */ public DataInputStream(InputStream in) { super(in); + buff = new byte[8]; } /** * Reads bytes from this stream into the byte array {@code buffer}. Returns * the number of bytes that have been read. - * + * * @param buffer * the buffer to read bytes into. * @return the number of bytes that have been read or -1 if the end of the @@ -61,7 +61,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * if a problem occurs while reading from this stream. * @see DataOutput#write(byte[]) * @see DataOutput#write(byte[], int, int) - * @since Android 1.0 */ @Override public final int read(byte[] buffer) throws IOException { @@ -73,7 +72,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { * the byte array {@code buffer} starting at {@code offset}. Returns the * number of bytes that have been read or -1 if no bytes have been read and * the end of the stream has been reached. - * + * * @param buffer * the byte array in which to store the bytes read. * @param offset @@ -87,7 +86,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * if a problem occurs while reading from this stream. * @see DataOutput#write(byte[]) * @see DataOutput#write(byte[], int, int) - * @since Android 1.0 */ @Override public final int read(byte[] buffer, int offset, int length) @@ -97,7 +95,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { /** * Reads a boolean from this stream. - * + * * @return the next boolean value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before one byte @@ -105,7 +103,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeBoolean(boolean) - * @since Android 1.0 */ public final boolean readBoolean() throws IOException { int temp = in.read(); @@ -117,7 +114,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { /** * Reads an 8-bit byte value from this stream. - * + * * @return the next byte value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before one byte @@ -125,7 +122,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeByte(int) - * @since Android 1.0 */ public final byte readByte() throws IOException { int temp = in.read(); @@ -137,7 +133,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { /** * Reads a 16-bit character value from this stream. - * + * * @return the next char value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before two bytes @@ -145,20 +141,29 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeChar(int) - * @since Android 1.0 */ public final char readChar() throws IOException { - int b1 = in.read(); - int b2 = in.read(); - if ((b1 | b2) < 0) { + if (readToBuff(2) < 0){ throw new EOFException(); } - return (char) ((b1 << 8) + b2); + return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff)); + + } + + private int readToBuff(int count) throws IOException { + int offset = 0; + + while(offset < count) { + int bytesRead = in.read(buff, offset, count - offset); + if(bytesRead == -1) return bytesRead; + offset += bytesRead; + } + return offset; } /** * Reads a 64-bit double value from this stream. - * + * * @return the next double value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before eight @@ -166,7 +171,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeDouble(double) - * @since Android 1.0 */ public final double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); @@ -174,7 +178,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { /** * Reads a 32-bit float value from this stream. - * + * * @return the next float value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before four @@ -182,7 +186,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeFloat(float) - * @since Android 1.0 */ public final float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); @@ -192,7 +195,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { * Reads bytes from this stream into the byte array {@code buffer}. This * method will block until {@code buffer.length} number of bytes have been * read. - * + * * @param buffer * to read bytes into. * @throws EOFException @@ -202,7 +205,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * if a problem occurs while reading from this stream. * @see DataOutput#write(byte[]) * @see DataOutput#write(byte[], int, int) - * @since Android 1.0 */ public final void readFully(byte[] buffer) throws IOException { readFully(buffer, 0, buffer.length); @@ -213,7 +215,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { * buffer} starting at the position {@code offset}. This method blocks until * {@code length} bytes have been read. If {@code length} is zero, then this * method returns without reading any bytes. - * + * * @param buffer * the byte array into which the data is read. * @param offset @@ -232,7 +234,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws NullPointerException * if {@code buffer} or the source stream are null. * @see java.io.DataInput#readFully(byte[], int, int) - * @since Android 1.0 */ public final void readFully(byte[] buffer, int offset, int length) throws IOException { @@ -271,7 +272,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { /** * Reads a 32-bit integer value from this stream. - * + * * @return the next int value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before four @@ -279,25 +280,13 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeInt(int) - * @since Android 1.0 */ public final int readInt() throws IOException { - // BEGIN android-changed - byte[] buf = new byte[4]; - int nread = 0; - while (nread < 4) { - int nbytes = in.read(buf, nread, 4 - nread); - if (nbytes == -1) { - throw new EOFException(); - } - nread += nbytes; + if (readToBuff(4) < 0){ + throw new EOFException(); } - int b1 = buf[0] & 0xff; - int b2 = buf[1] & 0xff; - int b3 = buf[2] & 0xff; - int b4 = buf[3] & 0xff; - return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4); - // END android-changed + return ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) | + ((buff[2] & 0xff) << 8) | (buff[3] & 0xff); } /** @@ -305,13 +294,12 @@ public class DataInputStream extends FilterInputStream implements DataInput { * source stream. A line is represented by zero or more characters followed * by {@code '\n'}, {@code '\r'}, {@code "\r\n"} or the end of the stream. * The string does not include the newline sequence. - * + * * @return the contents of the line or {@code null} if no characters were * read before the end of the source stream has been reached. * @throws IOException * if a problem occurs while reading from this stream. * @deprecated Use {@link BufferedReader} - * @since Android 1.0 */ @Deprecated public final String readLine() throws IOException { @@ -350,7 +338,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { /** * Reads a 64-bit long value from this stream. - * + * * @return the next long value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before eight @@ -358,24 +346,22 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeLong(long) - * @since Android 1.0 */ public final long readLong() throws IOException { - int i1 = readInt(); - int b1 = in.read(); - int b2 = in.read(); - int b3 = in.read(); - int b4 = in.read(); - if ((b1 | b2 | b3 | b4) < 0) { + if (readToBuff(8) < 0){ throw new EOFException(); } - return (((long) i1) << 32) + ((long) b1 << 24) + (b2 << 16) + (b3 << 8) - + b4; + int i1 = ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) | + ((buff[2] & 0xff) << 8) | (buff[3] & 0xff); + int i2 = ((buff[4] & 0xff) << 24) | ((buff[5] & 0xff) << 16) | + ((buff[6] & 0xff) << 8) | (buff[7] & 0xff); + + return ((i1 & 0xffffffffL) << 32) | (i2 & 0xffffffffL); } /** * Reads a 16-bit short value from this stream. - * + * * @return the next short value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before two bytes @@ -383,29 +369,18 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeShort(int) - * @since Android 1.0 */ public final short readShort() throws IOException { - // BEGIN android-changed - byte[] buf = new byte[2]; - int nread = 0; - while (nread < 2) { - int nbytes = in.read(buf, nread, 2 - nread); - if (nbytes == -1) { - throw new EOFException(); - } - nread += nbytes; + if (readToBuff(2) < 0){ + throw new EOFException(); } - int b1 = buf[0] & 0xff; - int b2 = buf[1] & 0xff; - return (short) ((b1 << 8) + b2); - // END android-changed + return (short) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff)); } /** * Reads an unsigned 8-bit byte value from this stream and returns it as an * int. - * + * * @return the next unsigned byte value from the source stream. * @throws EOFException * if the end of the filtered stream has been reached before one @@ -413,7 +388,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeByte(int) - * @since Android 1.0 */ public final int readUnsignedByte() throws IOException { int temp = in.read(); @@ -426,7 +400,7 @@ public class DataInputStream extends FilterInputStream implements DataInput { /** * Reads a 16-bit unsigned short value from this stream and returns it as an * int. - * + * * @return the next unsigned short value from the source stream. * @throws EOFException * if the end of the filtered stream is reached before two bytes @@ -434,21 +408,18 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeShort(int) - * @since Android 1.0 */ public final int readUnsignedShort() throws IOException { - int b1 = in.read(); - int b2 = in.read(); - if ((b1 | b2) < 0) { + if (readToBuff(2) < 0){ throw new EOFException(); } - return ((b1 << 8) + b2); + return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff)); } /** * Reads an string encoded in {@link DataInput modified UTF-8} from this * stream. - * + * * @return the next {@link DataInput MUTF-8} encoded string read from the * source stream. * @throws EOFException if the end of the input is reached before the read @@ -456,90 +427,28 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutput#writeUTF(java.lang.String) - * @since Android 1.0 */ public final String readUTF() throws IOException { - int utfSize = readUnsignedShort(); - return decodeUTF(utfSize); + return decodeUTF(readUnsignedShort()); } - // BEGIN android-removed - // static final int MAX_BUF_SIZE = 8192; - // - // private static class CacheLock { - // } - // - // static final Object cacheLock = new CacheLock(); - // - // static boolean useShared = true; - // - // static byte[] byteBuf = new byte[0]; - // - // static char[] charBuf = new char[0]; - // END android-removed String decodeUTF(int utfSize) throws IOException { - // BEGIN android-removed - // byte[] buf; - // char[] out = null; - // boolean makeBuf = true; - // - // /* - // * Try to avoid the synchronization -- if we get a stale value for - // * useShared then there is no foul below, but those that sync on the - // * lock must see the right value. - // */ - // if (utfSize <= MAX_BUF_SIZE && useShared) { - // synchronized (cacheLock) { - // if (useShared) { - // useShared = false; - // makeBuf = false; - // } - // } - // } - // if (makeBuf) { - // buf = new byte[utfSize]; - // out = new char[utfSize]; - // } else { - // /* - // * Need to 'sample' byteBuf and charBuf before using them because - // * they are not protected by the cacheLock. They may get out of sync - // * with the static and one another, but that is ok because we - // * explicitly check and fix their length after sampling. - // */ - // buf = byteBuf; - // if (buf.length < utfSize) { - // buf = byteBuf = new byte[utfSize]; - // } - // out = charBuf; - // if (out.length < utfSize) { - // out = charBuf = new char[utfSize]; - // } - // } - // END android-removed - // BEGIN android-added + return decodeUTF(utfSize, this); + } + + private static String decodeUTF(int utfSize, DataInput in) throws IOException { byte[] buf = new byte[utfSize]; char[] out = new char[utfSize]; - // END android-added - readFully(buf, 0, utfSize); - String result; - result = Util.convertUTF8WithBuf(buf, out, 0, utfSize); - // BEGIN android-removed - // if (!makeBuf) { - // /* - // * Do not synchronize useShared on cacheLock, it will make it back - // * to main storage at some point, and no harm until it does. - // */ - // useShared = true; - // } - //END android-removed - return result; + in.readFully(buf, 0, utfSize); + + return Util.convertUTF8WithBuf(buf, out, 0, utfSize); } /** * Reads a string encoded in {@link DataInput modified UTF-8} from the * {@code DataInput} stream {@code in}. - * + * * @param in * the input stream to read from. * @return the next {@link DataInput MUTF-8} encoded string from the source @@ -547,19 +456,18 @@ public class DataInputStream extends FilterInputStream implements DataInput { * @throws IOException * if a problem occurs while reading from this stream. * @see DataOutputStream#writeUTF(java.lang.String) - * @since Android 1.0 */ public static final String readUTF(DataInput in) throws IOException { - return in.readUTF(); + return decodeUTF(in.readUnsignedShort(), in); } /** * Skips {@code count} number of bytes in this stream. Subsequent {@code * read()}s will not return these bytes unless {@code reset()} is used. - * + * * This method will not throw an {@link EOFException} if the end of the * input is reached before {@code count} bytes where skipped. - * + * * @param count * the number of bytes to skip. * @return the number of bytes actually skipped. @@ -567,7 +475,6 @@ public class DataInputStream extends FilterInputStream implements DataInput { * if a problem occurs during skipping. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ public final int skipBytes(int count) throws IOException { int skipped = 0; diff --git a/luni/src/main/java/java/io/DataOutput.java b/luni/src/main/java/java/io/DataOutput.java index d028a18..8275958 100644 --- a/luni/src/main/java/java/io/DataOutput.java +++ b/luni/src/main/java/java/io/DataOutput.java @@ -23,35 +23,29 @@ package java.io; * DataInput. Types that can be written include byte, 16-bit short, 32-bit int, * 32-bit float, 64-bit long, 64-bit double, byte strings, and {@link DataInput * MUTF-8} encoded strings. - * + * * @see DataOutputStream * @see RandomAccessFile - * - * @since Android 1.0 */ public interface DataOutput { /** * Writes the entire contents of the byte array {@code buffer} to this * stream. - * + * * @param buffer * the buffer to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readFully(byte[]) * @see DataInput#readFully(byte[], int, int) - * @since Android 1.0 */ public abstract void write(byte[] buffer) throws IOException; - // BEGIN android-note - // changed array notation to be consistent with the rest of harmony - // END android-note /** * Writes {@code count} bytes from the byte array {@code buffer} starting at * offset {@code index}. - * + * * @param buffer * the buffer to write. * @param offset @@ -62,7 +56,6 @@ public interface DataOutput { * if an I/O error occurs while writing. * @see DataInput#readFully(byte[]) * @see DataInput#readFully(byte[], int, int) - * @since Android 1.0 */ public abstract void write(byte[] buffer, int offset, int count) throws IOException; // BEGIN android-note @@ -71,51 +64,47 @@ public interface DataOutput { /** * Writes the specified 8-bit byte. - * + * * @param oneByte * the byte to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readByte() - * @since Android 1.0 */ public abstract void write(int oneByte) throws IOException; /** * Writes the specified boolean. - * + * * @param val * the boolean value to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readBoolean() - * @since Android 1.0 */ public abstract void writeBoolean(boolean val) throws IOException; /** * Writes the specified 8-bit byte. - * + * * @param val * the byte value to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readByte() * @see DataInput#readUnsignedByte() - * @since Android 1.0 */ public abstract void writeByte(int val) throws IOException; /** * Writes the low order 8-bit bytes from the specified string. - * + * * @param str * the string containing the bytes to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readFully(byte[]) * @see DataInput#readFully(byte[],int,int) - * @since Android 1.0 */ public abstract void writeBytes(String str) throws IOException; @@ -123,106 +112,95 @@ public interface DataOutput { * Writes the specified 16-bit character. Only the two least significant * bytes of the integer {@code oneByte} are written, with the higher one * written first. This represents the Unicode value of the char. - * + * * @param val * the character to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readChar() - * @since Android 1.0 */ public abstract void writeChar(int val) throws IOException; - // BEGIN android-note - // renamed parameter because it was misleading - // END android-note /** * Writes the 16-bit characters contained in {@code str}. - * + * * @param str * the string that contains the characters to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readChar() - * @since Android 1.0 */ public abstract void writeChars(String str) throws IOException; /** * Writes the specified 64-bit double. The resulting output is the eight * bytes returned by {@link Double#doubleToLongBits(double)}. - * + * * @param val * the double to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readDouble() - * @since Android 1.0 */ public abstract void writeDouble(double val) throws IOException; /** * Writes the specified 32-bit float. The resulting output is the four bytes * returned by {@link Float#floatToIntBits(float)}. - * + * * @param val * the float to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readFloat() - * @since Android 1.0 */ public abstract void writeFloat(float val) throws IOException; /** * Writes the specified 32-bit int. The resulting output is the four bytes, * highest order first, of {@code val}. - * + * * @param val * the int to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readInt() - * @since Android 1.0 */ public abstract void writeInt(int val) throws IOException; /** * Writes the specified 64-bit long. The resulting output is the eight * bytes, highest order first, of {@code val}. - * + * * @param val * the long to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readLong() - * @since Android 1.0 */ public abstract void writeLong(long val) throws IOException; /** * Writes the specified 16-bit short. Only the lower two bytes of {@code * val} are written with the higher one written first. - * + * * @param val * the short to write. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readShort() * @see DataInput#readUnsignedShort() - * @since Android 1.0 */ public abstract void writeShort(int val) throws IOException; /** * Writes the specified string encoded in {@link DataInput modified UTF-8}. - * + * * @param str * the string to write encoded in {@link DataInput modified UTF-8}. * @throws IOException * if an I/O error occurs while writing. * @see DataInput#readUTF() - * @since Android 1.0 */ public abstract void writeUTF(String str) throws IOException; } diff --git a/luni/src/main/java/java/io/DataOutputStream.java b/luni/src/main/java/java/io/DataOutputStream.java index 7f45c58..18e04a5 100644 --- a/luni/src/main/java/java/io/DataOutputStream.java +++ b/luni/src/main/java/java/io/DataOutputStream.java @@ -24,41 +24,37 @@ import org.apache.harmony.luni.util.Msg; * Typically, this stream can be read in by DataInputStream. Types that can be * written include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long, * 64-bit double, byte strings, and {@link DataInput MUTF-8} encoded strings. - * + * * @see DataInputStream - * - * @since Android 1.0 */ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * The number of bytes written out so far. - * - * @since Android 1.0 */ protected int written; + byte buff[]; /** * Constructs a new {@code DataOutputStream} on the {@code OutputStream} * {@code out}. Note that data written by this stream is not in a human * readable form but can be reconstructed by using a {@link DataInputStream} * on the resulting output. - * + * * @param out * the target stream for writing. - * @since Android 1.0 */ public DataOutputStream(OutputStream out) { super(out); + buff = new byte[8]; } /** * Flushes this stream to ensure all pending data is sent out to the target * stream. This implementation then also flushes the target stream. - * + * * @throws IOException * if an error occurs attempting to flush this stream. - * @since Android 1.0 */ @Override public void flush() throws IOException { @@ -67,9 +63,8 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Returns the total number of bytes written to the target stream so far. - * + * * @return the number of bytes written to the target stream. - * @since Android 1.0 */ public final int size() { if (written < 0) { @@ -81,7 +76,7 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Writes {@code count} bytes from the byte array {@code buffer} starting at * {@code offset} to the target stream. - * + * * @param buffer * the buffer to write to the target stream. * @param offset @@ -94,7 +89,6 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { * if {@code buffer} is {@code null}. * @see DataInputStream#readFully(byte[]) * @see DataInputStream#readFully(byte[], int, int) - * @since Android 1.0 */ @Override public void write(byte[] buffer, int offset, int count) throws IOException { @@ -111,13 +105,12 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Writes a byte to the target stream. Only the least significant byte of * the integer {@code oneByte} is written. - * + * * @param oneByte * the byte to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readByte() - * @since Android 1.0 */ @Override public void write(int oneByte) throws IOException { @@ -127,13 +120,12 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Writes a boolean to the target stream. - * + * * @param val * the boolean value to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readBoolean() - * @since Android 1.0 */ public final void writeBoolean(boolean val) throws IOException { out.write(val ? 1 : 0); @@ -143,14 +135,13 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Writes an 8-bit byte to the target stream. Only the least significant * byte of the integer {@code val} is written. - * + * * @param val * the byte value to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readByte() * @see DataInputStream#readUnsignedByte() - * @since Android 1.0 */ public final void writeByte(int val) throws IOException { out.write(val); @@ -159,14 +150,13 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Writes the low order bytes from a string to the target stream. - * + * * @param str * the string containing the bytes to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readFully(byte[]) * @see DataInputStream#readFully(byte[],int,int) - * @since Android 1.0 */ public final void writeBytes(String str) throws IOException { if (str.length() == 0) { @@ -184,31 +174,30 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { * Writes a 16-bit character to the target stream. Only the two lower bytes * of the integer {@code val} are written, with the higher one written * first. This corresponds to the Unicode value of {@code val}. - * + * * @param val * the character to write to the target stream * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readChar() - * @since Android 1.0 */ public final void writeChar(int val) throws IOException { - out.write(val >> 8); - out.write(val); + buff[0] = (byte) (val >> 8); + buff[1] = (byte) val; + out.write(buff, 0, 2); written += 2; } /** * Writes the 16-bit characters contained in {@code str} to the target * stream. - * + * * @param str * the string that contains the characters to write to this * stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readChar() - * @since Android 1.0 */ public final void writeChars(String str) throws IOException { byte newBytes[] = new byte[str.length() * 2]; @@ -224,13 +213,12 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Writes a 64-bit double to the target stream. The resulting output is the * eight bytes resulting from calling Double.doubleToLongBits(). - * + * * @param val * the double to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readDouble() - * @since Android 1.0 */ public final void writeDouble(double val) throws IOException { writeLong(Double.doubleToLongBits(val)); @@ -239,13 +227,12 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Writes a 32-bit float to the target stream. The resulting output is the * four bytes resulting from calling Float.floatToIntBits(). - * + * * @param val * the float to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readFloat() - * @since Android 1.0 */ public final void writeFloat(float val) throws IOException { writeInt(Float.floatToIntBits(val)); @@ -254,63 +241,68 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { /** * Writes a 32-bit int to the target stream. The resulting output is the * four bytes, highest order first, of {@code val}. - * + * * @param val * the int to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readInt() - * @since Android 1.0 */ public final void writeInt(int val) throws IOException { - out.write(val >> 24); - out.write(val >> 16); - out.write(val >> 8); - out.write(val); + buff[0] = (byte) (val >> 24); + buff[1] = (byte) (val >> 16); + buff[2] = (byte) (val >> 8); + buff[3] = (byte) val; + out.write(buff, 0, 4); written += 4; } /** * Writes a 64-bit long to the target stream. The resulting output is the * eight bytes, highest order first, of {@code val}. - * + * * @param val * the long to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readLong() - * @since Android 1.0 */ public final void writeLong(long val) throws IOException { - writeInt((int) (val >> 32)); - writeInt((int) val); + buff[0] = (byte) (val >> 56); + buff[1] = (byte) (val >> 48); + buff[2] = (byte) (val >> 40); + buff[3] = (byte) (val >> 32); + buff[4] = (byte) (val >> 24); + buff[5] = (byte) (val >> 16); + buff[6] = (byte) (val >> 8); + buff[7] = (byte) val; + out.write(buff, 0, 8); + written += 8; } /** * Writes the specified 16-bit short to the target stream. Only the lower * two bytes of the integer {@code val} are written, with the higher one * written first. - * + * * @param val * the short to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see DataInputStream#readShort() * @see DataInputStream#readUnsignedShort() - * @since Android 1.0 */ public final void writeShort(int val) throws IOException { - writeChar(val); + buff[0] = (byte) (val >> 8); + buff[1] = (byte) val; + out.write(buff, 0, 2); + written += 2; } - - // BEGIN android-added - static final int MAX_BUF_SIZE = 8192; - // END android-added - + /** * Writes the specified encoded in {@link DataInput modified UTF-8} to this * stream. - * + * * @param str * the string to write to the target stream encoded in * {@link DataInput modified UTF-8}. @@ -319,58 +311,14 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { * @throws UTFDataFormatException * if the encoded string is longer than 65535 bytes. * @see DataInputStream#readUTF() - * @since Android 1.0 */ public final void writeUTF(String str) throws IOException { - int length = str.length(); - // BEGIN android-changed - if (length <= MAX_BUF_SIZE / 3) { - int size = length * 3; - byte[] utfBytes = new byte[size]; - // boolean makeBuf = true; - // synchronized (DataInputStream.byteBuf) { - // if (DataInputStream.useShared) { - // DataInputStream.useShared = false; - // makeBuf = false; - // } - // } - // if (makeBuf) { - // utfBytes = new byte[size]; - // } else { - // if (DataInputStream.byteBuf.length < size) { - // DataInputStream.byteBuf = new byte[size]; - // } - // utfBytes = DataInputStream.byteBuf; - // } - int utfIndex = 0; - for (int i = 0; i < length; i++) { - int charValue = str.charAt(i); - if (charValue > 0 && charValue <= 127) { - utfBytes[utfIndex++] = (byte) charValue; - } else if (charValue <= 2047) { - utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6))); - utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue)); - } else { - utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12))); - utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6))); - utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue)); - } - } - writeShort(utfIndex); - write(utfBytes, 0, utfIndex); - // if (!makeBuf) { - // DataInputStream.useShared = true; - // } - } else { - long utfCount; - if (length <= 65535 && (utfCount = countUTFBytes(str)) <= 65535) { - writeShort((int) utfCount); - writeUTFBytes(str, utfCount); - } else { - throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$ - } + long utfCount = countUTFBytes(str); + if (utfCount > 65535) { + throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$ } - // END android-changed + writeShort((int) utfCount); + writeUTFBytes(str, utfCount); } long countUTFBytes(String str) { @@ -389,76 +337,23 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput { } void writeUTFBytes(String str, long count) throws IOException { - boolean single = true; int size = (int) count; - // BEGIN android-changed - if (count > MAX_BUF_SIZE) { - single = false; - size = MAX_BUF_SIZE; - } + int length = str.length(); byte[] utfBytes = new byte[size]; - // END android-changed - // BEGIN android-removed - // boolean makeBuf = true; - // if (DataInputStream.useShared) { - // synchronized (DataInputStream.cacheLock) { - // if (DataInputStream.useShared) { - // DataInputStream.useShared = false; - // makeBuf = false; - // } - // } - // } - // if (makeBuf) { - // utfBytes = new byte[size]; - // } else { - // // byteBuf is not protected by the cacheLock, so sample it first - // utfBytes = DataInputStream.byteBuf; - // if (utfBytes.length < size) { - // utfBytes = DataInputStream.byteBuf = new byte[size]; - // } - // } - // END android-removed - - int utfIndex = 0, i = 0, length = str.length(); - int end = length; - while (i < length) { - if (!single) { - end = i + ((utfBytes.length - utfIndex) / 3); - if (end > length) { - end = length; - } - } - for (int j = i; j < end; j++) { - int charValue = str.charAt(j); - if (charValue > 0 && charValue <= 127) { - utfBytes[utfIndex++] = (byte) charValue; - } else if (charValue <= 2047) { - utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6))); - utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue)); - } else { - utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12))); - utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6))); - utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue)); - } - } - if (single || utfIndex > utfBytes.length - 300) { - write(utfBytes, 0, utfIndex); - if (single) { - return; - } - utfIndex = 0; - } - i = end; - } - if (utfIndex > 0) { - write(utfBytes, 0, utfIndex); + int utfIndex = 0; + for (int i = 0; i < length; i++) { + int charValue = str.charAt(i); + if (charValue > 0 && charValue <= 127) { + utfBytes[utfIndex++] = (byte) charValue; + } else if (charValue <= 2047) { + utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6))); + utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue)); + } else { + utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12))); + utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6))); + utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue)); + } } - // BEGIN android-removed - // if (!makeBuf) { - // // Update the useShared flag optimistically (see DataInputStream - // // equivalent) - // DataInputStream.useShared = true; - // } - // END android-removed + write(utfBytes, 0, utfIndex); } } diff --git a/luni/src/main/java/java/io/EOFException.java b/luni/src/main/java/java/io/EOFException.java index 40beadd..7999f43 100644 --- a/luni/src/main/java/java/io/EOFException.java +++ b/luni/src/main/java/java/io/EOFException.java @@ -20,8 +20,6 @@ package java.io; /** * Thrown when a program encounters the end of a file or stream during an input * operation. - * - * @since Android 1.0 */ public class EOFException extends IOException { @@ -29,8 +27,6 @@ public class EOFException extends IOException { /** * Constructs a new {@code EOFException} with its stack trace filled in. - * - * @since Android 1.0 */ public EOFException() { super(); @@ -42,7 +38,6 @@ public class EOFException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public EOFException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/EmulatedFields.java b/luni/src/main/java/java/io/EmulatedFields.java index 4ef241d..a947a52 100644 --- a/luni/src/main/java/java/io/EmulatedFields.java +++ b/luni/src/main/java/java/io/EmulatedFields.java @@ -103,17 +103,18 @@ class EmulatedFields { } /** - * Return a boolean indicating if the field named <code>name</code> has - * been assigned a value explicitly (false) or if it still holds a default - * value for the type (true) because it hasn't been assigned to yet. + * Returns {@code true} indicating the field called {@code name} has not had + * a value explicitly assigned and that it still holds a default value for + * its type, or {@code false} indicating that the field named has been + * assigned a value explicitly. * * @param name - * a String, the name of the field to test - * @return <code>true</code> if <code>name</code> still holds its - * default value, <code>false</code> otherwise + * the name of the field to test. + * @return {@code true} if {@code name} still holds its default value, + * {@code false} otherwise * * @throws IllegalArgumentException - * If <code>name</code> is null + * if {@code name} is {@code null} */ public boolean defaulted(String name) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, null); @@ -124,23 +125,23 @@ class EmulatedFields { } /** - * Find and return an ObjectSlot that corresponds to a field named - * <code>fieldName</code> and type <code>fieldType</code>. If the field - * type <code>fieldType</code> corresponds to a primitive type, the field - * type has to match exactly or <code>null</code> is returned. If the - * field type <code>fieldType</code> corresponds to an object type, the - * field type has to be compatible in terms of assignment, or null is - * returned. If <code>fieldType</code> is <code>null</code>, no such - * compatibility checking is performed and the slot is returned. + * Finds and returns an ObjectSlot that corresponds to a field named {@code + * fieldName} and type {@code fieldType}. If the field type {@code + * fieldType} corresponds to a primitive type, the field type has to match + * exactly or {@code null} is returned. If the field type {@code fieldType} + * corresponds to an object type, the field type has to be compatible in + * terms of assignment, or null is returned. If {@code fieldType} is {@code + * null}, no such compatibility checking is performed and the slot is + * returned. * * @param fieldName - * A String, the name of the field to find + * the name of the field to find * @param fieldType - * A Class, the type of the field. This will be used to test - * compatibility. If null, no testing is done, the corresponding - * slot is returned. - * @return If there is no field with that name, or no compatible field - * (relative to <code>fieldType</code>) + * the type of the field. This will be used to test + * compatibility. If {@code null}, no testing is done, the + * corresponding slot is returned. + * @return the object slot, or {@code null} if there is no field with that + * name, or no compatible field (relative to {@code fieldType}) */ private ObjectSlot findSlot(String fieldName, Class<?> fieldType) { boolean isPrimitive = fieldType != null && fieldType.isPrimitive(); @@ -187,19 +188,19 @@ class EmulatedFields { } /** - * Find and return the byte value of a given field named <code>name</code> + * Finds and returns the byte value of a given field named {@code name} * in the receiver. If the field has not been assigned any value yet, the - * default value <code>defaultValue</code> is returned instead. + * default value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public byte get(String name, byte defaultValue) throws IllegalArgumentException { @@ -213,19 +214,19 @@ class EmulatedFields { } /** - * Find and return the char value of a given field named <code>name</code> - * in the receiver. If the field has not been assigned any value yet, the - * default value <code>defaultValue</code> is returned instead. + * Finds and returns the char value of a given field named {@code name} in the + * receiver. If the field has not been assigned any value yet, the default + * value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public char get(String name, char defaultValue) throws IllegalArgumentException { @@ -239,19 +240,19 @@ class EmulatedFields { } /** - * Find and return the double value of a given field named <code>name</code> + * Finds and returns the double value of a given field named {@code name} * in the receiver. If the field has not been assigned any value yet, the - * default value <code>defaultValue</code> is returned instead. + * default value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public double get(String name, double defaultValue) throws IllegalArgumentException { @@ -265,19 +266,19 @@ class EmulatedFields { } /** - * Find and return the float value of a given field named <code>name</code> - * in the receiver. If the field has not been assigned any value yet, the - * default value <code>defaultValue</code> is returned instead. + * Finds and returns the float value of a given field named {@code name} in + * the receiver. If the field has not been assigned any value yet, the + * default value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public float get(String name, float defaultValue) throws IllegalArgumentException { @@ -291,19 +292,19 @@ class EmulatedFields { } /** - * Find and return the int value of a given field named <code>name</code> - * in the receiver. If the field has not been assigned any value yet, the - * default value <code>defaultValue</code> is returned instead. + * Finds and returns the int value of a given field named {@code name} in the + * receiver. If the field has not been assigned any value yet, the default + * value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public int get(String name, int defaultValue) throws IllegalArgumentException { @@ -317,19 +318,19 @@ class EmulatedFields { } /** - * Find and return the long value of a given field named <code>name</code> - * in the receiver. If the field has not been assigned any value yet, the - * default value <code>defaultValue</code> is returned instead. + * Finds and returns the long value of a given field named {@code name} in the + * receiver. If the field has not been assigned any value yet, the default + * value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public long get(String name, long defaultValue) throws IllegalArgumentException { @@ -343,19 +344,19 @@ class EmulatedFields { } /** - * Find and return the Object value of a given field named <code>name</code> - * in the receiver. If the field has not been assigned any value yet, the - * default value <code>defaultValue</code> is returned instead. + * Finds and returns the Object value of a given field named {@code name} in + * the receiver. If the field has not been assigned any value yet, the + * default value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public Object get(String name, Object defaultValue) throws IllegalArgumentException { @@ -368,19 +369,19 @@ class EmulatedFields { } /** - * Find and return the short value of a given field named <code>name</code> - * in the receiver. If the field has not been assigned any value yet, the - * default value <code>defaultValue</code> is returned instead. + * Finds and returns the short value of a given field named {@code name} in + * the receiver. If the field has not been assigned any value yet, the + * default value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public short get(String name, short defaultValue) throws IllegalArgumentException { @@ -394,20 +395,19 @@ class EmulatedFields { } /** - * Find and return the boolean value of a given field named - * <code>name</code> in the receiver. If the field has not been assigned - * any value yet, the default value <code>defaultValue</code> is returned - * instead. + * Finds and returns the boolean value of a given field named {@code name} in + * the receiver. If the field has not been assigned any value yet, the + * default value {@code defaultValue} is returned instead. * * @param name - * A String, the name of the field to find + * the name of the field to find. * @param defaultValue - * Return value in case the field has not been assigned to yet. + * return value in case the field has not been assigned to yet. * @return the value of the given field if it has been assigned, the default - * value otherwise + * value otherwise. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public boolean get(String name, boolean defaultValue) throws IllegalArgumentException { @@ -421,16 +421,16 @@ class EmulatedFields { } /** - * Find and set the byte value of a given field named <code>name</code> in - * the receiver. + * Find and set the byte value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, byte value) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, Byte.TYPE); @@ -442,16 +442,16 @@ class EmulatedFields { } /** - * Find and set the char value of a given field named <code>name</code> in - * the receiver. + * Find and set the char value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, char value) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, Character.TYPE); @@ -463,16 +463,16 @@ class EmulatedFields { } /** - * Find and set the double value of a given field named <code>name</code> - * in the receiver. + * Find and set the double value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, double value) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, Double.TYPE); @@ -484,16 +484,16 @@ class EmulatedFields { } /** - * Find and set the float value of a given field named <code>name</code> - * in the receiver. + * Find and set the float value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, float value) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, Float.TYPE); @@ -505,16 +505,16 @@ class EmulatedFields { } /** - * Find and set the int value of a given field named <code>name</code> in - * the receiver. + * Find and set the int value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, int value) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, Integer.TYPE); @@ -526,16 +526,16 @@ class EmulatedFields { } /** - * Find and set the long value of a given field named <code>name</code> in - * the receiver. + * Find and set the long value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, long value) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, Long.TYPE); @@ -547,16 +547,16 @@ class EmulatedFields { } /** - * Find and set the Object value of a given field named <code>name</code> - * in the receiver. + * Find and set the Object value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, Object value) throws IllegalArgumentException { Class<?> valueClass = null; @@ -572,16 +572,16 @@ class EmulatedFields { } /** - * Find and set the short value of a given field named <code>name</code> - * in the receiver. + * Find and set the short value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, short value) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, Short.TYPE); @@ -593,16 +593,16 @@ class EmulatedFields { } /** - * Find and set the boolean value of a given field named <code>name</code> - * in the receiver. + * Find and set the boolean value of a given field named {@code name} in the + * receiver. * * @param name - * A String, the name of the field to set + * the name of the field to set. * @param value - * New value for the field. + * new value for the field. * * @throws IllegalArgumentException - * If the corresponding field can not be found. + * if the corresponding field can not be found. */ public void put(String name, boolean value) throws IllegalArgumentException { ObjectSlot slot = findSlot(name, Boolean.TYPE); diff --git a/luni/src/main/java/java/io/Externalizable.java b/luni/src/main/java/java/io/Externalizable.java index 03049eb..d07f0b7 100644 --- a/luni/src/main/java/java/io/Externalizable.java +++ b/luni/src/main/java/java/io/Externalizable.java @@ -20,8 +20,6 @@ package java.io; /** * Defines an interface for classes that want to be serializable, but have their * own binary representation. - * - * @since Android 1.0 */ public interface Externalizable extends Serializable { /** @@ -33,7 +31,6 @@ public interface Externalizable extends Serializable { * if an error occurs attempting to read from {@code input}. * @throws ClassNotFoundException * if the class of the instance being loaded cannot be found. - * @since Android 1.0 */ public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException; @@ -45,7 +42,6 @@ public interface Externalizable extends Serializable { * the ObjectOutput to write the object to. * @throws IOException * if an error occurs attempting to write to {@code output}. - * @since Android 1.0 */ public void writeExternal(ObjectOutput output) throws IOException; } diff --git a/luni/src/main/java/java/io/File.java b/luni/src/main/java/java/io/File.java index f4e8623..e34ab18 100644 --- a/luni/src/main/java/java/io/File.java +++ b/luni/src/main/java/java/io/File.java @@ -21,15 +21,11 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.security.AccessController; +import java.security.SecureRandom; import java.util.ArrayList; -// BEGIN android-added -import java.util.Collections; -// END android-added import java.util.List; -// BEGIN android-removed -// import org.apache.harmony.luni.util.DeleteOnExit; -// END android-removed +import org.apache.harmony.luni.util.DeleteOnExit; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; import org.apache.harmony.luni.util.Util; @@ -45,50 +41,39 @@ import org.apache.harmony.luni.util.Util; * <p> * When manipulating file paths, the static fields of this class may be used to * determine the platform specific separators. - * + * * @see java.io.Serializable * @see java.lang.Comparable - * - * @since Android 1.0 */ public class File implements Serializable, Comparable<File> { + private static final long serialVersionUID = 301077366599181567L; + private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + private String path; transient byte[] properPath; /** - * The system dependent file separator character. Since Android is a Unix- - * based system, this defaults to '/'. - * - * @since Android 1.0 + * The system dependent file separator character. */ public static final char separatorChar; /** * The system dependent file separator string. The initial value of this - * field is the system property "file.separator". Since Android is a Unix- - * based system, this defaults to "/". - * - * @since Android 1.0 + * field is the system property "file.separator". */ public static final String separator; /** - * The system dependent path separator character. Since Android is a Unix- - * based system, this defaults to ':'. - * - * @since Android 1.0 + * The system dependent path separator character. */ public static final char pathSeparatorChar; /** * The system dependent path separator string. The initial value of this - * field is the system property "path.separator". Since Android is a Unix- - * based system, this defaults to ':'. - * - * @since Android 1.0 + * field is the system property "path.separator". */ public static final String pathSeparator; @@ -115,14 +100,13 @@ public class File implements Serializable, Comparable<File> { /** * Constructs a new file using the specified directory and name. - * + * * @param dir * the directory where the file is stored. * @param name * the file's name. * @throws NullPointerException - * if {@code name} is null. - * @since Android 1.0 + * if {@code name} is {@code null}. */ public File(File dir, String name) { if (name == null) { @@ -137,10 +121,9 @@ public class File implements Serializable, Comparable<File> { /** * Constructs a new file using the specified path. - * + * * @param path * the path to be used for the file. - * @since Android 1.0 */ public File(String path) { // path == null check & NullPointerException thrown by fixSlashes @@ -150,14 +133,13 @@ public class File implements Serializable, Comparable<File> { /** * Constructs a new File using the specified directory path and file name, * placing a path separator between the two. - * + * * @param dirPath * the path to the directory where the file is stored. * @param name * the file's name. * @throws NullPointerException - * if {@code name} is null. - * @since Android 1.0 + * if {@code name} is {@code null}. */ public File(String dirPath, String name) { if (name == null) { @@ -175,7 +157,7 @@ public class File implements Serializable, Comparable<File> { * needs to be an absolute and hierarchical Unified Resource Identifier with * file scheme and non-empty path component, but with undefined authority, * query or fragment components. - * + * * @param uri * the Unified Resource Identifier that is used to construct this * file. @@ -183,7 +165,6 @@ public class File implements Serializable, Comparable<File> { * if {@code uri} does not comply with the conditions above. * @see #toURI * @see java.net.URI - * @since Android 1.0 */ public File(URI uri) { // check pre-conditions @@ -193,7 +174,7 @@ public class File implements Serializable, Comparable<File> { private String calculatePath(String dirPath, String name) { dirPath = fixSlashes(dirPath); - if (!name.equals("")) { //$NON-NLS-1$ + if (!name.equals(EMPTY_STRING) || dirPath.equals(EMPTY_STRING)) { // Remove all the proceeding separator chars from name name = fixSlashes(name); @@ -217,36 +198,37 @@ public class File implements Serializable, Comparable<File> { return dirPath; } + @SuppressWarnings("nls") private void checkURI(URI uri) { if (!uri.isAbsolute()) { - throw new IllegalArgumentException(Msg.getString("K031a", uri)); //$NON-NLS-1$ - } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) { //$NON-NLS-1$ - throw new IllegalArgumentException(Msg.getString("K031b", uri)); //$NON-NLS-1$ + throw new IllegalArgumentException(Msg.getString("K031a", uri)); + } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) { + throw new IllegalArgumentException(Msg.getString("K031b", uri)); } String temp = uri.getScheme(); - if (temp == null || !temp.equals("file")) { //$NON-NLS-1$ - throw new IllegalArgumentException(Msg.getString("K031c", uri)); //$NON-NLS-1$ + if (temp == null || !temp.equals("file")) { + throw new IllegalArgumentException(Msg.getString("K031c", uri)); } temp = uri.getRawPath(); if (temp == null || temp.length() == 0) { - throw new IllegalArgumentException(Msg.getString("K031d", uri)); //$NON-NLS-1$ + throw new IllegalArgumentException(Msg.getString("K031d", uri)); } if (uri.getRawAuthority() != null) { - throw new IllegalArgumentException(Msg.getString( - "K031e", new String[] { "authority", uri.toString() })); //$NON-NLS-1$ //$NON-NLS-2$ + throw new IllegalArgumentException(Msg.getString("K031e", + new String[] { "authority", uri.toString() })); } if (uri.getRawQuery() != null) { - throw new IllegalArgumentException(Msg.getString( - "K031e", new String[] { "query", uri.toString() })); //$NON-NLS-1$//$NON-NLS-2$ + throw new IllegalArgumentException(Msg.getString("K031e", + new String[] { "query", uri.toString() })); } if (uri.getRawFragment() != null) { - throw new IllegalArgumentException(Msg.getString( - "K031e", new String[] { "fragment", uri.toString() })); //$NON-NLS-1$ //$NON-NLS-2$ + throw new IllegalArgumentException(Msg.getString("K031e", + new String[] { "fragment", uri.toString() })); } } @@ -259,9 +241,8 @@ public class File implements Serializable, Comparable<File> { * file systems, each with its own platform-dependent root. Further, the * canonical pathname of any file on the system will always begin with one * of the returned file system roots. - * + * * @return the array of file system roots. - * @since Android 1.0 */ public static File[] listRoots() { byte[][] rootsList = rootsImpl(); @@ -293,7 +274,8 @@ public class File implements Serializable, Comparable<File> { char newPath[] = origPath.toCharArray(); for (int i = 0; i < length; i++) { char pathChar = newPath[i]; - if (pathChar == '\\' || pathChar == '/') { + if ((separatorChar == '\\' && pathChar == '\\') + || pathChar == '/') { /* UNC Name requires 2 leading slashes */ if ((foundSlash && i == uncIndex) || !foundSlash) { newPath[newLength++] = separatorChar; @@ -319,42 +301,40 @@ public class File implements Serializable, Comparable<File> { && (newLength > (uncIndex + 1) || (newLength == 2 && newPath[0] != separatorChar))) { newLength--; } - String tempPath = new String(newPath, 0, newLength); - // If it's the same keep it identical for SecurityManager purposes - if (!tempPath.equals(origPath)) { - return tempPath; - } - return origPath; + + return new String(newPath, 0, newLength); } /** * Indicates whether the current context is allowed to read from this file. - * + * * @return {@code true} if this file can be read, {@code false} otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * read request. - * @since Android 1.0 */ public boolean canRead() { + if (path.length() == 0) { + return false; + } SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead(path); } + byte[] pp = properPath(true); // BEGIN android-changed - return exists() && isReadableImpl(properPath(true)); + return exists() && isReadableImpl(pp); // END android-changed } /** * Indicates whether the current context is allowed to write to this file. - * + * * @return {@code true} if this file can be written, {@code false} * otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * write request. - * @since Android 1.0 */ public boolean canWrite() { SecurityManager security = System.getSecurityManager(); @@ -375,13 +355,12 @@ public class File implements Serializable, Comparable<File> { /** * Returns the relative sort ordering of the paths for this file and the * file {@code another}. The ordering is platform dependent. - * + * * @param another * a file to compare this file to * @return an int determined by comparing the two paths. Possible values are * described in the Comparable interface. * @see Comparable - * @since Android 1.0 */ public int compareTo(File another) { if (caseSensitive) { @@ -392,13 +371,12 @@ public class File implements Serializable, Comparable<File> { /** * Deletes this file. Directories must be empty before they will be deleted. - * + * * @return {@code true} if this file was deleted, {@code false} otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * request. * @see java.lang.SecurityManager#checkDelete - * @since Android 1.0 */ public boolean delete() { SecurityManager security = System.getSecurityManager(); @@ -418,13 +396,12 @@ public class File implements Serializable, Comparable<File> { /** * Schedules this file to be automatically deleted once the virtual machine - * terminates. This will only happen when the virtual machine terminates + * terminates. This will only happen when the virtual machine terminates * normally as described by the Java Language Specification section 12.9. - * + * * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * request. - * @since Android 1.0 */ public void deleteOnExit() { SecurityManager security = System.getSecurityManager(); @@ -439,12 +416,11 @@ public class File implements Serializable, Comparable<File> { /** * Compares {@code obj} to this file and returns {@code true} if they * represent the <em>same</em> object using a path specific comparison. - * + * * @param obj * the object to compare this file with. * @return {@code true} if {@code obj} is the same as this object, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object obj) { @@ -460,13 +436,13 @@ public class File implements Serializable, Comparable<File> { /** * Returns a boolean indicating whether this file can be found on the * underlying file system. - * + * * @return {@code true} if this file exists, {@code false} otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. * @see #getPath - * @since Android 1.0 + * @see java.lang.SecurityManager#checkRead(FileDescriptor) */ public boolean exists() { if (path.length() == 0) { @@ -483,22 +459,20 @@ public class File implements Serializable, Comparable<File> { /** * Returns the absolute path of this file. - * + * * @return the absolute file path. * @see java.lang.SecurityManager#checkPropertyAccess - * @since Android 1.0 */ public String getAbsolutePath() { byte[] absolute = properPath(false); - return Util.toString(absolute); + return Util.toUTF8String(absolute); } /** * Returns a new file constructed using the absolute path of this file. - * + * * @return a new file from this file's absolute path. * @see java.lang.SecurityManager#checkPropertyAccess - * @since Android 1.0 */ public File getAbsoluteFile() { return new File(this.getAbsolutePath()); @@ -513,42 +487,20 @@ public class File implements Serializable, Comparable<File> { * with a direct directory reference. If the file does not exist, * getCanonicalPath() may not resolve any references and simply returns an * absolute path name or throws an IOException. - * + * * @return the canonical path of this file. * @throws IOException * if an I/O error occurs. * @see java.lang.SecurityManager#checkPropertyAccess - * @since Android 1.0 */ public String getCanonicalPath() throws IOException { byte[] result = properPath(false); - - boolean exists = false; - byte[] pathBytes = result; - do { - byte[] linkBytes = getLinkImpl(pathBytes); - if (linkBytes == pathBytes) { - break; - } - if (linkBytes[0] == separatorChar) { - pathBytes = linkBytes; - } else { - int index = pathBytes.length - 1; - while (pathBytes[index] != separatorChar) { - index--; - } - byte[] temp = new byte[index + 1 + linkBytes.length]; - System.arraycopy(pathBytes, 0, temp, 0, index + 1); - System.arraycopy(linkBytes, 0, temp, index + 1, - linkBytes.length); - pathBytes = temp; - } - exists = existsImpl(pathBytes); - } while (exists); - if (exists) { - result = pathBytes; + if(separatorChar == '/') { + // resolve the full path first + result = resolveLink(result, result.length, false); + // resolve the parent directories + result = resolve(result); } - int numSeparators = 1; for (int i = 0; i < result.length; i++) { if (result[i] == separatorChar) { @@ -614,18 +566,104 @@ public class File implements Serializable, Comparable<File> { newResult[newLength] = 0; newResult = getCanonImpl(newResult); newLength = newResult.length; - return Util.toString(newResult, 0, newLength); + return Util.toUTF8String(newResult, 0, newLength); + } + + /* + * Resolve symbolic links in the parent directories. + */ + private byte[] resolve(byte[] newResult) throws IOException { + int last = 1, nextSize, linkSize; + byte[] linkPath = newResult, bytes; + boolean done, inPlace; + for (int i = 1; i <= newResult.length; i++) { + if (i == newResult.length || newResult[i] == separatorChar) { + done = i >= newResult.length - 1; + // if there is only one segment, do nothing + if (done && linkPath.length == 1) { + return newResult; + } + inPlace = false; + if (linkPath == newResult) { + bytes = newResult; + // if there are no symbolic links, terminate the C string + // instead of copying + if (!done) { + inPlace = true; + newResult[i] = '\0'; + } + } else { + nextSize = i - last + 1; + linkSize = linkPath.length; + if (linkPath[linkSize - 1] == separatorChar) { + linkSize--; + } + bytes = new byte[linkSize + nextSize]; + System.arraycopy(linkPath, 0, bytes, 0, linkSize); + System.arraycopy(newResult, last - 1, bytes, linkSize, + nextSize); + // the full path has already been resolved + } + if (done) { + return bytes; + } + linkPath = resolveLink(bytes, inPlace ? i : bytes.length, true); + if (inPlace) { + newResult[i] = '/'; + } + last = i + 1; + } + } + throw new InternalError(); + } + + /* + * Resolve a symbolic link. While the path resolves to an existing path, + * keep resolving. If an absolute link is found, resolve the parent + * directories if resolveAbsolute is true. + */ + private byte[] resolveLink(byte[] pathBytes, int length, + boolean resolveAbsolute) throws IOException { + boolean restart = false; + byte[] linkBytes, temp; + do { + linkBytes = getLinkImpl(pathBytes); + if (linkBytes == pathBytes) { + break; + } + if (linkBytes[0] == separatorChar) { + // link to an absolute path, if resolving absolute paths, + // resolve the parent dirs again + restart = resolveAbsolute; + pathBytes = linkBytes; + } else { + int last = length - 1; + while (pathBytes[last] != separatorChar) { + last--; + } + last++; + temp = new byte[last + linkBytes.length]; + System.arraycopy(pathBytes, 0, temp, 0, last); + System.arraycopy(linkBytes, 0, temp, last, linkBytes.length); + pathBytes = temp; + } + length = pathBytes.length; + } while (existsImpl(pathBytes)); + // resolve the parent directories + if (restart) { + return resolve(pathBytes); + } + return pathBytes; } /** * Returns a new file created using the canonical path of this file. * Equivalent to {@code new File(this.getCanonicalPath())}. - * + * * @return the new file constructed from this file's canonical path. * @throws IOException * if an I/O error occurs. * @see java.lang.SecurityManager#checkPropertyAccess - * @since Android 1.0 */ public File getCanonicalFile() throws IOException { return new File(getCanonicalPath()); @@ -635,10 +673,9 @@ public class File implements Serializable, Comparable<File> { /** * Returns the name of the file or directory represented by this file. - * + * * @return this file's name or an empty string if there is no name part in * the file's path. - * @since Android 1.0 */ public String getName() { int separatorIndex = path.lastIndexOf(separator); @@ -650,9 +687,8 @@ public class File implements Serializable, Comparable<File> { * Returns the pathname of the parent of this file. This is the path up to * but not including the last name. {@code null} is returned if there is no * parent. - * + * * @return this file's parent pathname or {@code null}. - * @since Android 1.0 */ public String getParent() { int length = path.length(), firstInPath = 0; @@ -677,9 +713,8 @@ public class File implements Serializable, Comparable<File> { * Returns a new file made from the pathname of the parent of this file. * This is the path up to but not including the last name. {@code null} is * returned when there is no parent. - * + * * @return a new file representing this file's parent or {@code null}. - * @since Android 1.0 */ public File getParentFile() { String tempParent = getParent(); @@ -691,9 +726,8 @@ public class File implements Serializable, Comparable<File> { /** * Returns the path of this file. - * + * * @return this file's path. - * @since Android 1.0 */ public String getPath() { return path; @@ -702,10 +736,9 @@ public class File implements Serializable, Comparable<File> { /** * Returns an integer hash code for the receiver. Any two objects for which * {@code equals} returns {@code true} must return the same hash code. - * + * * @return this files's hash value. * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -721,11 +754,10 @@ public class File implements Serializable, Comparable<File> { * the character '/'; on Windows it is absolute if either it starts with * '\', '/', '\\' (to represent a file server), or a letter followed by a * colon. - * + * * @return {@code true} if this file's pathname is absolute, {@code false} * otherwise. * @see #getPath - * @since Android 1.0 */ public boolean isAbsolute() { // BEGIN android-changed @@ -741,13 +773,12 @@ public class File implements Serializable, Comparable<File> { /** * Indicates if this file represents a <em>directory</em> on the * underlying file system. - * + * * @return {@code true} if this file is a directory, {@code false} * otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. - * @since Android 1.0 */ public boolean isDirectory() { if (path.length() == 0) { @@ -765,12 +796,11 @@ public class File implements Serializable, Comparable<File> { /** * Indicates if this file represents a <em>file</em> on the underlying * file system. - * + * * @return {@code true} if this file is a file, {@code false} otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. - * @since Android 1.0 */ public boolean isFile() { if (path.length() == 0) { @@ -787,16 +817,15 @@ public class File implements Serializable, Comparable<File> { /** * Returns whether or not this file is a hidden file as defined by the - * operating system. The notion of "hidden" is system-dependent. For - * Unix systems (like Android) a file is considered hidden if its name - * starts with a ".". For Windows systems there is an explicit flag in the - * file system for this purpose. - * + * operating system. The notion of "hidden" is system-dependent. For Unix + * systems a file is considered hidden if its name starts with a ".". For + * Windows systems there is an explicit flag in the file system for this + * purpose. + * * @return {@code true} if the file is hidden, {@code false} otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. - * @since Android 1.0 */ public boolean isHidden() { if (path.length() == 0) { @@ -822,12 +851,11 @@ public class File implements Serializable, Comparable<File> { /** * Returns the time when this file was last modified, measured in * milliseconds since January 1st, 1970, midnight. - * + * * @return the time when this file was last modified. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. - * @since Android 1.0 */ public long lastModified() { SecurityManager security = System.getSecurityManager(); @@ -847,7 +875,7 @@ public class File implements Serializable, Comparable<File> { /** * Sets the time this file was last modified, measured in milliseconds since * January 1st, 1970, midnight. - * + * * @param time * the last modification time for this file. * @return {@code true} if the operation is successful, {@code false} @@ -857,7 +885,6 @@ public class File implements Serializable, Comparable<File> { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies write * access to this file. - * @since Android 1.0 */ public boolean setLastModified(long time) { if (time < 0) { @@ -875,13 +902,12 @@ public class File implements Serializable, Comparable<File> { /** * Marks this file or directory to be read-only as defined by the operating * system. - * + * * @return {@code true} if the operation is successful, {@code false} * otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies write * access to this file. - * @since Android 1.0 */ public boolean setReadOnly() { SecurityManager security = System.getSecurityManager(); @@ -895,12 +921,11 @@ public class File implements Serializable, Comparable<File> { /** * Returns the length of this file in bytes. - * + * * @return the number of bytes in this file. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. - * @since Android 1.0 */ public long length() { SecurityManager security = System.getSecurityManager(); @@ -914,35 +939,42 @@ public class File implements Serializable, Comparable<File> { /** * Returns an array of strings with the file names in the directory - * represented by this file. The result is {@ null} if this file is not a - * directory. + * represented by this file. The result is {@code null} if this file is not + * a directory. * <p> * The entries {@code .} and {@code ..} representing the current and parent * directory are not returned as part of the list. - * </p> - * + * * @return an array of strings with file names or {@code null}. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. * @see #isDirectory - * @since Android 1.0 + * @see java.lang.SecurityManager#checkRead(FileDescriptor) */ public java.lang.String[] list() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead(path); } - if (!isDirectory()) { + + if (path.length() == 0) { return null; } - byte[][] implList = listImpl(properPath(true)); + + byte[] bs = properPath(true); + if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) { + return null; + } + + byte[][] implList = listImpl(bs); if (implList == null) { + // empty list return new String[0]; } String result[] = new String[implList.length]; for (int index = 0; index < implList.length; index++) { - result[index] = Util.toString(implList[index]); + result[index] = Util.toUTF8String(implList[index]); } return result; } @@ -952,13 +984,13 @@ public class File implements Serializable, Comparable<File> { * file. The result is {@code null} if this file is not a directory. The * paths of the files in the array are absolute if the path of this file is * absolute, they are relative otherwise. - * + * * @return an array of files or {@code null}. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. * @see #list - * @since Android 1.0 + * @see #isDirectory */ public File[] listFiles() { String[] tempNames = list(); @@ -982,8 +1014,7 @@ public class File implements Serializable, Comparable<File> { * <p> * The entries {@code .} and {@code ..} representing the current and parent * directories are not returned as part of the list. - * </p> - * + * * @param filter * the filter to match names against, may be {@code null}. * @return an array of files or {@code null}. @@ -991,7 +1022,9 @@ public class File implements Serializable, Comparable<File> { * if a {@code SecurityManager} is installed and it denies read * access to this file. * @see #list(FilenameFilter filter) - * @since Android 1.0 + * @see #getPath + * @see #isDirectory + * @see java.lang.SecurityManager#checkRead(FileDescriptor) */ public File[] listFiles(FilenameFilter filter) { String[] tempNames = list(filter); @@ -1014,25 +1047,33 @@ public class File implements Serializable, Comparable<File> { * <p> * The entries {@code .} and {@code ..} representing the current and parent * directories are not returned as part of the list. - * </p> - * + * * @param filter * the filter to match names against, may be {@code null}. * @return an array of files or {@code null}. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. - * @since Android 1.0 + * @see #getPath + * @see #isDirectory + * @see java.lang.SecurityManager#checkRead(FileDescriptor) */ public File[] listFiles(FileFilter filter) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead(path); } - if (!isDirectory()) { + + if (path.length() == 0) { + return null; + } + + byte[] bs = properPath(true); + if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) { return null; } - byte[][] implList = listImpl(properPath(true)); + + byte[][] implList = listImpl(bs); if (implList == null) { return new File[0]; } @@ -1056,38 +1097,46 @@ public class File implements Serializable, Comparable<File> { * <p> * The entries {@code .} and {@code ..} representing the current and parent * directories are not returned as part of the list. - * </p> - * + * * @param filter * the filter to match names against, may be {@code null}. * @return an array of files or {@code null}. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies read * access to this file. - * @since Android 1.0 + * @see #getPath + * @see #isDirectory + * @see java.lang.SecurityManager#checkRead(FileDescriptor) */ public java.lang.String[] list(FilenameFilter filter) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead(path); } - if (!isDirectory()) { + + if (path.length() == 0) { + return null; + } + + byte[] bs = properPath(true); + if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) { return null; } - byte[][] implList = listImpl(properPath(true)); + + byte[][] implList = listImpl(bs); if (implList == null) { + // empty list return new String[0]; } - java.util.Vector<String> tempResult = new java.util.Vector<String>(); + List<String> tempResult = new ArrayList<String>(); for (int index = 0; index < implList.length; index++) { String aName = Util.toString(implList[index]); if (filter == null || filter.accept(this, aName)) { - tempResult.addElement(aName); + tempResult.add(aName); } } - String[] result = new String[tempResult.size()]; - tempResult.copyInto(result); - return result; + + return tempResult.toArray(new String[tempResult.size()]); } private synchronized static native byte[][] listImpl(byte[] path); @@ -1095,14 +1144,13 @@ public class File implements Serializable, Comparable<File> { /** * Creates the directory named by the trailing filename of this file. Does * not create the complete path required to create this directory. - * + * * @return {@code true} if the directory has been created, {@code false} * otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies write * access for this file. * @see #mkdirs - * @since Android 1.0 */ public boolean mkdir() { SecurityManager security = System.getSecurityManager(); @@ -1117,7 +1165,7 @@ public class File implements Serializable, Comparable<File> { /** * Creates the directory named by the trailing filename of this file, * including the complete directory path required to create this directory. - * + * * @return {@code true} if the necessary directories have been created, * {@code false} if the target directory already exists or one of * the directories can not be created. @@ -1125,7 +1173,6 @@ public class File implements Serializable, Comparable<File> { * if a {@code SecurityManager} is installed and it denies write * access for this file. * @see #mkdir - * @since Android 1.0 */ public boolean mkdirs() { /* If the terminal directory already exists, answer false */ @@ -1151,7 +1198,7 @@ public class File implements Serializable, Comparable<File> { /** * Creates a new, empty file on the file system according to the path * information stored in this file. - * + * * @return {@code true} if the file has been created, {@code false} if it * already exists. * @throws IOException @@ -1160,7 +1207,6 @@ public class File implements Serializable, Comparable<File> { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies write * access for this file. - * @since Android 1.0 */ public boolean createNewFile() throws IOException { SecurityManager security = System.getSecurityManager(); @@ -1215,10 +1261,11 @@ public class File implements Serializable, Comparable<File> { /** * Creates an empty temporary file using the given prefix and suffix as part - * of the file name. If suffix is null, {@code .tmp} is used. This method - * is a convenience method that calls {@link #createTempFile(String, String, - * File)} with the third argument being {@code null}. - * + * of the file name. If suffix is {@code null}, {@code .tmp} is used. This + * method is a convenience method that calls + * {@link #createTempFile(String, String, File)} with the third argument + * being {@code null}. + * * @param prefix * the prefix to the temp file name. * @param suffix @@ -1226,7 +1273,6 @@ public class File implements Serializable, Comparable<File> { * @return the temporary file. * @throws IOException * if an error occurs when writing the file. - * @since Android 1.0 */ public static File createTempFile(String prefix, String suffix) throws IOException { @@ -1236,7 +1282,7 @@ public class File implements Serializable, Comparable<File> { /** * Creates an empty temporary file in the given directory using the given * prefix and suffix as part of the file name. - * + * * @param prefix * the prefix to the temp file name. * @param suffix @@ -1246,26 +1292,30 @@ public class File implements Serializable, Comparable<File> { * {@code null} for the default location for temporary files, * which is taken from the "java.io.tmpdir" system property. It * may be necessary to set this property to an existing, writable - * directory for this method to work properly. + * directory for this method to work properly. * @return the temporary file. * @throws IllegalArgumentException * if the length of {@code prefix} is less than 3. * @throws IOException * if an error occurs when writing the file. - * @since Android 1.0 */ + @SuppressWarnings("nls") public static File createTempFile(String prefix, String suffix, File directory) throws IOException { // Force a prefix null check first if (prefix.length() < 3) { - throw new IllegalArgumentException(Msg.getString("K006b")); //$NON-NLS-1$ - } - String newSuffix = suffix == null ? ".tmp" : suffix; //$NON-NLS-1$ - String tmpDir = "."; //$NON-NLS-1$ - tmpDir = AccessController.doPrivileged(new PriviAction<String>( - "java.io.tmpdir", ".")); //$NON-NLS-1$//$NON-NLS-2$ - File result, tmpDirFile = directory == null ? new File(tmpDir) - : directory; + throw new IllegalArgumentException(Msg.getString("K006b")); + } + String newSuffix = suffix == null ? ".tmp" : suffix; + File tmpDirFile; + if (directory == null) { + String tmpDir = AccessController.doPrivileged( + new PriviAction<String>("java.io.tmpdir", ".")); + tmpDirFile = new File(tmpDir); + } else { + tmpDirFile = directory; + } + File result; do { result = genTempFile(prefix, newSuffix, tmpDirFile); } while (!result.createNewFile()); @@ -1274,7 +1324,7 @@ public class File implements Serializable, Comparable<File> { private static File genTempFile(String prefix, String suffix, File directory) { if (counter == 0) { - int newInt = new java.util.Random().nextInt(); + int newInt = new SecureRandom().nextInt(); counter = ((newInt / 65535) & 0xFFFF) + 0x2710; } StringBuilder newName = new StringBuilder(); @@ -1290,7 +1340,7 @@ public class File implements Serializable, Comparable<File> { * Returns a string representing the proper path for this file. If this file * path is absolute, the user.dir property is not prepended, otherwise it * is. - * + * * @param internal * is user.dir internal. * @return the proper path. @@ -1311,7 +1361,7 @@ public class File implements Serializable, Comparable<File> { userdir = System.getProperty("user.dir"); //$NON-NLS-1$ } if (path.length() == 0) { - return properPath = Util.getBytes(userdir); + return properPath = Util.getUTF8Bytes(userdir); } int length = userdir.length(); if (length > 0 && userdir.charAt(length - 1) == separatorChar) { @@ -1328,14 +1378,13 @@ public class File implements Serializable, Comparable<File> { /** * Renames this file to the name represented by the {@code dest} file. This * works for both normal files and directories. - * + * * @param dest * the file containing the new name. * @return {@code true} if the File was renamed, {@code false} otherwise. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies write * access for this file or the {@code dest} file. - * @since Android 1.0 */ public boolean renameTo(java.io.File dest) { SecurityManager security = System.getSecurityManager(); @@ -1351,9 +1400,8 @@ public class File implements Serializable, Comparable<File> { /** * Returns a string containing a concise, human-readable description of this * file. - * + * * @return a printable representation of this file. - * @since Android 1.0 */ @Override public String toString() { @@ -1364,22 +1412,22 @@ public class File implements Serializable, Comparable<File> { * Returns a Uniform Resource Identifier for this file. The URI is system * dependent and may not be transferable between different operating / file * systems. - * + * * @return an URI for this file. - * @since Android 1.0 */ + @SuppressWarnings("nls") public URI toURI() { String name = getAbsoluteName(); try { - if (!name.startsWith("/")) { //$NON-NLS-1$ + if (!name.startsWith("/")) { // start with sep. - return new URI("file", null, //$NON-NLS-1$ - new StringBuilder(name.length() + 1).append('/') - .append(name).toString(), null, null); - } else if (name.startsWith("//")) { //$NON-NLS-1$ - return new URI("file", name, null); // UNC path //$NON-NLS-1$ + return new URI("file", null, new StringBuilder( + name.length() + 1).append('/').append(name).toString(), + null, null); + } else if (name.startsWith("//")) { + return new URI("file", "", name, null); // UNC path } - return new URI("file", null, name, null, null); //$NON-NLS-1$ + return new URI("file", null, name, null, null); } catch (URISyntaxException e) { // this should never happen return null; @@ -1390,22 +1438,23 @@ public class File implements Serializable, Comparable<File> { * Returns a Uniform Resource Locator for this file. The URL is system * dependent and may not be transferable between different operating / file * systems. - * - * @return an URL for this file. + * + * @return a URL for this file. * @throws java.net.MalformedURLException - * if the path cannot be transformed into an URL. - * @since Android 1.0 + * if the path cannot be transformed into a URL. */ + @SuppressWarnings("nls") public URL toURL() throws java.net.MalformedURLException { String name = getAbsoluteName(); - if (!name.startsWith("/")) { //$NON-NLS-1$ + if (!name.startsWith("/")) { // start with sep. - return new URL("file", "", -1, new StringBuilder(name.length() + 1) //$NON-NLS-1$ //$NON-NLS-2$ - .append('/').append(name).toString(), null); - } else if (name.startsWith("//")) { //$NON-NLS-1$ - return new URL("file:" + name); // UNC path //$NON-NLS-1$ + return new URL( + "file", EMPTY_STRING, -1, new StringBuilder(name.length() + 1) //$NON-NLS-1$ + .append('/').append(name).toString(), null); + } else if (name.startsWith("//")) { + return new URL("file:" + name); // UNC path } - return new URL("file", "", -1, name, null); //$NON-NLS-1$ //$NON-NLS-2$ + return new URL("file", EMPTY_STRING, -1, name, null); } private String getAbsoluteName() { @@ -1436,60 +1485,3 @@ public class File implements Serializable, Comparable<File> { path = path.replace(inSeparator, separatorChar); } } - -// BEGIN android-added -/** - * Implements the actual DeleteOnExit mechanism. Is registered as a shutdown - * hook in the Runtime, once it is actually being used. - */ -class DeleteOnExit extends Thread { - - /** - * Our singleton instance. - */ - private static DeleteOnExit instance; - - /** - * Our list of files scheduled for deletion. - */ - private ArrayList<String> files = new ArrayList<String>(); - - /** - * Returns our singleton instance, creating it if necessary. - */ - public static synchronized DeleteOnExit getInstance() { - if (instance == null) { - instance = new DeleteOnExit(); - Runtime.getRuntime().addShutdownHook(instance); - } - - return instance; - } - - /** - * Schedules a file for deletion. - * - * @param filename The file to delete. - */ - public void addFile(String filename) { - synchronized(files) { - if (!files.contains(filename)) { - files.add(filename); - } - } - } - - /** - * Does the actual work. Note we (a) first sort the files lexicographically - * and then (b) delete them in reverse order. This is to make sure files - * get deleted before their parent directories. - */ - @Override - public void run() { - Collections.sort(files); - for (int i = files.size() - 1; i >= 0; i--) { - new File(files.get(i)).delete(); - } - } -} -// END android-added diff --git a/luni/src/main/java/java/io/FileDescriptor.java b/luni/src/main/java/java/io/FileDescriptor.java index e131c88..15eb983 100644 --- a/luni/src/main/java/java/io/FileDescriptor.java +++ b/luni/src/main/java/java/io/FileDescriptor.java @@ -30,33 +30,25 @@ package java.io; * System.err streams respectively. * <p> * Applications should not create new FileDescriptors. - * + * * @see FileInputStream#getFD() * @see FileOutputStream#getFD() * @see RandomAccessFile#getFD() - * - * @since Android 1.0 */ public final class FileDescriptor { /** * The FileDescriptor representing standard input. - * - * @since Android 1.0 */ public static final FileDescriptor in = new FileDescriptor(); /** * FileDescriptor representing standard out. - * - * @since Android 1.0 */ public static final FileDescriptor out = new FileDescriptor(); /** * FileDescriptor representing standard error. - * - * @since Android 1.0 */ public static final FileDescriptor err = new FileDescriptor(); @@ -68,8 +60,8 @@ public final class FileDescriptor { */ int descriptor = -1; // END android-changed - - boolean readOnly = false; + + boolean readOnly = false; private static native void oneTimeInitialization(); @@ -84,8 +76,6 @@ public final class FileDescriptor { /** * Constructs a new FileDescriptor containing an invalid handle. The * contained handle is usually modified by native code at a later point. - * - * @since Android 1.0 */ public FileDescriptor() { super(); @@ -94,10 +84,9 @@ public final class FileDescriptor { /** * Ensures that data which is buffered within the underlying implementation * is written out to the appropriate device before returning. - * + * * @throws SyncFailedException * when the operation fails. - * @since Android 1.0 */ public void sync() throws SyncFailedException { // if the descriptor is a read-only one, do nothing @@ -105,15 +94,16 @@ public final class FileDescriptor { syncImpl(); } } - + private native void syncImpl() throws SyncFailedException; /** * Indicates whether this FileDescriptor is valid. - * + * * @return {@code true} if this FileDescriptor is valid, {@code false} * otherwise. - * @since Android 1.0 */ - public native boolean valid(); + public boolean valid() { + return descriptor != -1; + } } diff --git a/luni/src/main/java/java/io/FileFilter.java b/luni/src/main/java/java/io/FileFilter.java index 674ce13..5638dd9 100644 --- a/luni/src/main/java/java/io/FileFilter.java +++ b/luni/src/main/java/java/io/FileFilter.java @@ -24,21 +24,18 @@ package java.io; /** * An interface for filtering {@link File} objects based on their names * or other information. - * + * * @see File#listFiles(FileFilter) - * - * @since Android 1.0 */ public interface FileFilter { /** * Indicating whether a specific file should be included in a pathname list. - * + * * @param pathname * the abstract file to check. * @return {@code true} if the file should be included, {@code false} * otherwise. - * @since Android 1.0 */ public abstract boolean accept(File pathname); } diff --git a/luni/src/main/java/java/io/FileInputStream.java b/luni/src/main/java/java/io/FileInputStream.java index c39d1e7..1243262 100644 --- a/luni/src/main/java/java/io/FileInputStream.java +++ b/luni/src/main/java/java/io/FileInputStream.java @@ -31,11 +31,9 @@ import org.apache.harmony.nio.FileChannelFactory; * Since this may induce some performance penalty, in particular if many small * read requests are made, a FileInputStream is often wrapped by a * BufferedInputStream. - * + * * @see BufferedInputStream * @see FileOutputStream - * - * @since Android 1.0 */ public class FileInputStream extends InputStream implements Closeable { /** @@ -58,7 +56,7 @@ public class FileInputStream extends InputStream implements Closeable { /** * Constructs a new {@code FileInputStream} based on {@code file}. - * + * * @param file * the file from which this stream reads. * @throws FileNotFoundException @@ -66,7 +64,6 @@ public class FileInputStream extends InputStream implements Closeable { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * read request. - * @since Android 1.0 */ public FileInputStream(File file) throws FileNotFoundException { super(); @@ -90,7 +87,7 @@ public class FileInputStream extends InputStream implements Closeable { * Constructs a new {@code FileInputStream} on the {@link FileDescriptor} * {@code fd}. The file must already be open, therefore no * {@code FileNotFoundException} will be thrown. - * + * * @param fd * the FileDescriptor from which this stream reads. * @throws NullPointerException @@ -98,7 +95,6 @@ public class FileInputStream extends InputStream implements Closeable { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * read request. - * @since Android 1.0 */ public FileInputStream(FileDescriptor fd) { super(); @@ -121,7 +117,7 @@ public class FileInputStream extends InputStream implements Closeable { * Constructs a new {@code FileInputStream} on the file named * {@code fileName}. The path of {@code fileName} may be absolute or * relative to the system property {@code "user.dir"}. - * + * * @param fileName * the path and name of the file from which this stream reads. * @throws FileNotFoundException @@ -129,7 +125,6 @@ public class FileInputStream extends InputStream implements Closeable { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * read request. - * @since Android 1.0 */ public FileInputStream(String fileName) throws FileNotFoundException { this(null == fileName ? (File) null : new File(fileName)); @@ -139,11 +134,10 @@ public class FileInputStream extends InputStream implements Closeable { * Returns the number of bytes that are available before this stream will * block. This method always returns the size of the file minus the current * position. - * + * * @return the number of bytes available before blocking. * @throws IOException * if an error occurs in this stream. - * @since Android 1.0 */ @Override public int available() throws IOException { @@ -157,7 +151,7 @@ public class FileInputStream extends InputStream implements Closeable { // use. return fileSystem.ioctlAvailable(fd.descriptor); - // END android-added + // END android-added // BEGIN android-deleted // synchronized (repositioningLock) { @@ -179,10 +173,9 @@ public class FileInputStream extends InputStream implements Closeable { /** * Closes this stream. - * + * * @throws IOException * if an error occurs attempting to close this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -203,10 +196,9 @@ public class FileInputStream extends InputStream implements Closeable { /** * Ensures that all resources for this stream are released when it is about * to be garbage collected. - * + * * @throws IOException * if an error occurs attempting to finalize this stream. - * @since Android 1.0 */ @Override protected void finalize() throws IOException { @@ -220,10 +212,8 @@ public class FileInputStream extends InputStream implements Closeable { * that is the same as the current position of this stream within the file. * All changes made to the underlying file descriptor state via the channel * are visible by the input stream and vice versa. - * </p> - * + * * @return the file channel for this stream. - * @since Android 1.0 */ public FileChannel getChannel() { // BEGIN android-changed @@ -240,12 +230,11 @@ public class FileInputStream extends InputStream implements Closeable { /** * Returns the {@link FileDescriptor} representing the operating system * resource for this stream. - * + * * @return the {@code FileDescriptor} for this stream. * @throws IOException * if an error occurs while getting this stream's * {@code FileDescriptor}. - * @since Android 1.0 */ public final FileDescriptor getFD() throws IOException { return fd; @@ -255,11 +244,10 @@ public class FileInputStream extends InputStream implements Closeable { * Reads a single byte from this stream and returns it as an integer in the * range from 0 to 255. Returns -1 if the end of this stream has been * reached. - * + * * @return the byte read or -1 if the end of this stream has been reached. * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -271,14 +259,13 @@ public class FileInputStream extends InputStream implements Closeable { /** * Reads bytes from this stream and stores them in the byte array * {@code buffer}. - * + * * @param buffer * the byte array in which to store the bytes read. * @return the number of bytes actually read or -1 if the end of the stream * has been reached. * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ @Override public int read(byte[] buffer) throws IOException { @@ -288,7 +275,7 @@ public class FileInputStream extends InputStream implements Closeable { /** * Reads at most {@code count} bytes from this stream and stores them in the * byte array {@code buffer} starting at {@code offset}. - * + * * @param buffer * the byte array in which to store the bytes read. * @param offset @@ -304,7 +291,6 @@ public class FileInputStream extends InputStream implements Closeable { * {@code buffer}. * @throws IOException * if the stream is closed or another IOException occurs. - * @since Android 1.0 */ @Override public int read(byte[] buffer, int offset, int count) throws IOException { @@ -338,14 +324,13 @@ public class FileInputStream extends InputStream implements Closeable { * Skips {@code count} number of bytes in this stream. Subsequent * {@code read()}'s will not return these bytes unless {@code reset()} is * used. This method may perform multiple reads to read {@code count} bytes. - * + * * @param count * the number of bytes to skip. * @return the number of bytes actually skipped. * @throws IOException * if {@code count < 0}, this stream is closed or another * IOException occurs. - * @since Android 1.0 */ @Override public long skip(long count) throws IOException { diff --git a/luni/src/main/java/java/io/FileNotFoundException.java b/luni/src/main/java/java/io/FileNotFoundException.java index a0f5bc6..2ab9e89 100644 --- a/luni/src/main/java/java/io/FileNotFoundException.java +++ b/luni/src/main/java/java/io/FileNotFoundException.java @@ -19,8 +19,6 @@ package java.io; /** * Thrown when a file specified by a program cannot be found. - * - * @since Android 1.0 */ public class FileNotFoundException extends IOException { @@ -29,8 +27,6 @@ public class FileNotFoundException extends IOException { /** * Constructs a new {@code FileNotFoundException} with its stack trace * filled in. - * - * @since Android 1.0 */ public FileNotFoundException() { super(); @@ -42,7 +38,6 @@ public class FileNotFoundException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public FileNotFoundException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/FileOutputStream.java b/luni/src/main/java/java/io/FileOutputStream.java index 00ae5d8..f0b25c9 100644 --- a/luni/src/main/java/java/io/FileOutputStream.java +++ b/luni/src/main/java/java/io/FileOutputStream.java @@ -31,10 +31,10 @@ import org.apache.harmony.nio.FileChannelFactory; * Since this may induce some performance penalty, in particular if many small * write requests are made, a FileOutputStream is often wrapped by a * BufferedOutputStream. - * + * * @see BufferedOutputStream * @see FileInputStream - * + * * @since Android 1.0 */ public class FileOutputStream extends OutputStream implements Closeable { @@ -55,7 +55,7 @@ public class FileOutputStream extends OutputStream implements Closeable { /** * Constructs a new FileOutputStream on the File {@code file}. If the file * exists, it is overwritten. - * + * * @param file * the file to which this stream writes. * @throws FileNotFoundException @@ -63,7 +63,7 @@ public class FileOutputStream extends OutputStream implements Closeable { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * write request. - * @since Android 1.0 + * @see java.lang.SecurityManager#checkWrite(FileDescriptor) */ public FileOutputStream(File file) throws FileNotFoundException { this(file, false); @@ -73,7 +73,7 @@ public class FileOutputStream extends OutputStream implements Closeable { * Constructs a new FileOutputStream on the File {@code file}. The * parameter {@code append} determines whether or not the file is opened and * appended to or just opened and overwritten. - * + * * @param file * the file to which this stream writes. * @param append @@ -83,7 +83,8 @@ public class FileOutputStream extends OutputStream implements Closeable { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * write request. - * @since Android 1.0 + * @see java.lang.SecurityManager#checkWrite(FileDescriptor) + * @see java.lang.SecurityManager#checkWrite(String) */ public FileOutputStream(File file, boolean append) throws FileNotFoundException { @@ -104,7 +105,7 @@ public class FileOutputStream extends OutputStream implements Closeable { * Constructs a new FileOutputStream on the FileDescriptor {@code fd}. The * file must already be open, therefore no {@code FileNotFoundException} * will be thrown. - * + * * @param fd * the FileDescriptor to which this stream writes. * @throws NullPointerException @@ -112,7 +113,7 @@ public class FileOutputStream extends OutputStream implements Closeable { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * write request. - * @since Android 1.0 + * @see java.lang.SecurityManager#checkWrite(FileDescriptor) */ public FileOutputStream(FileDescriptor fd) { super(); @@ -133,7 +134,7 @@ public class FileOutputStream extends OutputStream implements Closeable { * Constructs a new FileOutputStream on the file named {@code filename}. If * the file exists, it is overwritten. The {@code filename} may be absolute * or relative to the system property {@code "user.dir"}. - * + * * @param filename * the name of the file to which this stream writes. * @throws FileNotFoundException @@ -141,7 +142,6 @@ public class FileOutputStream extends OutputStream implements Closeable { * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * write request. - * @since Android 1.0 */ public FileOutputStream(String filename) throws FileNotFoundException { this(filename, false); @@ -152,17 +152,16 @@ public class FileOutputStream extends OutputStream implements Closeable { * The parameter {@code append} determines whether or not the file is opened * and appended to or just opened and overwritten. The {@code filename} may * be absolute or relative to the system property {@code "user.dir"}. - * - * @param append - * indicates whether or not to append to an existing file. + * * @param filename * the name of the file to which this stream writes. + * @param append + * indicates whether or not to append to an existing file. * @throws FileNotFoundException * if the file cannot be opened for writing. * @throws SecurityException * if a {@code SecurityManager} is installed and it denies the * write request. - * @since Android 1.0 */ public FileOutputStream(String filename, boolean append) throws FileNotFoundException { @@ -172,10 +171,9 @@ public class FileOutputStream extends OutputStream implements Closeable { /** * Closes this stream. This implementation closes the underlying operating * system resources allocated to represent this stream. - * + * * @throws IOException * if an error occurs attempting to close this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -204,10 +202,9 @@ public class FileOutputStream extends OutputStream implements Closeable { /** * Frees any resources allocated for this stream before it is garbage * collected. This method is called from the Java Virtual Machine. - * + * * @throws IOException * if an error occurs attempting to finalize this stream. - * @since Android 1.0 */ @Override protected void finalize() throws IOException { @@ -221,10 +218,8 @@ public class FileOutputStream extends OutputStream implements Closeable { * file that is the same as the current position of this stream within the * file. All changes made to the underlying file descriptor state via the * channel are visible by the output stream and vice versa. - * </p> - * + * * @return the file channel representation for this stream. - * @since Android 1.0 */ public FileChannel getChannel() { return channel; @@ -233,12 +228,11 @@ public class FileOutputStream extends OutputStream implements Closeable { /** * Returns a FileDescriptor which represents the lowest level representation * of an operating system stream resource. - * + * * @return a FileDescriptor representing this stream. * @throws IOException * if an error occurs attempting to get the FileDescriptor of * this stream. - * @since Android 1.0 */ public final FileDescriptor getFD() throws IOException { return fd; @@ -247,13 +241,12 @@ public class FileOutputStream extends OutputStream implements Closeable { /** * Writes the entire contents of the byte array {@code buffer} to this * stream. - * + * * @param buffer * the buffer to be written to the file. * @throws IOException * if this stream is closed or an error occurs attempting to * write to this stream. - * @since Android 1.0 */ @Override public void write(byte[] buffer) throws IOException { @@ -263,7 +256,7 @@ public class FileOutputStream extends OutputStream implements Closeable { /** * Writes {@code count} bytes from the byte array {@code buffer} starting at * {@code offset} to this stream. - * + * * @param buffer * the buffer to write to this stream. * @param offset @@ -279,7 +272,6 @@ public class FileOutputStream extends OutputStream implements Closeable { * write to this stream. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ @Override public void write(byte[] buffer, int offset, int count) throws IOException { @@ -308,13 +300,12 @@ public class FileOutputStream extends OutputStream implements Closeable { /** * Writes the specified byte {@code oneByte} to this stream. Only the low * order byte of the integer {@code oneByte} is written. - * + * * @param oneByte * the byte to be written. * @throws IOException * if this stream is closed an error occurs attempting to write * to this stream. - * @since Android 1.0 */ @Override public void write(int oneByte) throws IOException { diff --git a/luni/src/main/java/java/io/FilePermission.java b/luni/src/main/java/java/io/FilePermission.java index 3702ac7..610adee 100644 --- a/luni/src/main/java/java/io/FilePermission.java +++ b/luni/src/main/java/java/io/FilePermission.java @@ -34,7 +34,6 @@ import org.apache.harmony.luni.util.Msg; * and directories contained in that directory. If the pathname * ends in {@code /-}, it includes all the files and directories in that * directory <i>recursively</i>. The following pathnames have a special meaning: - * </p> * <ul> * <li> * "*": all files in the current directory; @@ -46,8 +45,6 @@ import org.apache.harmony.luni.util.Msg; * "<<ALL FILES>>": any file and directory in the file system. * </li> * </ul> - * - * @since Android 1.0 */ public final class FilePermission extends Permission implements Serializable { @@ -87,8 +84,7 @@ public final class FilePermission extends Permission implements Serializable { * it contains a string other than "read", "write", "execute" * and "delete". * @throws NullPointerException - * if {@code path} is null. - * @since Android 1.0 + * if {@code path} is {@code null}. */ public FilePermission(String path, String actions) { super(path); @@ -197,7 +193,6 @@ public final class FilePermission extends Permission implements Serializable { * Returns the actions associated with this file permission. * * @return the actions associated with this file permission. - * @since Android 1.0 */ @Override public String getActions() { @@ -213,7 +208,6 @@ public final class FilePermission extends Permission implements Serializable { * the object to check equality with. * @return {@code true} if this file permission is equal to {@code obj}, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object obj) { @@ -245,7 +239,6 @@ public final class FilePermission extends Permission implements Serializable { * the permission to check. * @return {@code true} if the argument permission is implied by the * receiver, and {@code false} if it is not. - * @since Android 1.0 */ @Override public boolean implies(Permission p) { @@ -361,7 +354,6 @@ public final class FilePermission extends Permission implements Serializable { * * @return A new PermissionCollection object suitable for storing * FilePermission objects. - * @since Android 1.0 */ @Override public PermissionCollection newPermissionCollection() { @@ -372,7 +364,6 @@ public final class FilePermission extends Permission implements Serializable { * Calculates the hash code value for this file permission. * * @return the hash code value for this file permission. - * @since Android 1.0 */ @Override public int hashCode() { diff --git a/luni/src/main/java/java/io/FilePermissionCollection.java b/luni/src/main/java/java/io/FilePermissionCollection.java index 9d49b79..3049442 100644 --- a/luni/src/main/java/java/io/FilePermissionCollection.java +++ b/luni/src/main/java/java/io/FilePermissionCollection.java @@ -25,8 +25,6 @@ import java.util.Vector; /** * Collects {@link FilePermission} objects and allows to query whether a * particular permission is implied by it. - * - * @since Android 1.0 */ final class FilePermissionCollection extends PermissionCollection implements Serializable { diff --git a/luni/src/main/java/java/io/FileReader.java b/luni/src/main/java/java/io/FileReader.java index 90cd454..c62fdeb 100644 --- a/luni/src/main/java/java/io/FileReader.java +++ b/luni/src/main/java/java/io/FileReader.java @@ -27,8 +27,6 @@ package java.io; * * @see BufferedReader * @see FileWriter - * - * @since Android 1.0 */ public class FileReader extends InputStreamReader { @@ -39,7 +37,6 @@ public class FileReader extends InputStreamReader { * a File to be opened for reading characters from. * @throws FileNotFoundException * if {@code file} does not exist. - * @since Android 1.0 */ public FileReader(File file) throws FileNotFoundException { super(new FileInputStream(file)); @@ -52,7 +49,6 @@ public class FileReader extends InputStreamReader { * * @param fd * the previously opened file descriptor. - * @since Android 1.0 */ public FileReader(FileDescriptor fd) { super(new FileInputStream(fd)); @@ -65,7 +61,6 @@ public class FileReader extends InputStreamReader { * an absolute or relative path specifying the file to open. * @throws FileNotFoundException * if there is no file named {@code filename}. - * @since Android 1.0 */ public FileReader(String filename) throws FileNotFoundException { super(new FileInputStream(filename)); diff --git a/luni/src/main/java/java/io/FileWriter.java b/luni/src/main/java/java/io/FileWriter.java index 63aee88..86a9af8 100644 --- a/luni/src/main/java/java/io/FileWriter.java +++ b/luni/src/main/java/java/io/FileWriter.java @@ -27,8 +27,6 @@ package java.io; * * @see BufferedWriter * @see FileReader - * - * @since Android 1.0 */ public class FileWriter extends OutputStreamWriter { @@ -39,7 +37,6 @@ public class FileWriter extends OutputStreamWriter { * the non-null File to write bytes to. * @throws IOException * if {@code file} cannot be opened for writing. - * @since Android 1.0 */ public FileWriter(File file) throws IOException { super(new FileOutputStream(file)); @@ -56,7 +53,6 @@ public class FileWriter extends OutputStreamWriter { * indicates whether or not to append to an existing file. * @throws IOException * if the {@code file} cannot be opened for writing. - * @since Android 1.0 */ public FileWriter(File file, boolean append) throws IOException { super(new FileOutputStream(file, append)); @@ -67,7 +63,6 @@ public class FileWriter extends OutputStreamWriter { * * @param fd * the non-null FileDescriptor to write bytes to. - * @since Android 1.0 */ public FileWriter(FileDescriptor fd) { super(new FileOutputStream(fd)); @@ -80,7 +75,6 @@ public class FileWriter extends OutputStreamWriter { * the non-null name of the file to write bytes to. * @throws IOException * if the file cannot be opened for writing. - * @since Android 1.0 */ public FileWriter(String filename) throws IOException { super(new FileOutputStream(new File(filename))); @@ -97,7 +91,6 @@ public class FileWriter extends OutputStreamWriter { * indicates whether or not to append to an existing file. * @throws IOException * if the {@code file} cannot be opened for writing. - * @since Android 1.0 */ public FileWriter(String filename, boolean append) throws IOException { super(new FileOutputStream(filename, append)); diff --git a/luni/src/main/java/java/io/FilenameFilter.java b/luni/src/main/java/java/io/FilenameFilter.java index 40a6cca..a51bcc6 100644 --- a/luni/src/main/java/java/io/FilenameFilter.java +++ b/luni/src/main/java/java/io/FilenameFilter.java @@ -21,9 +21,8 @@ package java.io; * An interface for filtering {@link File} objects based on their names * or the directory they reside in. * + * @see File * @see File#list(FilenameFilter) - * - * @since Android 1.0 */ public interface FilenameFilter { @@ -34,10 +33,9 @@ public interface FilenameFilter { * the directory in which the {@code filename} was found. * @param filename * the name of the file in {@code dir} to test. - * @return {@code true} if the filename matches the filter - * and can be included in the list, {@code false} + * @return {@code true} if the filename matches the filter + * and can be included in the list, {@code false} * otherwise. - * @since Android 1.0 */ public abstract boolean accept(File dir, String filename); } diff --git a/luni/src/main/java/java/io/FilterInputStream.java b/luni/src/main/java/java/io/FilterInputStream.java index 5110060..0baa409 100644 --- a/luni/src/main/java/java/io/FilterInputStream.java +++ b/luni/src/main/java/java/io/FilterInputStream.java @@ -26,21 +26,13 @@ package java.io; * from this class. * * @see FilterOutputStream - * - * @since Android 1.0 */ public class FilterInputStream extends InputStream { - // BEGIN android-changed - // The underlying input stream address should not be cached in a register. - // This was changed to be more close to the RI. /** * The source input stream that is filtered. - * - * @since Android 1.0 */ protected volatile InputStream in; - // END android-changed /** * Constructs a new {@code FilterInputStream} with the specified input @@ -48,7 +40,6 @@ public class FilterInputStream extends InputStream { * * @param in * the non-null InputStream to filter reads on. - * @since Android 1.0 */ protected FilterInputStream(InputStream in) { super(); @@ -57,12 +48,11 @@ public class FilterInputStream extends InputStream { /** * Returns the number of bytes that are available before this stream will - * block. - * + * block. + * * @return the number of bytes available before blocking. * @throws IOException * if an error occurs in this stream. - * @since Android 1.0 */ @Override public int available() throws IOException { @@ -74,7 +64,6 @@ public class FilterInputStream extends InputStream { * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -88,14 +77,12 @@ public class FilterInputStream extends InputStream { * position, provided that {@code readlimit} has not been surpassed. * <p> * This implementation sets a mark in the filtered stream. - * </p> - * + * * @param readlimit * the number of bytes that can be read from this stream before * the mark is invalidated. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public synchronized void mark(int readlimit) { @@ -112,7 +99,6 @@ public class FilterInputStream extends InputStream { * @see #mark(int) * @see #reset() * @see #skip(long) - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -128,7 +114,6 @@ public class FilterInputStream extends InputStream { * reached. * @throws IOException * if the stream is closed or another IOException occurs. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -147,7 +132,6 @@ public class FilterInputStream extends InputStream { * filtered stream has been reached while reading. * @throws IOException * if this stream is closed or another IOException occurs. - * @since Android 1.0 */ @Override public int read(byte[] buffer) throws IOException { @@ -172,7 +156,6 @@ public class FilterInputStream extends InputStream { * filtered stream has been reached while reading. * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ @Override public int read(byte[] buffer, int offset, int count) throws IOException { @@ -189,7 +172,6 @@ public class FilterInputStream extends InputStream { * bytes have been read since setting the mark. * @see #mark(int) * @see #markSupported() - * @since Android 1.0 */ @Override public synchronized void reset() throws IOException { @@ -208,12 +190,10 @@ public class FilterInputStream extends InputStream { * @throws IOException * if this stream is closed or another IOException occurs. * @see #mark(int) - * @see #reset() - * @since Android 1.0 + * @see #reset() */ @Override public long skip(long count) throws IOException { return in.skip(count); } } - diff --git a/luni/src/main/java/java/io/FilterOutputStream.java b/luni/src/main/java/java/io/FilterOutputStream.java index 212b22e..66765f9 100644 --- a/luni/src/main/java/java/io/FilterOutputStream.java +++ b/luni/src/main/java/java/io/FilterOutputStream.java @@ -26,27 +26,22 @@ import org.apache.harmony.luni.util.Msg; * decompression of the underlying stream. Output streams that wrap another * output stream and provide some additional functionality on top of it usually * inherit from this class. - * + * * @see FilterOutputStream - * - * @since Android 1.0 */ public class FilterOutputStream extends OutputStream { /** * The target output stream for this filter stream. - * - * @since Android 1.0 */ protected OutputStream out; /** * Constructs a new {@code FilterOutputStream} with {@code out} as its * target stream. - * + * * @param out * the target stream that this stream writes to. - * @since Android 1.0 */ public FilterOutputStream(OutputStream out) { this.out = out; @@ -54,10 +49,9 @@ public class FilterOutputStream extends OutputStream { /** * Closes this stream. This implementation closes the target stream. - * + * * @throws IOException * if an error occurs attempting to close this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -73,10 +67,9 @@ public class FilterOutputStream extends OutputStream { /** * Ensures that all pending data is sent out to the target stream. This * implementation flushes the target stream. - * + * * @throws IOException * if an error occurs attempting to flush this stream. - * @since Android 1.0 */ @Override public void flush() throws IOException { @@ -87,12 +80,11 @@ public class FilterOutputStream extends OutputStream { * Writes the entire contents of the byte array {@code buffer} to this * stream. This implementation writes the {@code buffer} to the target * stream. - * + * * @param buffer * the buffer to be written. * @throws IOException * if an I/O error occurs while writing to this stream. - * @since Android 1.0 */ @Override public void write(byte[] buffer) throws IOException { @@ -105,7 +97,7 @@ public class FilterOutputStream extends OutputStream { /** * Writes {@code count} bytes from the byte array {@code buffer} starting at * {@code offset} to the target stream. - * + * * @param buffer * the buffer to write. * @param offset @@ -118,7 +110,6 @@ public class FilterOutputStream extends OutputStream { * {@code buffer}. * @throws IOException * if an I/O error occurs while writing to this stream. - * @since Android 1.0 */ @Override public void write(byte[] buffer, int offset, int count) throws IOException { @@ -149,12 +140,11 @@ public class FilterOutputStream extends OutputStream { /** * Writes one byte to the target stream. Only the low order byte of the * integer {@code oneByte} is written. - * + * * @param oneByte * the byte to be written. * @throws IOException * if an I/O error occurs while writing to this stream. - * @since Android 1.0 */ @Override public void write(int oneByte) throws IOException { diff --git a/luni/src/main/java/java/io/FilterReader.java b/luni/src/main/java/java/io/FilterReader.java index 7fa96b5..e8e06dd 100644 --- a/luni/src/main/java/java/io/FilterReader.java +++ b/luni/src/main/java/java/io/FilterReader.java @@ -26,15 +26,11 @@ package java.io; * class. * * @see FilterWriter - * - * @since Android 1.0 */ public abstract class FilterReader extends Reader { /** * The target Reader which is being filtered. - * - * @since Android 1.0 */ protected Reader in; @@ -43,7 +39,6 @@ public abstract class FilterReader extends Reader { * * @param in * The non-null Reader to filter reads on. - * @since Android 1.0 */ protected FilterReader(Reader in) { super(in); @@ -55,7 +50,6 @@ public abstract class FilterReader extends Reader { * * @throws IOException * if an error occurs while closing this reader. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -71,7 +65,6 @@ public abstract class FilterReader extends Reader { * position, provided that {@code readlimit} has not been surpassed. * <p> * This implementation sets a mark in the filtered reader. - * </p> * * @param readlimit * the number of bytes that can be read from this reader before @@ -80,7 +73,6 @@ public abstract class FilterReader extends Reader { * if an error occurs while marking this reader. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public synchronized void mark(int readlimit) throws IOException { @@ -98,7 +90,6 @@ public abstract class FilterReader extends Reader { * @see #mark(int) * @see #reset() * @see #skip(long) - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -116,7 +107,6 @@ public abstract class FilterReader extends Reader { * been reached. * @throws IOException * if an error occurs while reading from this reader. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -142,7 +132,6 @@ public abstract class FilterReader extends Reader { * filtered reader has been reached while reading. * @throws IOException * if an error occurs while reading from this reader. - * @since Android 1.0 */ @Override public int read(char[] buffer, int offset, int count) throws IOException { @@ -161,7 +150,6 @@ public abstract class FilterReader extends Reader { * is called, {@code false} if unknown or blocking will occur. * @throws IOException * if the reader is closed or some other I/O error occurs. - * @since Android 1.0 */ @Override public boolean ready() throws IOException { @@ -182,7 +170,6 @@ public abstract class FilterReader extends Reader { * {@code mark()} and {@code reset()}. * @see #mark(int) * @see #markSupported() - * @since Android 1.0 */ @Override public void reset() throws IOException { @@ -205,7 +192,6 @@ public abstract class FilterReader extends Reader { * @see #mark(int) * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public long skip(long count) throws IOException { diff --git a/luni/src/main/java/java/io/FilterWriter.java b/luni/src/main/java/java/io/FilterWriter.java index 66c1d34..cd48f64 100644 --- a/luni/src/main/java/java/io/FilterWriter.java +++ b/luni/src/main/java/java/io/FilterWriter.java @@ -24,26 +24,22 @@ package java.io; * decompression of the underlying writer. Writers that wrap another writer and * provide some additional functionality on top of it usually inherit from this * class. - * + * * @see FilterReader - * - * @since Android 1.0 */ public abstract class FilterWriter extends Writer { /** * The Writer being filtered. - * @since Android 1.0 */ protected Writer out; /** * Constructs a new FilterWriter on the Writer {@code out}. All writes are * now filtered through this writer. - * + * * @param out * the target Writer to filter writes on. - * @since Android 1.0 */ protected FilterWriter(Writer out) { super(out); @@ -52,10 +48,9 @@ public abstract class FilterWriter extends Writer { /** * Closes this writer. This implementation closes the target writer. - * + * * @throws IOException * if an error occurs attempting to close this writer. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -67,10 +62,9 @@ public abstract class FilterWriter extends Writer { /** * Flushes this writer to ensure all pending data is sent out to the target * writer. This implementation flushes the target writer. - * + * * @throws IOException * if an error occurs attempting to flush this writer. - * @since Android 1.0 */ @Override public void flush() throws IOException { @@ -82,7 +76,7 @@ public abstract class FilterWriter extends Writer { /** * Writes {@code count} characters from the char array {@code buffer} * starting at position {@code offset} to the target writer. - * + * * @param buffer * the buffer to write. * @param offset @@ -91,7 +85,6 @@ public abstract class FilterWriter extends Writer { * the number of characters in {@code buffer} to write. * @throws IOException * if an error occurs while writing to this writer. - * @since Android 1.0 */ @Override public void write(char[] buffer, int offset, int count) throws IOException { @@ -106,12 +99,11 @@ public abstract class FilterWriter extends Writer { /** * Writes the specified character {@code oneChar} to the target writer. Only the * two least significant bytes of the integer {@code oneChar} are written. - * + * * @param oneChar * the char to write to the target writer. * @throws IOException * if an error occurs while writing to this writer. - * @since Android 1.0 */ @Override public void write(int oneChar) throws IOException { @@ -124,7 +116,7 @@ public abstract class FilterWriter extends Writer { * Writes {@code count} characters from the string {@code str} starting at * position {@code index} to this writer. This implementation writes * {@code str} to the target writer. - * + * * @param str * the string to be written. * @param offset @@ -133,7 +125,6 @@ public abstract class FilterWriter extends Writer { * the number of chars in {@code str} to write. * @throws IOException * if an error occurs while writing to this writer. - * @since Android 1.0 */ @Override public void write(String str, int offset, int count) throws IOException { diff --git a/luni/src/main/java/java/io/Flushable.java b/luni/src/main/java/java/io/Flushable.java index 55fcc92..c36de30 100644 --- a/luni/src/main/java/java/io/Flushable.java +++ b/luni/src/main/java/java/io/Flushable.java @@ -20,17 +20,14 @@ package java.io; * Defines an interface for classes that can (or need to) be flushed, typically * before some output processing is considered to be finished and the object * gets closed. - * - * @since Android 1.0 */ public interface Flushable { /** * Flushes the object by writing out any buffered data to the underlying * output. - * + * * @throws IOException * if there are any issues writing the data. - * @since Android 1.0 */ void flush() throws IOException; } diff --git a/luni/src/main/java/java/io/IOException.java b/luni/src/main/java/java/io/IOException.java index 869a6d0..24cea9f 100644 --- a/luni/src/main/java/java/io/IOException.java +++ b/luni/src/main/java/java/io/IOException.java @@ -22,8 +22,6 @@ package java.io; * calling the constructor, as usual. Note there are also several subclasses of * this class for more specific error situations, such as * {@link FileNotFoundException} or {@link EOFException}. - * - * @since Android 1.0 */ public class IOException extends Exception { @@ -31,8 +29,6 @@ public class IOException extends Exception { /** * Constructs a new {@code IOException} with its stack trace filled in. - * - * @since Android 1.0 */ public IOException() { super(); @@ -44,7 +40,6 @@ public class IOException extends Exception { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public IOException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/InputStream.java b/luni/src/main/java/java/io/InputStream.java index 23fd89c..f20ce7d 100644 --- a/luni/src/main/java/java/io/InputStream.java +++ b/luni/src/main/java/java/io/InputStream.java @@ -34,10 +34,8 @@ import org.apache.harmony.luni.util.Msg; * <p> * Many specialized input streams for purposes like reading from a file already * exist in this package. - * + * * @see OutputStream - * - * @since Android 1.0 */ public abstract class InputStream extends Object implements Closeable { @@ -46,8 +44,6 @@ public abstract class InputStream extends Object implements Closeable { /** * This constructor does nothing. It is provided for signature * compatibility. - * - * @since Android 1.0 */ public InputStream() { /* empty */ @@ -57,11 +53,10 @@ public abstract class InputStream extends Object implements Closeable { * Returns the number of bytes that are available before this stream will * block. This implementation always returns 0. Subclasses should override * and indicate the correct number of bytes available. - * + * * @return the number of bytes available before blocking. * @throws IOException * if an error occurs in this stream. - * @since Android 1.0 */ public int available() throws IOException { return 0; @@ -70,10 +65,9 @@ public abstract class InputStream extends Object implements Closeable { /** * Closes this stream. Concrete implementations of this class should free * any resources during close. This implementation does nothing. - * + * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ public void close() throws IOException { /* empty */ @@ -87,14 +81,12 @@ public abstract class InputStream extends Object implements Closeable { * <p> * This default implementation does nothing and concrete subclasses must * provide their own implementation. - * </p> - * + * * @param readlimit * the number of bytes that can be read from this stream before * the mark is invalidated. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ public void mark(int readlimit) { /* empty */ @@ -103,11 +95,10 @@ public abstract class InputStream extends Object implements Closeable { /** * Indicates whether this stream supports the {@code mark()} and * {@code reset()} methods. The default implementation returns {@code false}. - * + * * @return always {@code false}. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ public boolean markSupported() { return false; @@ -118,24 +109,22 @@ public abstract class InputStream extends Object implements Closeable { * range from 0 to 255. Returns -1 if the end of the stream has been * reached. Blocks until one byte has been read, the end of the source * stream is detected or an exception is thrown. - * + * * @return the byte read or -1 if the end of stream has been reached. * @throws IOException * if the stream is closed or another IOException occurs. - * @since Android 1.0 */ public abstract int read() throws IOException; /** * Reads bytes from this stream and stores them in the byte array {@code b}. - * + * * @param b * the byte array in which to store the bytes read. * @return the number of bytes actually read or -1 if the end of the stream * has been reached. * @throws IOException * if this stream is closed or another IOException occurs. - * @since Android 1.0 */ public int read(byte[] b) throws IOException { // BEGIN android-note @@ -147,7 +136,7 @@ public abstract class InputStream extends Object implements Closeable { /** * Reads at most {@code length} bytes from this stream and stores them in * the byte array {@code b} starting at {@code offset}. - * + * * @param b * the byte array in which to store the bytes read. * @param offset @@ -163,7 +152,6 @@ public abstract class InputStream extends Object implements Closeable { * {@code b}. * @throws IOException * if the stream is closed or another IOException occurs. - * @since Android 1.0 */ public int read(byte[] b, int offset, int length) throws IOException { // BEGIN android-note @@ -195,7 +183,7 @@ public abstract class InputStream extends Object implements Closeable { } throw e; } - b[offset + i] = (byte)c; + b[offset + i] = (byte) c; } return length; } @@ -208,11 +196,9 @@ public abstract class InputStream extends Object implements Closeable { * <p> * This implementation always throws an {@code IOException} and concrete * subclasses should provide the proper implementation. - * </p> - * + * * @throws IOException * if this stream is closed or another IOException occurs. - * @since Android 1.0 */ public synchronized void reset() throws IOException { throw new IOException(); @@ -225,14 +211,12 @@ public abstract class InputStream extends Object implements Closeable { * <p> * This default implementation reads {@code n} bytes into a temporary * buffer. Concrete subclasses should provide their own implementation. - * </p> - * + * * @param n * the number of bytes to skip. * @return the number of bytes actually skipped. * @throws IOException * if this stream is closed or another IOException occurs. - * @since Android 1.0 */ public long skip(long n) throws IOException { if (n <= 0) { diff --git a/luni/src/main/java/java/io/InputStreamReader.java b/luni/src/main/java/java/io/InputStreamReader.java index 0f74b14..0fdcb9a 100644 --- a/luni/src/main/java/java/io/InputStreamReader.java +++ b/luni/src/main/java/java/io/InputStreamReader.java @@ -26,15 +26,11 @@ import java.nio.charset.CodingErrorAction; import java.nio.charset.MalformedInputException; import java.nio.charset.UnmappableCharacterException; import java.security.AccessController; -import java.util.HashMap; +import org.apache.harmony.luni.util.HistoricalNamesUtil; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; -// BEGIN android-note -// Later changes from Harmony have been integrated into this version. -// END android-note - /** * A class for turning a byte stream into a character stream. Data read from the * source input stream is converted into characters by either a default or a @@ -42,10 +38,8 @@ import org.apache.harmony.luni.util.PriviAction; * "file.encoding" system property. {@code InputStreamReader} contains a buffer * of bytes read from the source stream and converts these into characters as * needed. The buffer size is 8K. - * + * * @see OutputStreamWriter - * - * @since Android 1.0 */ public class InputStreamReader extends Reader { private InputStream in; @@ -63,10 +57,9 @@ public class InputStreamReader extends Reader { * {@code in}. This constructor sets the character converter to the encoding * specified in the "file.encoding" property and falls back to ISO 8859_1 * (ISO-Latin-1) if the property doesn't exist. - * + * * @param in * the input stream from which to read characters. - * @since Android 1.0 */ public InputStreamReader(InputStream in) { super(in); @@ -85,7 +78,7 @@ public class InputStreamReader extends Reader { * character converter that is used to decode bytes into characters is * identified by name by {@code enc}. If the encoding cannot be found, an * UnsupportedEncodingException error is thrown. - * + * * @param in * the InputStream from which to read characters. * @param enc @@ -94,7 +87,6 @@ public class InputStreamReader extends Reader { * if {@code enc} is {@code null}. * @throws UnsupportedEncodingException * if the encoding specified by {@code enc} cannot be found. - * @since Android 1.0 */ public InputStreamReader(InputStream in, final String enc) throws UnsupportedEncodingException { @@ -117,12 +109,11 @@ public class InputStreamReader extends Reader { /** * Constructs a new InputStreamReader on the InputStream {@code in} and * CharsetDecoder {@code dec}. - * + * * @param in * the source InputStream from which to read characters. * @param dec * the CharsetDecoder used by the character conversion. - * @since Android 1.0 */ public InputStreamReader(InputStream in, CharsetDecoder dec) { super(in); @@ -135,12 +126,11 @@ public class InputStreamReader extends Reader { /** * Constructs a new InputStreamReader on the InputStream {@code in} and * Charset {@code charset}. - * + * * @param in * the source InputStream from which to read characters. * @param charset * the Charset that defines the character converter - * @since Android 1.0 */ public InputStreamReader(InputStream in, Charset charset) { super(in); @@ -154,10 +144,9 @@ public class InputStreamReader extends Reader { /** * Closes this reader. This implementation closes the source InputStream and * releases all local storage. - * + * * @throws IOException * if an error occurs attempting to close this reader. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -178,10 +167,9 @@ public class InputStreamReader extends Reader { /** * Returns the name of the encoding used to convert bytes into characters. * The value {@code null} is returned if this reader has been closed. - * + * * @return the name of the character converter or {@code null} if this * reader is closed. - * @since Android 1.0 */ public String getEncoding() { if (!isOpen()) { @@ -190,172 +178,17 @@ public class InputStreamReader extends Reader { return HistoricalNamesUtil.getHistoricalName(decoder.charset().name()); } - /* - * helper for getEncoding() - */ - @SuppressWarnings("nls") - static class HistoricalNamesUtil { - private static HashMap<String, String> historicalNames = new HashMap<String, String>(); - static { - historicalNames.put("Big5-HKSCS", "Big5_HKSCS"); - historicalNames.put("EUC-JP", "EUC_JP"); - historicalNames.put("EUC-KR", "EUC_KR"); - historicalNames.put("GB2312", "EUC_CN"); - historicalNames.put("IBM-Thai", "Cp838"); - historicalNames.put("IBM00858", "Cp858"); - historicalNames.put("IBM01140", "Cp1140"); - historicalNames.put("IBM01141", "Cp1141"); - historicalNames.put("IBM01142", "Cp1142"); - historicalNames.put("IBM01143", "Cp1143"); - historicalNames.put("IBM01144", "Cp1144"); - historicalNames.put("IBM01145", "Cp1145"); - historicalNames.put("IBM01146", "Cp1146"); - historicalNames.put("IBM01147", "Cp1147"); - historicalNames.put("IBM01148", "Cp1148"); - historicalNames.put("IBM01149", "Cp1149"); - historicalNames.put("IBM037", "Cp037"); - historicalNames.put("IBM1026", "Cp1026"); - historicalNames.put("IBM1047", "Cp1047"); - historicalNames.put("IBM273", "Cp273"); - historicalNames.put("IBM277", "Cp277"); - historicalNames.put("IBM278", "Cp278"); - historicalNames.put("IBM280", "Cp280"); - historicalNames.put("IBM284", "Cp284"); - historicalNames.put("IBM285", "Cp285"); - historicalNames.put("IBM297", "Cp297"); - historicalNames.put("IBM420", "Cp420"); - historicalNames.put("IBM424", "Cp424"); - historicalNames.put("IBM437", "Cp437"); - historicalNames.put("IBM500", "Cp500"); - historicalNames.put("IBM775", "Cp775"); - historicalNames.put("IBM850", "Cp850"); - historicalNames.put("IBM852", "Cp852"); - historicalNames.put("IBM855", "Cp855"); - historicalNames.put("IBM857", "Cp857"); - historicalNames.put("IBM860", "Cp860"); - historicalNames.put("IBM861", "Cp861"); - historicalNames.put("IBM862", "Cp862"); - historicalNames.put("IBM863", "Cp863"); - historicalNames.put("IBM864", "Cp864"); - historicalNames.put("IBM865", "Cp865"); - historicalNames.put("IBM866", "Cp866"); - historicalNames.put("IBM868", "Cp868"); - historicalNames.put("IBM869", "Cp869"); - historicalNames.put("IBM870", "Cp870"); - historicalNames.put("IBM871", "Cp871"); - historicalNames.put("IBM918", "Cp918"); - historicalNames.put("ISO-2022-CN", "ISO2022CN"); - historicalNames.put("ISO-2022-JP", "ISO2022JP"); - historicalNames.put("ISO-2022-KR", "ISO2022KR"); - historicalNames.put("ISO-8859-1", "ISO8859_1"); - historicalNames.put("ISO-8859-13", "ISO8859_13"); - historicalNames.put("ISO-8859-15", "ISO8859_15"); - historicalNames.put("ISO-8859-2", "ISO8859_2"); - historicalNames.put("ISO-8859-3", "ISO8859_3"); - historicalNames.put("ISO-8859-4", "ISO8859_4"); - historicalNames.put("ISO-8859-5", "ISO8859_5"); - historicalNames.put("ISO-8859-6", "ISO8859_6"); - historicalNames.put("ISO-8859-7", "ISO8859_7"); - historicalNames.put("ISO-8859-8", "ISO8859_8"); - historicalNames.put("ISO-8859-9", "ISO8859_9"); - historicalNames.put("KOI8-R", "KOI8_R"); - historicalNames.put("Shift_JIS", "SJIS"); - historicalNames.put("TIS-620", "TIS620"); - historicalNames.put("US-ASCII", "ASCII"); - historicalNames.put("UTF-16BE", "UnicodeBigUnmarked"); - historicalNames.put("UTF-16LE", "UnicodeLittleUnmarked"); - historicalNames.put("UTF-8", "UTF8"); - historicalNames.put("windows-1250", "Cp1250"); - historicalNames.put("windows-1251", "Cp1251"); - historicalNames.put("windows-1252", "Cp1252"); - historicalNames.put("windows-1253", "Cp1253"); - historicalNames.put("windows-1254", "Cp1254"); - historicalNames.put("windows-1255", "Cp1255"); - historicalNames.put("windows-1256", "Cp1256"); - historicalNames.put("windows-1257", "Cp1257"); - historicalNames.put("windows-1258", "Cp1258"); - historicalNames.put("windows-31j", "MS932"); - historicalNames.put("x-Big5-Solaris", "Big5_Solaris"); - historicalNames.put("x-euc-jp-linux", "EUC_JP_LINUX"); - historicalNames.put("x-EUC-TW", "EUC_TW"); - historicalNames.put("x-eucJP-Open", "EUC_JP_Solaris"); - historicalNames.put("x-IBM1006", "Cp1006"); - historicalNames.put("x-IBM1025", "Cp1025"); - historicalNames.put("x-IBM1046", "Cp1046"); - historicalNames.put("x-IBM1097", "Cp1097"); - historicalNames.put("x-IBM1098", "Cp1098"); - historicalNames.put("x-IBM1112", "Cp1112"); - historicalNames.put("x-IBM1122", "Cp1122"); - historicalNames.put("x-IBM1123", "Cp1123"); - historicalNames.put("x-IBM1124", "Cp1124"); - historicalNames.put("x-IBM1381", "Cp1381"); - historicalNames.put("x-IBM1383", "Cp1383"); - historicalNames.put("x-IBM33722", "Cp33722"); - historicalNames.put("x-IBM737", "Cp737"); - historicalNames.put("x-IBM856", "Cp856"); - historicalNames.put("x-IBM874", "Cp874"); - historicalNames.put("x-IBM875", "Cp875"); - historicalNames.put("x-IBM921", "Cp921"); - historicalNames.put("x-IBM922", "Cp922"); - historicalNames.put("x-IBM930", "Cp930"); - historicalNames.put("x-IBM933", "Cp933"); - historicalNames.put("x-IBM935", "Cp935"); - historicalNames.put("x-IBM937", "Cp937"); - historicalNames.put("x-IBM939", "Cp939"); - historicalNames.put("x-IBM942", "Cp942"); - historicalNames.put("x-IBM942C", "Cp942C"); - historicalNames.put("x-IBM943", "Cp943"); - historicalNames.put("x-IBM943C", "Cp943C"); - historicalNames.put("x-IBM948", "Cp948"); - historicalNames.put("x-IBM949", "Cp949"); - historicalNames.put("x-IBM949C", "Cp949C"); - historicalNames.put("x-IBM950", "Cp950"); - historicalNames.put("x-IBM964", "Cp964"); - historicalNames.put("x-IBM970", "Cp970"); - historicalNames.put("x-ISCII91", "ISCII91"); - historicalNames.put("x-ISO-2022-CN-CNS", "ISO2022CN"); - historicalNames.put("x-ISO-2022-CN-GB", "ISO2022CN"); - historicalNames.put("x-JISAutoDetect", "JISAutoDetect"); - historicalNames.put("x-MacArabic", "MacArabic"); - historicalNames.put("x-MacCentralEurope", "MacCentralEurope"); - historicalNames.put("x-MacCroatian", "MacCroatian"); - historicalNames.put("x-MacCyrillic", "MacCyrillic"); - historicalNames.put("x-MacDingbat", "MacDingbat"); - historicalNames.put("x-MacGreek", "MacGreek"); - historicalNames.put("x-MacHebrew", "MacHebrew"); - historicalNames.put("x-MacIceland", "MacIceland"); - historicalNames.put("x-MacRoman", "MacRoman"); - historicalNames.put("x-MacRomania", "MacRomania"); - historicalNames.put("x-MacSymbol", "MacSymbol"); - historicalNames.put("x-MacThai", "MacThai"); - historicalNames.put("x-MacTurkish", "MacTurkish"); - historicalNames.put("x-MacUkraine", "MacUkraine"); - historicalNames.put("x-MS950-HKSCS", "MS950_HKSCS"); - historicalNames.put("x-mswin-936", "MS936"); - historicalNames.put("x-PCK", "PCK"); - historicalNames.put("x-windows-874", "MS874"); - historicalNames.put("x-windows-949", "MS949"); - historicalNames.put("x-windows-950", "MS950"); - } - - public static String getHistoricalName(String name) { - return (!historicalNames.containsKey(name) ? name : historicalNames - .get(name)); - } - } - /** * Reads a single character from this reader and returns it as an integer * with the two higher-order bytes set to 0. Returns -1 if the end of the * reader has been reached. The byte value is either obtained from * converting bytes in this reader's buffer or by first filling the buffer * from the source InputStream and then reading from the buffer. - * + * * @return the character read or -1 if the end of the reader has been * reached. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -377,7 +210,7 @@ public class InputStreamReader extends Reader { * been reached. The bytes are either obtained from converting bytes in this * reader's buffer or by first filling the buffer from the source * InputStream and then reading from the buffer. - * + * * @param buf * the array to store the characters read. * @param offset @@ -393,7 +226,6 @@ public class InputStreamReader extends Reader { * {@code buf}. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ @Override public int read(char[] buf, int offset, int length) throws IOException { @@ -465,10 +297,7 @@ public class InputStreamReader extends Reader { if (result == CoderResult.UNDERFLOW && endOfInput) { result = decoder.decode(bytes, out, true); - // FIXME: should flush at first, but seems ICU has a bug that it - // will throw IAE if some malform/unmappable bytes found during - // decoding - // result = decoder.flush(out); + decoder.flush(out); decoder.reset(); } if (result.isMalformed()) { @@ -496,12 +325,11 @@ public class InputStreamReader extends Reader { * {@code read()} is called. This implementation returns {@code true} if * there are bytes available in the buffer or the source stream has bytes * available. - * + * * @return {@code true} if the receiver will not block when {@code read()} * is called, {@code false} if unknown or blocking will occur. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ @Override public boolean ready() throws IOException { diff --git a/luni/src/main/java/java/io/InterruptedIOException.java b/luni/src/main/java/java/io/InterruptedIOException.java index de11d28..4d537fc 100644 --- a/luni/src/main/java/java/io/InterruptedIOException.java +++ b/luni/src/main/java/java/io/InterruptedIOException.java @@ -21,8 +21,6 @@ package java.io; * Signals that a blocking I/O operation has been interrupted. The number of * bytes that were transferred successfully before the interruption took place * is stored in a field of the exception. - * - * @since Android 1.0 */ public class InterruptedIOException extends IOException { @@ -30,16 +28,12 @@ public class InterruptedIOException extends IOException { /** * The number of bytes transferred before the I/O interrupt occurred. - * - * @since Android 1.0 */ public int bytesTransferred; /** * Constructs a new {@code InterruptedIOException} with its stack trace * filled in. - * - * @since Android 1.0 */ public InterruptedIOException() { super(); @@ -51,7 +45,6 @@ public class InterruptedIOException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public InterruptedIOException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/InvalidClassException.java b/luni/src/main/java/java/io/InvalidClassException.java index 10764b5..4712bb6 100644 --- a/luni/src/main/java/java/io/InvalidClassException.java +++ b/luni/src/main/java/java/io/InvalidClassException.java @@ -30,8 +30,6 @@ package java.io; * * @see ObjectInputStream #readObject() * @see ObjectInputValidation#validateObject() - * - * @since Android 1.0 */ public class InvalidClassException extends ObjectStreamException { @@ -39,8 +37,6 @@ public class InvalidClassException extends ObjectStreamException { /** * The fully qualified name of the class that caused the problem. - * - * @since Android 1.0 */ public String classname; @@ -50,7 +46,6 @@ public class InvalidClassException extends ObjectStreamException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public InvalidClassException(String detailMessage) { super(detailMessage); @@ -65,7 +60,6 @@ public class InvalidClassException extends ObjectStreamException { * the name of the class that caused the exception. * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public InvalidClassException(String className, String detailMessage) { super(detailMessage); @@ -80,7 +74,6 @@ public class InvalidClassException extends ObjectStreamException { * * @return the detail message, possibly concatenated with the name of the * class that caused the problem. - * @since Android 1.0 */ @Override public String getMessage() { diff --git a/luni/src/main/java/java/io/InvalidObjectException.java b/luni/src/main/java/java/io/InvalidObjectException.java index a2bb5df..365209d 100644 --- a/luni/src/main/java/java/io/InvalidObjectException.java +++ b/luni/src/main/java/java/io/InvalidObjectException.java @@ -22,8 +22,6 @@ package java.io; * * @see ObjectInputStream#registerValidation(ObjectInputValidation, int) * @see ObjectInputValidation#validateObject() - * - * @since Android 1.0 */ public class InvalidObjectException extends ObjectStreamException { @@ -35,7 +33,6 @@ public class InvalidObjectException extends ObjectStreamException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public InvalidObjectException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/LineNumberInputStream.java b/luni/src/main/java/java/io/LineNumberInputStream.java index 3bb3997..1a40177 100644 --- a/luni/src/main/java/java/io/LineNumberInputStream.java +++ b/luni/src/main/java/java/io/LineNumberInputStream.java @@ -27,10 +27,8 @@ import org.apache.harmony.luni.util.Msg; * line terminator sequences are {@code '\r'}, {@code '\n'} and {@code "\r\n"}. * When using {@code read}, line terminator sequences are always translated into * {@code '\n'}. - * + * * @deprecated Use {@link LineNumberReader} - * - * @since Android 1.0 */ @Deprecated public class LineNumberInputStream extends FilterInputStream { @@ -46,10 +44,9 @@ public class LineNumberInputStream extends FilterInputStream { /** * Constructs a new {@code LineNumberInputStream} on the {@link InputStream} * {@code in}. Line numbers are counted for all data read from this stream. - * + * * @param in * The non-null input stream to count line numbers. - * @since Android 1.0 */ public LineNumberInputStream(InputStream in) { super(in); @@ -63,12 +60,10 @@ public class LineNumberInputStream extends FilterInputStream { * which are converted into {@code '\n'} by this stream. Therefore, * {@code available} returns only {@code in.available() / 2} bytes as * result. - * </p> - * + * * @return the guaranteed number of bytes available before blocking. * @throws IOException * if an error occurs in this stream. - * @since Android 1.0 */ @Override public int available() throws IOException { @@ -77,9 +72,8 @@ public class LineNumberInputStream extends FilterInputStream { /** * Returns the current line number for this stream. Numbering starts at 0. - * + * * @return the current line number. - * @since Android 1.0 */ public int getLineNumber() { return lineNumber; @@ -94,14 +88,12 @@ public class LineNumberInputStream extends FilterInputStream { * line number count. * <p> * This implementation sets a mark in the filtered stream. - * </p> - * + * * @param readlimit * the number of bytes that can be read from this stream before * the mark is invalidated. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public void mark(int readlimit) { @@ -119,14 +111,13 @@ public class LineNumberInputStream extends FilterInputStream { * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and * {@code "\r\n"}. Line terminator sequences are always translated into * {@code '\n'}. - * </p> - * + * * @return the byte read or -1 if the end of the filtered stream has been * reached. * @throws IOException * if the stream is closed or another IOException occurs. - * @since Android 1.0 */ + @SuppressWarnings("fallthrough") @Override public int read() throws IOException { int currentChar = lastChar; @@ -159,8 +150,7 @@ public class LineNumberInputStream extends FilterInputStream { * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and * {@code "\r\n"}. Line terminator sequences are always translated into * {@code '\n'}. - * </p> - * + * * @param buffer * the array in which to store the bytes read. * @param offset @@ -178,7 +168,6 @@ public class LineNumberInputStream extends FilterInputStream { * if this stream is closed or another IOException occurs. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ @Override public int read(byte[] buffer, int offset, int length) throws IOException { @@ -217,14 +206,13 @@ public class LineNumberInputStream extends FilterInputStream { /** * Resets this stream to the last marked location. It also resets the line * count to what is was when this stream was marked. - * + * * @throws IOException * if this stream is already closed, no mark has been set or the * mark is no longer valid because more than {@code readlimit} * bytes have been read since setting the mark. * @see #mark(int) * @see #markSupported() - * @since Android 1.0 */ @Override public void reset() throws IOException { @@ -237,12 +225,11 @@ public class LineNumberInputStream extends FilterInputStream { * Sets the line number of this stream to the specified * {@code lineNumber}. Note that this may have side effects on the * line number associated with the last marked position. - * + * * @param lineNumber * the new lineNumber value. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ public void setLineNumber(int lineNumber) { this.lineNumber = lineNumber; @@ -254,7 +241,7 @@ public class LineNumberInputStream extends FilterInputStream { * used. This implementation skips {@code count} number of bytes in the * filtered stream and increments the line number count whenever line * terminator sequences are skipped. - * + * * @param count * the number of bytes to skip. * @return the number of bytes actually skipped. @@ -263,7 +250,6 @@ public class LineNumberInputStream extends FilterInputStream { * @see #mark(int) * @see #read() * @see #reset() - * @since Android 1.0 */ @Override public long skip(long count) throws IOException { diff --git a/luni/src/main/java/java/io/LineNumberReader.java b/luni/src/main/java/java/io/LineNumberReader.java index 8110426..8ecdd95 100644 --- a/luni/src/main/java/java/io/LineNumberReader.java +++ b/luni/src/main/java/java/io/LineNumberReader.java @@ -22,8 +22,6 @@ package java.io; * while reading the data. The line number starts at 0 and is incremented any * time {@code '\r'}, {@code '\n'} or {@code "\r\n"} is read. The class has an * internal buffer for its data. The size of the buffer defaults to 8 KB. - * - * @since Android 1.0 */ public class LineNumberReader extends BufferedReader { @@ -38,10 +36,9 @@ public class LineNumberReader extends BufferedReader { /** * Constructs a new LineNumberReader on the Reader {@code in}. The internal * buffer gets the default size (8 KB). - * + * * @param in * the Reader that is buffered. - * @since Android 1.0 */ public LineNumberReader(Reader in) { super(in); @@ -50,14 +47,13 @@ public class LineNumberReader extends BufferedReader { /** * Constructs a new LineNumberReader on the Reader {@code in}. The size of * the internal buffer is specified by the parameter {@code size}. - * + * * @param in * the Reader that is buffered. * @param size * the size of the buffer to allocate. * @throws IllegalArgumentException * if {@code size <= 0}. - * @since Android 1.0 */ public LineNumberReader(Reader in, int size) { super(in, size); @@ -65,9 +61,8 @@ public class LineNumberReader extends BufferedReader { /** * Returns the current line number for this reader. Numbering starts at 0. - * + * * @return the current line number. - * @since Android 1.0 */ public int getLineNumber() { synchronized (lock) { @@ -82,7 +77,7 @@ public class LineNumberReader extends BufferedReader { * position, provided that {@code readlimit} has not been surpassed. The * line number associated with this marked position is also stored so that * it can be restored when {@code reset()} is called. - * + * * @param readlimit * the number of characters that can be read from this stream * before the mark is invalidated. @@ -90,7 +85,6 @@ public class LineNumberReader extends BufferedReader { * if an error occurs while setting the mark in this reader. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public void mark(int readlimit) throws IOException { @@ -110,14 +104,13 @@ public class LineNumberReader extends BufferedReader { * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and * {@code "\r\n"}. Line terminator sequences are always translated into * {@code '\n'}. - * </p> - * + * * @return the character read or -1 if the end of the source reader has been * reached. * @throws IOException * if the reader is closed or another IOException occurs. - * @since Android 1.0 */ + @SuppressWarnings("fallthrough") @Override public int read() throws IOException { synchronized (lock) { @@ -148,8 +141,7 @@ public class LineNumberReader extends BufferedReader { * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and * {@code "\r\n"}. Line terminator sequences are always translated into * {@code '\n'}. - * </p> - * + * * @param buffer * the array in which to store the characters read. * @param offset @@ -161,7 +153,6 @@ public class LineNumberReader extends BufferedReader { * source reader has been reached while reading. * @throws IOException * if this reader is closed or another IOException occurs. - * @since Android 1.0 */ @Override public int read(char[] buffer, int offset, int count) throws IOException { @@ -193,28 +184,17 @@ public class LineNumberReader extends BufferedReader { * represented by 0 or more characters followed by {@code '\r'}, * {@code '\n'}, {@code "\r\n"} or the end of the stream. The returned * string does not include the newline sequence. - * + * * @return the contents of the line or {@code null} if no characters have * been read before the end of the stream has been reached. * @throws IOException * if this reader is closed or another IOException occurs. - * @since Android 1.0 */ @Override public String readLine() throws IOException { synchronized (lock) { - /* Typical Line Length */ - StringBuilder result = new StringBuilder(80); - while (true) { - int character = read(); - if (character == -1) { - return result.length() != 0 ? result.toString() : null; - } - if (character == '\n') { - return result.toString(); - } - result.append((char) character); - } + lineNumber++; + return super.readLine(); } } @@ -222,14 +202,13 @@ public class LineNumberReader extends BufferedReader { * Resets this reader to the last marked location. It also resets the line * count to what is was when this reader was marked. This implementation * resets the source reader. - * + * * @throws IOException * if this reader is already closed, no mark has been set or the * mark is no longer valid because more than {@code readlimit} * bytes have been read since setting the mark. * @see #mark(int) * @see #markSupported() - * @since Android 1.0 */ @Override public void reset() throws IOException { @@ -244,12 +223,11 @@ public class LineNumberReader extends BufferedReader { * Sets the line number of this reader to the specified {@code lineNumber}. * Note that this may have side effects on the line number associated with * the last marked position. - * + * * @param lineNumber * the new line number value. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ public void setLineNumber(int lineNumber) { synchronized (lock) { @@ -263,7 +241,7 @@ public class LineNumberReader extends BufferedReader { * is used. This implementation skips {@code count} number of characters in * the source reader and increments the line number count whenever line * terminator sequences are skipped. - * + * * @param count * the number of characters to skip. * @return the number of characters actually skipped. @@ -274,7 +252,6 @@ public class LineNumberReader extends BufferedReader { * @see #mark(int) * @see #read() * @see #reset() - * @since Android 1.0 */ @Override public long skip(long count) throws IOException { diff --git a/luni/src/main/java/java/io/NotActiveException.java b/luni/src/main/java/java/io/NotActiveException.java index 402eabe..51f4d3f 100644 --- a/luni/src/main/java/java/io/NotActiveException.java +++ b/luni/src/main/java/java/io/NotActiveException.java @@ -29,8 +29,6 @@ package java.io; * <li>{@link ObjectInputStream#registerValidation(ObjectInputValidation, int)}</li> * <li>{@link ObjectOutputStream#defaultWriteObject()}</li> * </ul> - * - * @since Android 1.0 */ public class NotActiveException extends ObjectStreamException { @@ -39,8 +37,6 @@ public class NotActiveException extends ObjectStreamException { /** * Constructs a new {@code NotActiveException} with its stack trace filled * in. - * - * @since Android 1.0 */ public NotActiveException() { super(); @@ -52,7 +48,6 @@ public class NotActiveException extends ObjectStreamException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NotActiveException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/NotSerializableException.java b/luni/src/main/java/java/io/NotSerializableException.java index ac57a76..f6e93a7 100644 --- a/luni/src/main/java/java/io/NotSerializableException.java +++ b/luni/src/main/java/java/io/NotSerializableException.java @@ -26,8 +26,6 @@ package java.io; * * @see ObjectOutput#writeObject(Object) * @see ObjectOutputStream#writeObject(Object) - * - * @since Android 1.0 */ public class NotSerializableException extends ObjectStreamException { @@ -36,8 +34,6 @@ public class NotSerializableException extends ObjectStreamException { /** * Constructs a new {@code NotSerializableException} with its stack trace * filled in. - * - * @since Android 1.0 */ public NotSerializableException() { super(); @@ -49,7 +45,6 @@ public class NotSerializableException extends ObjectStreamException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NotSerializableException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/ObjectInput.java b/luni/src/main/java/java/io/ObjectInput.java index 7ca3cbe..3b32553 100644 --- a/luni/src/main/java/java/io/ObjectInput.java +++ b/luni/src/main/java/java/io/ObjectInput.java @@ -22,8 +22,6 @@ package java.io; * * @see ObjectInputStream * @see ObjectOutput - * - * @since Android 1.0 */ public interface ObjectInput extends DataInput { /** @@ -33,7 +31,6 @@ public interface ObjectInput extends DataInput { * @return the number of bytes available. * @throws IOException * if an I/O error occurs. - * @since Android 1.0 */ public int available() throws IOException; @@ -43,7 +40,6 @@ public interface ObjectInput extends DataInput { * * @throws IOException * if an I/O error occurs while closing the input stream. - * @since Android 1.0 */ public void close() throws IOException; @@ -55,7 +51,6 @@ public interface ObjectInput extends DataInput { * @return the byte read or -1 if the end of this stream has been reached. * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ public int read() throws IOException; @@ -69,7 +64,6 @@ public interface ObjectInput extends DataInput { * reached. * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ public int read(byte[] buffer) throws IOException; @@ -89,7 +83,6 @@ public interface ObjectInput extends DataInput { * reached. * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ public int read(byte[] buffer, int offset, int count) throws IOException; @@ -102,7 +95,6 @@ public interface ObjectInput extends DataInput { * if the object's class cannot be found. * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ public Object readObject() throws ClassNotFoundException, IOException; @@ -117,7 +109,6 @@ public interface ObjectInput extends DataInput { * * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ public long skip(long toSkip) throws IOException; } diff --git a/luni/src/main/java/java/io/ObjectInputStream.java b/luni/src/main/java/java/io/ObjectInputStream.java index 9483ab0..7dc87ff 100644 --- a/luni/src/main/java/java/io/ObjectInputStream.java +++ b/luni/src/main/java/java/io/ObjectInputStream.java @@ -17,6 +17,11 @@ package java.io; +// BEGIN android-note +// Harmony uses ObjectAccessors to access fields through JNI. Android has not +// yet migrated that API. As a consequence, there's a lot of changes here... +// END android-note + import java.io.EmulatedFields.ObjectSlot; import java.lang.reflect.Array; import java.lang.reflect.Constructor; @@ -27,14 +32,20 @@ import java.lang.reflect.Proxy; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; -import java.util.Hashtable; -import java.util.IdentityHashMap; +import java.util.HashMap; import java.util.Iterator; // BEGIN android-added import dalvik.system.VMStack; // END android-added +// BEGIN android-removed +// import org.apache.harmony.misc.accessors.ObjectAccessor; +// import org.apache.harmony.misc.accessors.AccessorFactory; +// END android-removed + +import org.apache.harmony.kernel.vm.VM; +import org.apache.harmony.luni.internal.nls.Messages; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; @@ -42,18 +53,19 @@ import org.apache.harmony.luni.util.PriviAction; * A specialized {@link InputStream} that is able to read (deserialize) Java * objects as well as primitive data types (int, byte, char etc.). The data has * typically been saved using an ObjectOutputStream. - * + * * @see ObjectOutputStream * @see ObjectInput * @see Serializable * @see Externalizable - * - * @since Android 1.0 */ public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants { - private static InputStream emptyStream = new ByteArrayInputStream( + // BEGIN android-note + // this is non-static to avoid sync contention. Would static be faster? + // END android-note + private InputStream emptyStream = new ByteArrayInputStream( new byte[0]); // To put into objectsRead when reading unsharedObject @@ -85,7 +97,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, private boolean enableResolve; // Table mapping Integer (handle) -> Object - private Hashtable<Integer, Object> objectsRead; + private HashMap<Integer, Object> objectsRead; // Used by defaultReadObject private Object currentObject; @@ -109,10 +121,8 @@ public class ObjectInputStream extends InputStream implements ObjectInput, // Handle for the current class descriptor private Integer descriptorHandle; - // cache for readResolve methods - private IdentityHashMap<Class<?>, Object> readResolveCache; - - private static final Hashtable<String, Class<?>> PRIMITIVE_CLASSES = new Hashtable<String, Class<?>>(); + private static final HashMap<String, Class<?>> PRIMITIVE_CLASSES = + new HashMap<String, Class<?>>(); static { PRIMITIVE_CLASSES.put("byte", byte.class); //$NON-NLS-1$ @@ -125,6 +135,10 @@ public class ObjectInputStream extends InputStream implements ObjectInput, PRIMITIVE_CLASSES.put("double", double.class); //$NON-NLS-1$ } + // BEGIN android-removed + // private ObjectAccessor accessor = AccessorFactory.getObjectAccessor(); + // END android-removed + // Internal type used to keep track of validators & corresponding priority static class InputValidationDesc { ObjectInputValidation validator; @@ -135,22 +149,19 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * GetField is an inner class that provides access to the persistent fields * read from the source stream. - * - * @since Android 1.0 */ public abstract static class GetField { /** * Gets the ObjectStreamClass that describes a field. - * + * * @return the descriptor class for a serialized field. - * @since Android 1.0 */ public abstract ObjectStreamClass getObjectStreamClass(); /** * Indicates if the field identified by {@code name} is defaulted. This * means that it has no value in this stream. - * + * * @param name * the name of the field to check. * @return {@code true} if the field is defaulted, {@code false} @@ -160,7 +171,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IOException * if an error occurs while reading from the source input * stream. - * @since Android 1.0 */ public abstract boolean defaulted(String name) throws IOException, IllegalArgumentException; @@ -168,7 +178,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Gets the value of the boolean field identified by {@code name} from * the persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -181,7 +191,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code name} is * not {@code boolean}. - * @since Android 1.0 */ public abstract boolean get(String name, boolean defaultValue) throws IOException, IllegalArgumentException; @@ -189,7 +198,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Gets the value of the character field identified by {@code name} from * the persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -202,7 +211,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code name} is * not {@code char}. - * @since Android 1.0 */ public abstract char get(String name, char defaultValue) throws IOException, IllegalArgumentException; @@ -210,7 +218,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Gets the value of the byte field identified by {@code name} from the * persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -223,7 +231,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code name} is * not {@code byte}. - * @since Android 1.0 */ public abstract byte get(String name, byte defaultValue) throws IOException, IllegalArgumentException; @@ -231,7 +238,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Gets the value of the short field identified by {@code name} from the * persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -244,7 +251,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code name} is * not {@code short}. - * @since Android 1.0 */ public abstract short get(String name, short defaultValue) throws IOException, IllegalArgumentException; @@ -252,7 +258,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Gets the value of the integer field identified by {@code name} from * the persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -265,15 +271,14 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code name} is * not {@code int}. - * @since Android 1.0 */ public abstract int get(String name, int defaultValue) throws IOException, IllegalArgumentException; - /** + /** * Gets the value of the long field identified by {@code name} from the * persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -286,7 +291,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code name} is * not {@code long}. - * @since Android 1.0 */ public abstract long get(String name, long defaultValue) throws IOException, IllegalArgumentException; @@ -294,7 +298,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Gets the value of the float field identified by {@code name} from the * persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -307,7 +311,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code float} is * not {@code char}. - * @since Android 1.0 */ public abstract float get(String name, float defaultValue) throws IOException, IllegalArgumentException; @@ -315,7 +318,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Gets the value of the double field identified by {@code name} from * the persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -328,7 +331,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code name} is * not {@code double}. - * @since Android 1.0 */ public abstract double get(String name, double defaultValue) throws IOException, IllegalArgumentException; @@ -336,7 +338,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Gets the value of the object field identified by {@code name} from * the persistent field. - * + * * @param name * the name of the field to get. * @param defaultValue @@ -349,7 +351,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IllegalArgumentException * if the type of the field identified by {@code name} is * not {@code Object}. - * @since Android 1.0 */ public abstract Object get(String name, Object defaultValue) throws IOException, IllegalArgumentException; @@ -359,14 +360,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Constructs a new ObjectInputStream. This default constructor can be used * by subclasses that do not want to use the public constructor if it * allocates unneeded data. - * + * * @throws IOException * if an error occurs when creating this stream. * @throws SecurityException * if a security manager is installed and it denies subclassing * this class. * @see SecurityManager#checkPermission(java.security.Permission) - * @since Android 1.0 */ protected ObjectInputStream() throws IOException, SecurityException { super(); @@ -382,7 +382,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Constructs a new ObjectInputStream that reads from the InputStream * {@code input}. - * + * * @param input * the non-null source InputStream to filter reads on. * @throws IOException @@ -393,7 +393,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws SecurityException * if a security manager is installed and it denies subclassing * this class. - * @since Android 1.0 */ public ObjectInputStream(InputStream input) throws StreamCorruptedException, IOException { @@ -437,7 +436,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, primitiveTypes = new DataInputStream(this); enableResolve = false; this.subclassOverridingImplementation = false; - this.readResolveCache = new IdentityHashMap<Class<?>, Object>(); resetState(); nestedLevels = 0; // So read...() methods can be used by @@ -452,12 +450,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Returns the number of bytes of primitive data that can be read from this * stream without blocking. This method should not be used at any arbitrary * position; just when reading primitive data types (int, char etc). - * + * * @return the number of available primitive data bytes. * @throws IOException * if any I/O problem occurs while computing the available * bytes. - * @since Android 1.0 */ @Override public int available() throws IOException { @@ -470,7 +467,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Checks to if it is ok to read primitive types from this stream at * this point. One is not supposed to read primitive types when about to * read an object, for example, so an exception has to be thrown. - * + * * @throws IOException * If any IO problem occurred when trying to read primitive type * or if it is illegal to read primitive types @@ -514,10 +511,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Closes this stream. This implementation closes the source stream. - * + * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -528,7 +524,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Default method to read objects from this stream. Serializable fields * defined in the object's class and superclasses are read from the source * stream. - * + * * @throws ClassNotFoundException * if the object's class cannot be found. * @throws IOException @@ -536,7 +532,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws NotActiveException * if this method is not called from {@code readObject()}. * @see ObjectOutputStream#defaultWriteObject - * @since Android 1.0 */ public void defaultReadObject() throws IOException, ClassNotFoundException, NotActiveException { @@ -552,7 +547,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Enables object replacement for this stream. By default this is not * enabled. Only trusted subclasses (loaded with system class loader) are * allowed to change this status. - * + * * @param enable * {@code true} to enable object replacement; {@code false} to * disable it. @@ -562,7 +557,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * object replacement for this stream. * @see #resolveObject * @see ObjectOutputStream#enableReplaceObject - * @since Android 1.0 */ protected boolean enableResolveObject(boolean enable) throws SecurityException { @@ -581,7 +575,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Checks if two classes belong to the same package. - * + * * @param c1 * one of the classes to test. * @param c2 @@ -594,12 +588,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, String nameC2 = c2.getName(); int indexDotC1 = nameC1.lastIndexOf('.'); int indexDotC2 = nameC2.lastIndexOf('.'); - // BEGIN android-changed - // copied from newer version of harmony if (indexDotC1 != indexDotC2) { return false; // cannot be in the same package if indices are not } - // END android-changed // the same if (indexDotC1 < 0) { return true; // both of them are in default package @@ -608,16 +599,17 @@ public class ObjectInputStream extends InputStream implements ObjectInput, nameC2.substring(0, indexDotC2)); } + // BEGIN android-added /** * Create and return a new instance of class {@code instantiationClass} * but running the constructor defined in class * {@code constructorClass} (same as {@code instantiationClass} * or a superclass). - * + * * Has to be native to avoid visibility rules and to be able to have * {@code instantiationClass} not the same as * {@code constructorClass} (no such API in java.lang.reflect). - * + * * @param instantiationClass * The new object will be an instance of this class * @param constructorClass @@ -626,26 +618,27 @@ public class ObjectInputStream extends InputStream implements ObjectInput, */ private static native Object newInstance(Class<?> instantiationClass, Class<?> constructorClass); + // END android-added /** * Return the next {@code int} handle to be used to indicate cyclic * references being loaded from the stream. - * + * * @return the next handle to represent the next cyclic reference */ - private int nextHandle() { - return this.currentHandle++; + private Integer nextHandle() { + return Integer.valueOf(this.currentHandle++); } /** * Return the next token code (TC) from the receiver, which indicates what * kind of object follows - * + * * @return the next TC from the receiver - * + * * @throws IOException * If an IO error occurs - * + * * @see ObjectStreamConstants */ private byte nextTC() throws IOException { @@ -670,12 +663,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Reads a single byte from the source stream and returns it as an integer * in the range from 0 to 255. Returns -1 if the end of the source stream * has been reached. Blocks if no input is available. - * + * * @return the byte read or -1 if the end of the source stream has been * reached. * @throws IOException * if an error occurs while reading from this stream. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -688,7 +680,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * in byte array {@code buffer} starting at offset {@code count}. Blocks * until {@code count} bytes have been read, the end of the source stream is * detected or an exception is thrown. - * + * * @param buffer * the array in which to store the bytes read. * @param offset @@ -706,7 +698,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * if an error occurs while reading from this stream. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ @Override public int read(byte[] buffer, int offset, int length) throws IOException { @@ -734,9 +725,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Reads and returns an array of raw bytes with primitive data. The array * will have up to 255 bytes. The primitive data will be in the format * described by {@code DataOutputStream}. - * + * * @return The primitive data read, as raw bytes - * + * * @throws IOException * If an IO exception happened when reading the primitive data. */ @@ -750,9 +741,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Reads and returns an array of raw bytes with primitive data. The array * will have more than 255 bytes. The primitive data will be in the format * described by {@code DataOutputStream}. - * + * * @return The primitive data read, as raw bytes - * + * * @throws IOException * If an IO exception happened when reading the primitive data. */ @@ -764,14 +755,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a boolean from the source stream. - * + * * @return the boolean value read from the source stream. * @throws EOFException * if the end of the input is reached before the read * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public boolean readBoolean() throws IOException { return primitiveTypes.readBoolean(); @@ -779,14 +769,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a byte (8 bit) from the source stream. - * + * * @return the byte value read from the source stream. * @throws EOFException * if the end of the input is reached before the read * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public byte readByte() throws IOException { return primitiveTypes.readByte(); @@ -794,14 +783,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a character (16 bit) from the source stream. - * + * * @return the char value read from the source stream. * @throws EOFException * if the end of the input is reached before the read * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public char readChar() throws IOException { return primitiveTypes.readChar(); @@ -809,7 +797,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads and discards block data and objects until TC_ENDBLOCKDATA is found. - * + * * @throws IOException * If an IO exception happened when reading the optional class * annotation. @@ -834,9 +822,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a class descriptor (an {@code ObjectStreamClass}) from the * stream. - * + * * @return the class descriptor read from the stream - * + * * @throws IOException * If an IO exception happened when reading the class * descriptor. @@ -855,8 +843,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamClass streamClass = ObjectStreamClass .lookup(proxyClass); streamClass.setLoadFields(new ObjectStreamField[0]); - registerObjectRead(streamClass, Integer.valueOf(nextHandle()), - false); + registerObjectRead(streamClass, nextHandle(), false); checkedSetSuperClassDesc(streamClass, readClassDesc()); return streamClass; case TC_REFERENCE: @@ -872,11 +859,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads the content of the receiver based on the previously read token * {@code tc}. - * + * * @param tc * The token code for the next item in the stream * @return the object read from the stream - * + * * @throws IOException * If an IO exception happened when reading the class * descriptor. @@ -922,11 +909,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads the content of the receiver based on the previously read token * {@code tc}. Primitive data content is considered an error. - * + * * @param unshared * read the object unshared * @return the object read from the stream - * + * * @throws IOException * If an IO exception happened when reading the class * descriptor. @@ -990,9 +977,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads the next item from the stream assuming it is a cyclic reference to * an object previously read. Return the actual object previously read. - * + * * @return the object previously read from the stream - * + * * @throws IOException * If an IO exception happened when reading the class * descriptor. @@ -1006,14 +993,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a double (64 bit) from the source stream. - * + * * @return the double value read from the source stream. * @throws EOFException * if the end of the input is reached before the read * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public double readDouble() throws IOException { return primitiveTypes.readDouble(); @@ -1029,9 +1015,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * When exceptions are found normally in the object graph, they are loaded * as a regular object, and not by this method. In that case, the set of * "known objects" is not reset. - * + * * @return the exception read - * + * * @throws IOException * If an IO exception happened when reading the exception * object. @@ -1064,17 +1050,17 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a collection of field descriptors (name, type name, etc) for the * class descriptor {@code cDesc} (an {@code ObjectStreamClass}) - * + * * @param cDesc * The class descriptor (an {@code ObjectStreamClass}) * for which to write field information - * + * * @throws IOException * If an IO exception happened when reading the field * descriptors. * @throws ClassNotFoundException * If a class for one of the field types could not be found - * + * * @see #readObject() */ private void readFieldDescriptors(ObjectStreamClass cDesc) @@ -1109,17 +1095,45 @@ public class ObjectInputStream extends InputStream implements ObjectInput, enableResolve = old; } } + + classSig = formatClassSig(classSig); ObjectStreamField f = new ObjectStreamField(classSig, fieldName); fields[i] = f; } } + /* + * Format the class signature for ObjectStreamField, for example, + * "[L[Ljava.lang.String;;" is converted to "[Ljava.lang.String;" + */ + private static String formatClassSig(String classSig) { + int start = 0; + int end = classSig.length(); + + if (end <= 0) { + return classSig; + } + + while (classSig.startsWith("[L", start) //$NON-NLS-1$ + && classSig.charAt(end - 1) == ';') { + start += 2; + end--; + } + + if (start > 0) { + start -= 2; + end++; + return classSig.substring(start, end); + } + return classSig; + } + /** * Reads the persistent fields of the object that is currently being read * from the source stream. The values read are stored in a GetField object * that provides access to the persistent fields. This GetField object is * then returned. - * + * * @return the GetField object from which persistent fields can be accessed * by name. * @throws ClassNotFoundException @@ -1129,7 +1143,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * if an error occurs while reading from this stream. * @throws NotActiveException * if this stream is currently not reading an object. - * @since Android 1.0 */ public GetField readFields() throws IOException, ClassNotFoundException, NotActiveException { @@ -1146,11 +1159,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a collection of field values for the emulated fields * {@code emulatedFields} - * + * * @param emulatedFields * an {@code EmulatedFieldsForLoading}, concrete subclass * of {@code GetField} - * + * * @throws IOException * If an IO exception happened when reading the field values. * @throws InvalidClassException @@ -1159,7 +1172,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws OptionalDataException * If optional data could not be found when reading the * exception graph - * + * * @see #readFields * @see #readObject() */ @@ -1206,13 +1219,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * This is the default mechanism, when emulated fields (an * {@code GetField}) are not used. Actual values to load are stored * directly into the object {@code obj}. - * + * * @param obj * Instance in which the fields will be set. * @param classDesc * A class descriptor (an {@code ObjectStreamClass}) * defining which fields should be loaded. - * + * * @throws IOException * If an IO exception happened when reading the field values. * @throws InvalidClassException @@ -1223,7 +1236,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * exception graph * @throws ClassNotFoundException * If a class of an object being de-serialized can not be found - * + * * @see #readFields * @see #readObject() */ @@ -1238,9 +1251,16 @@ public class ObjectInputStream extends InputStream implements ObjectInput, } for (ObjectStreamField fieldDesc : fields) { + + // BEGIN android-removed + // // get associated Field + // long fieldID = fieldDesc.getFieldID(accessor, declaringClass); + // END android-removed + // Code duplication starts, just because Java is typed if (fieldDesc.isPrimitive()) { try { + // BEGIN android-changed switch (fieldDesc.getTypeCode()) { case 'B': setField(obj, declaringClass, fieldDesc.getName(), @@ -1278,19 +1298,22 @@ public class ObjectInputStream extends InputStream implements ObjectInput, throw new StreamCorruptedException(Msg.getString( "K00d5", fieldDesc.getTypeCode())); //$NON-NLS-1$ } + // END android-changed } catch (NoSuchFieldError err) { } } else { // Object type (array included). String fieldName = fieldDesc.getName(); boolean setBack = false; + // BEGIN android-added ObjectStreamField field = classDesc.getField(fieldName); - if (mustResolve && field == null) { + // END android-added + if (mustResolve && fieldDesc == null) { setBack = true; mustResolve = false; } Object toSet; - if (field != null && field.isUnshared()) { + if (fieldDesc != null && fieldDesc.isUnshared()) { toSet = readUnshared(); } else { toSet = readObject(); @@ -1298,18 +1321,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, if (setBack) { mustResolve = true; } - if (field != null) { + if (fieldDesc != null) { if (toSet != null) { - // BEGIN android-removed - // Class<?> fieldType = field.getType(); - // END android-removed - // BEGIN android-added - // Originally getTypeInternal() was called getType(). - // After the semantics of getType() changed inside - // Harmony, the check below wasn't adjusted and didn't - // work anymore. - Class<?> fieldType = field.getTypeInternal(); - // END android-added + Class<?> fieldType = fieldDesc.getType(); Class<?> valueType = toSet.getClass(); if (!fieldType.isAssignableFrom(valueType)) { throw new ClassCastException(Msg.getString( @@ -1319,8 +1333,10 @@ public class ObjectInputStream extends InputStream implements ObjectInput, + fieldName })); } try { + // BEGIN android-changed objSetField(obj, declaringClass, fieldName, field .getTypeString(), toSet); + // END android-changed } catch (NoSuchFieldError e) { // Ignored } @@ -1332,14 +1348,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a float (32 bit) from the source stream. - * + * * @return the float value read from the source stream. * @throws EOFException * if the end of the input is reached before the read * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public float readFloat() throws IOException { return primitiveTypes.readFloat(); @@ -1348,7 +1363,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads bytes from the source stream into the byte array {@code buffer}. * This method will block until {@code buffer.length} bytes have been read. - * + * * @param buffer * the array in which to store the bytes read. * @throws EOFException @@ -1356,7 +1371,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public void readFully(byte[] buffer) throws IOException { primitiveTypes.readFully(buffer); @@ -1366,7 +1380,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Reads bytes from the source stream into the byte array {@code buffer}. * This method will block until {@code length} number of bytes have been * read. - * + * * @param buffer * the byte array in which to store the bytes read. * @param offset @@ -1379,7 +1393,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public void readFully(byte[] buffer, int offset, int length) throws IOException { @@ -1394,13 +1407,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * (corresponding to class descriptor {@code classDesc}) defines * private instance method {@code readObject} it will be used to load * field values. - * + * * @param object * Instance into which stored field values loaded. * @param classDesc * A class descriptor (an {@code ObjectStreamClass}) * defining which fields should be loaded. - * + * * @throws IOException * If an IO exception happened when reading the field values in * the hierarchy. @@ -1409,7 +1422,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws NotActiveException * If {@code defaultReadObject} is called from the wrong * context. - * + * * @see #defaultReadObject * @see #readObject() */ @@ -1449,7 +1462,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, int index = findStreamSuperclass(superclass, streamClassList, lastIndex); if (index == -1) { - readObjectNoData(object, superclass); + readObjectNoData(object, superclass, ObjectStreamClass.lookupStreamClass(superclass)); } else { for (int j = lastIndex; j <= index; j++) { readObjectForClass(object, streamClassList.get(j)); @@ -1483,16 +1496,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, return -1; } - private void readObjectNoData(Object object, Class<?> cl) + private void readObjectNoData(Object object, Class<?> cl, ObjectStreamClass classDesc) throws ObjectStreamException { - if (!ObjectStreamClass.isSerializable(cl)) { + if (!classDesc.isSerializable()) { return; } - - final Method readMethod = ObjectStreamClass - .getPrivateReadObjectNoDataMethod(cl); - if (readMethod != null) { - AccessController.doPrivileged(new PriviAction<Object>(readMethod)); + if (classDesc.hasMethodReadObjectNoData()){ + final Method readMethod = classDesc.getMethodReadObjectNoData(); try { readMethod.invoke(object, new Object[0]); } catch (InvocationTargetException e) { @@ -1507,6 +1517,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, throw new RuntimeException(e.toString()); } } + } private void readObjectForClass(Object object, ObjectStreamClass classDesc) @@ -1518,12 +1529,12 @@ public class ObjectInputStream extends InputStream implements ObjectInput, boolean hadWriteMethod = (classDesc.getFlags() & SC_WRITE_METHOD) > 0; Class<?> targetClass = classDesc.forClass(); + final Method readMethod; if (targetClass == null || !mustResolve) { readMethod = null; } else { - readMethod = ObjectStreamClass - .getPrivateReadObjectMethod(targetClass); + readMethod = classDesc.getMethodReadObject(); } try { if (readMethod != null) { @@ -1562,30 +1573,27 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads an integer (32 bit) from the source stream. - * + * * @return the integer value read from the source stream. * @throws EOFException * if the end of the input is reached before the read * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public int readInt() throws IOException { return primitiveTypes.readInt(); } /** - * Reads the next line from the source stream. Lines are terminated by + * Reads the next line from the source stream. Lines are terminated by * {@code '\r'}, {@code '\n'}, {@code "\r\n"} or an {@code EOF}. - * + * * @return the string read from the source stream. * @throws IOException * if an error occurs while reading from the source stream. * @deprecated Use {@link BufferedReader} - * @since Android 1.0 */ - @SuppressWarnings("deprecation") @Deprecated public String readLine() throws IOException { return primitiveTypes.readLine(); @@ -1593,14 +1601,13 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a long (64 bit) from the source stream. - * + * * @return the long value read from the source stream. * @throws EOFException * if the end of the input is reached before the read * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public long readLong() throws IOException { return primitiveTypes.readLong(); @@ -1609,11 +1616,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Read a new array from the receiver. It is assumed the array has not been * read yet (not a cyclic reference). Return the array read. - * + * * @param unshared * read the object unshared * @return the array read - * + * * @throws IOException * If an IO exception happened when reading the array. * @throws ClassNotFoundException @@ -1629,7 +1636,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$ } - Integer newHandle = Integer.valueOf(nextHandle()); + Integer newHandle = nextHandle(); // Array size int size = input.readInt(); @@ -1690,6 +1697,10 @@ public class ObjectInputStream extends InputStream implements ObjectInput, // Array of Objects Object[] objectArray = (Object[]) result; for (int i = 0; i < size; i++) { + // TODO: This place is the opportunity for enhancement + // We can implement writing elements through fast-path, + // without setting up the context (see readObject()) for + // each element with public API objectArray[i] = readObject(); } } @@ -1703,11 +1714,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a new class from the receiver. It is assumed the class has not been * read yet (not a cyclic reference). Return the class read. - * + * * @param unshared * read the object unshared * @return The {@code java.lang.Class} read from the stream. - * + * * @throws IOException * If an IO exception happened when reading the class. * @throws ClassNotFoundException @@ -1718,10 +1729,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamClass classDesc = readClassDesc(); if (classDesc != null) { - Integer newHandle = Integer.valueOf(nextHandle()); Class<?> localClass = classDesc.forClass(); if (localClass != null) { - registerObjectRead(localClass, newHandle, unshared); + registerObjectRead(localClass, nextHandle(), unshared); } return localClass; } @@ -1753,11 +1763,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamClass classDesc; primitiveData = input; Integer oldHandle = descriptorHandle; - descriptorHandle = Integer.valueOf(nextHandle()); + descriptorHandle = nextHandle(); classDesc = readClassDescriptor(); - if (descriptorHandle != null) { - registerObjectRead(classDesc, descriptorHandle, false); - } + registerObjectRead(classDesc, descriptorHandle, false); descriptorHandle = oldHandle; primitiveData = emptyStream; classDesc.setClass(resolveClass(classDesc)); @@ -1789,7 +1797,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, ClassNotFoundException, IOException { // read classdesc for Enum first ObjectStreamClass classDesc = readEnumDesc(); - Integer newHandle = Integer.valueOf(nextHandle()); + Integer newHandle = nextHandle(); // read name after class desc String name; byte tc = nextTC(); @@ -1818,11 +1826,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Reads a new class descriptor from the receiver. It is assumed the class * descriptor has not been read yet (not a cyclic reference). Return the * class descriptor read. - * + * * @param unshared * read the object unshared * @return The {@code ObjectStreamClass} read from the stream. - * + * * @throws IOException * If an IO exception happened when reading the class * descriptor. @@ -1835,21 +1843,17 @@ public class ObjectInputStream extends InputStream implements ObjectInput, // subclasses during readClassDescriptor() primitiveData = input; Integer oldHandle = descriptorHandle; - descriptorHandle = Integer.valueOf(nextHandle()); + descriptorHandle = nextHandle(); ObjectStreamClass newClassDesc = readClassDescriptor(); - if (descriptorHandle != null) { - registerObjectRead(newClassDesc, descriptorHandle, unshared); - } + registerObjectRead(newClassDesc, descriptorHandle, unshared); descriptorHandle = oldHandle; primitiveData = emptyStream; // We need to map classDesc to class. try { newClassDesc.setClass(resolveClass(newClassDesc)); - // Check SUIDs - verifySUID(newClassDesc); - // Check base name of the class - verifyBaseName(newClassDesc); + // Check SUIDs & base name of the class + verifyAndInit(newClassDesc); } catch (ClassNotFoundException e) { if (mustResolve) { throw e; @@ -1877,9 +1881,9 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Reads a new proxy class descriptor from the receiver. It is assumed the * proxy class descriptor has not been read yet (not a cyclic reference). * Return the proxy class descriptor read. - * + * * @return The {@code Class} read from the stream. - * + * * @throws IOException * If an IO exception happened when reading the class * descriptor. @@ -1901,33 +1905,33 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a class descriptor from the source stream. - * + * * @return the class descriptor read from the source stream. * @throws ClassNotFoundException * if a class for one of the objects cannot be found. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { ObjectStreamClass newClassDesc = new ObjectStreamClass(); String name = input.readUTF(); - if ("".equals(name)) { - throw new IOException("The stream is corrupted."); + if (name.length() == 0) { + // luni.07 = The stream is corrupted + throw new IOException(Messages.getString("luni.07")); //$NON-NLS-1$ } newClassDesc.setName(name); newClassDesc.setSerialVersionUID(input.readLong()); newClassDesc.setFlags(input.readByte()); - // We must register the class descriptor before reading field - // descriptors. - // if called outside of readObject, the descriptorHandle might be null - descriptorHandle = (null == descriptorHandle ? Integer - .valueOf(nextHandle()) : descriptorHandle); + /* + * We must register the class descriptor before reading field + * descriptors. If called outside of readObject, the descriptorHandle + * might be null. + */ + descriptorHandle = (null == descriptorHandle ? nextHandle() : descriptorHandle); registerObjectRead(newClassDesc, descriptorHandle, false); - descriptorHandle = null; readFieldDescriptors(newClassDesc); return newClassDesc; @@ -1936,7 +1940,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Creates the proxy class that implements the interfaces specified in * {@code interfaceNames}. - * + * * @param interfaceNames * the interfaces used to create the proxy class. * @return the proxy class. @@ -1946,16 +1950,15 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IOException * if an error occurs while reading from the source stream. * @see ObjectOutputStream#annotateProxyClass(Class) - * @since Android 1.0 */ protected Class<?> resolveProxyClass(String[] interfaceNames) throws IOException, ClassNotFoundException { - // BEGIN android-removed + // TODO: This method is opportunity for performance enhancement + // We can cache the classloader and recently used interfaces. + // BEGIN android-changed // ClassLoader loader = VM.getNonBootstrapClassLoader(); - // END android-removed - // BEGIN android-added ClassLoader loader = ClassLoader.getSystemClassLoader(); - // END android-added + // END android-changed Class<?>[] interfaces = new Class<?>[interfaceNames.length]; for (int i = 0; i < interfaceNames.length; i++) { interfaces[i] = Class.forName(interfaceNames[i], false, loader); @@ -1969,61 +1972,19 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Write a new handle describing a cyclic reference from the stream. - * + * * @return the handle read - * + * * @throws IOException * If an IO exception happened when reading the handle */ - private Integer readNewHandle() throws IOException { - return Integer.valueOf(input.readInt()); + private int readNewHandle() throws IOException { + return input.readInt(); } - /** - * Read a new object from the stream. It is assumed the object has not been - * loaded yet (not a cyclic reference). Return the object read. - * - * If the object implements {@code Externalizable} its - * {@code readExternal} is called. Otherwise, all fields described by - * the class hierarchy are loaded. Each class can define how its declared - * instance fields are loaded by defining a private method - * {@code readObject} - * - * @param unshared - * read the object unshared - * @return the object read - * - * @throws IOException - * If an IO exception happened when reading the object. - * @throws OptionalDataException - * If optional data could not be found when reading the object - * graph - * @throws ClassNotFoundException - * If a class for one of the objects could not be found - */ - private Object readNewObject(boolean unshared) - throws OptionalDataException, ClassNotFoundException, IOException { - ObjectStreamClass classDesc = readClassDesc(); + private Class<?> resolveConstructorClass(Class<?> objectClass, boolean wasSerializable, boolean wasExternalizable) + throws OptionalDataException, ClassNotFoundException, IOException { - if (classDesc == null) { - throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$ - } - - Integer newHandle = Integer.valueOf(nextHandle()); - - // Note that these values come from the Stream, and in fact it could be - // that the classes have been changed so that the info below now - // conflicts with the newer class - boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0; - boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0; - - // Maybe we should cache the values above in classDesc ? It may be the - // case that when reading classDesc we may need to read more stuff - // depending on the values above - Class<?> objectClass = classDesc.forClass(); - - Object result, registeredResult = null; - if (objectClass != null) { // The class of the instance may not be the same as the class of the // constructor to run // This is the constructor to run if Externalizable @@ -2083,9 +2044,71 @@ public class ObjectInputStream extends InputStream implements ObjectInput, } } + return constructorClass; + } + + /** + * Read a new object from the stream. It is assumed the object has not been + * loaded yet (not a cyclic reference). Return the object read. + * + * If the object implements <code>Externalizable</code> its + * <code>readExternal</code> is called. Otherwise, all fields described by + * the class hierarchy are loaded. Each class can define how its declared + * instance fields are loaded by defining a private method + * <code>readObject</code> + * + * @param unshared + * read the object unshared + * @return the object read + * + * @throws IOException + * If an IO exception happened when reading the object. + * @throws OptionalDataException + * If optional data could not be found when reading the object + * graph + * @throws ClassNotFoundException + * If a class for one of the objects could not be found + */ + private Object readNewObject(boolean unshared) + throws OptionalDataException, ClassNotFoundException, IOException { + ObjectStreamClass classDesc = readClassDesc(); + + if (classDesc == null) { + throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$ + } + + Integer newHandle = nextHandle(); + + // Note that these values come from the Stream, and in fact it could be + // that the classes have been changed so that the info below now + // conflicts with the newer class + boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0; + boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0; + + + // Maybe we should cache the values above in classDesc ? It may be the + // case that when reading classDesc we may need to read more stuff + // depending on the values above + Class<?> objectClass = classDesc.forClass(); + + Object result, registeredResult = null; + if (objectClass != null) { + + // BEGIN android-changed + // long constructor = classDesc.getConstructor(); + // if (constructor == ObjectStreamClass.CONSTRUCTOR_IS_NOT_RESOLVED) { + // constructor = accessor.getMethodID(resolveConstructorClass(objectClass, wasSerializable, wasExternalizable), null, new Class[0]); + // classDesc.setConstructor(constructor); + // } + Class constructorClass = resolveConstructorClass(objectClass, wasSerializable, wasExternalizable); + // END android-changed + // Now we know which class to instantiate and which constructor to // run. We are allowed to run the constructor. + // BEGIN android-changed + // result = accessor.newInstance(objectClass, constructor, null); result = newInstance(objectClass, constructorClass); + // END android-changed registerObjectRead(result, newHandle, unshared); registeredResult = result; @@ -2131,38 +2154,23 @@ public class ObjectInputStream extends InputStream implements ObjectInput, } if (objectClass != null) { - Object readResolveMethod = readResolveCache.get(objectClass); - if (readResolveMethod != this) { - if (readResolveMethod == null) { - final Method readResolve = ObjectStreamClass - .methodReadResolve(objectClass); - if (readResolve == null) { - readResolveCache.put(objectClass, this); - readResolveMethod = null; + + if (classDesc.hasMethodReadResolve()){ + Method methodReadResolve = classDesc.getMethodReadResolve(); + try { + result = methodReadResolve.invoke(result, (Object[]) null); + } catch (IllegalAccessException iae) { + } catch (InvocationTargetException ite) { + Throwable target = ite.getTargetException(); + if (target instanceof ObjectStreamException) { + throw (ObjectStreamException) target; + } else if (target instanceof Error) { + throw (Error) target; } else { - // Has replacement method - AccessController.doPrivileged(new PriviAction<Object>( - readResolve)); - readResolveCache.put(objectClass, readResolve); - readResolveMethod = readResolve; - } - } - if (readResolveMethod != null) { - try { - result = ((Method) readResolveMethod).invoke(result, - (Object[]) null); - } catch (IllegalAccessException iae) { - } catch (InvocationTargetException ite) { - Throwable target = ite.getTargetException(); - if (target instanceof ObjectStreamException) { - throw (ObjectStreamException) target; - } else if (target instanceof Error) { - throw (Error) target; - } else { - throw (RuntimeException) target; - } + throw (RuntimeException) target; } } + } } // We get here either if class-based replacement was not needed or if it @@ -2183,7 +2191,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Read a string encoded in {@link DataInput modified UTF-8} from the * receiver. Return the string read. - * + * * @param unshared * read the object unshared * @return the string just read. @@ -2195,8 +2203,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, if (enableResolve) { result = resolveObject(result); } - int newHandle = nextHandle(); - registerObjectRead(result, Integer.valueOf(newHandle), unshared); + registerObjectRead(result, nextHandle(), unshared); return result; } @@ -2204,11 +2211,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Read a new String in UTF format from the receiver. Return the string * read. - * + * * @param unshared * read the object unshared * @return the string just read. - * + * * @throws IOException * If an IO exception happened when reading the String. */ @@ -2218,15 +2225,14 @@ public class ObjectInputStream extends InputStream implements ObjectInput, if (enableResolve) { result = resolveObject(result); } - int newHandle = nextHandle(); - registerObjectRead(result, Integer.valueOf(newHandle), unshared); + registerObjectRead(result, nextHandle(), unshared); return result; } /** * Reads the next object from the source stream. - * + * * @return the object read from the source stream. * @throws ClassNotFoundException * if the class of one of the objects in the object graph cannot @@ -2236,7 +2242,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws OptionalDataException * if primitive data types were found instead of an object. * @see ObjectOutputStream#writeObject(Object) - * @since Android 1.0 */ public final Object readObject() throws OptionalDataException, ClassNotFoundException, IOException { @@ -2245,7 +2250,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads the next unshared object from the source stream. - * + * * @return the new object read. * @throws ClassNotFoundException * if the class of one of the objects in the object graph cannot @@ -2253,7 +2258,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IOException * if an error occurs while reading from the source stream. * @see ObjectOutputStream#writeUnshared - * @since Android 1.0 */ public Object readUnshared() throws IOException, ClassNotFoundException { return readObject(true); @@ -2347,7 +2351,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Method to be overriden by subclasses to read the next object from the * source stream. - * + * * @return the object read from the source stream. * @throws ClassNotFoundException * if the class of one of the objects in the object graph cannot @@ -2357,7 +2361,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws OptionalDataException * if primitive data types were found instead of an object. * @see ObjectOutputStream#writeObjectOverride - * @since Android 1.0 */ protected Object readObjectOverride() throws OptionalDataException, ClassNotFoundException, IOException { @@ -2370,11 +2373,10 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a short (16 bit) from the source stream. - * + * * @return the short value read from the source stream. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public short readShort() throws IOException { return primitiveTypes.readShort(); @@ -2382,13 +2384,12 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads and validates the ObjectInputStream header from the source stream. - * + * * @throws IOException * if an error occurs while reading from the source stream. * @throws StreamCorruptedException * if the source stream does not contain readable serialized * objects. - * @since Android 1.0 */ protected void readStreamHeader() throws IOException, StreamCorruptedException { @@ -2401,7 +2402,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads an unsigned byte (8 bit) from the source stream. - * + * * @return the unsigned byte value read from the source stream packaged in * an integer. * @throws EOFException @@ -2409,7 +2410,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public int readUnsignedByte() throws IOException { return primitiveTypes.readUnsignedByte(); @@ -2417,7 +2417,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads an unsigned short (16 bit) from the source stream. - * + * * @return the unsigned short value read from the source stream packaged in * an integer. * @throws EOFException @@ -2425,7 +2425,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public int readUnsignedShort() throws IOException { return primitiveTypes.readUnsignedShort(); @@ -2434,7 +2433,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Reads a string encoded in {@link DataInput modified UTF-8} from the * source stream. - * + * * @return the string encoded in {@link DataInput modified UTF-8} read from * the source stream. * @throws EOFException @@ -2442,7 +2441,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * request can be satisfied. * @throws IOException * if an error occurs while reading from the source stream. - * @since Android 1.0 */ public String readUTF() throws IOException { return primitiveTypes.readUTF(); @@ -2450,11 +2448,11 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Return the object previously read tagged with handle {@code handle}. - * + * * @param handle * The handle that this object was assigned when it was read. * @return the object previously read. - * + * * @throws InvalidObjectException * If there is no previously read object with this handle */ @@ -2472,14 +2470,14 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Assume object {@code obj} has been read, and assign a handle to * it, {@code handle}. - * + * * @param obj * Non-null object being loaded. * @param handle * An Integer, the handle to this object * @param unshared * Boolean, indicates that caller is reading in unshared mode - * + * * @see #nextHandle */ private void registerObjectRead(Object obj, Integer handle, boolean unshared) { @@ -2494,7 +2492,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * a class that implements "special" deserialization rules. It can be called * multiple times. Validation callbacks are then done in order of decreasing * priority, defined by {@code priority}. - * + * * @param object * an object that can validate itself by receiving a callback. * @param priority @@ -2512,7 +2510,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, Object instanceBeingRead = this.currentObject; // We can't be called from just anywhere. There are rules. - if (instanceBeingRead == null) { + if (instanceBeingRead == null && nestedLevels == 0) { throw new NotActiveException(); } if (object == null) { @@ -2552,7 +2550,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * Reset the collection of objects already loaded by the receiver. */ private void resetSeenObjects() { - objectsRead = new Hashtable<Integer, Object>(); + objectsRead = new HashMap<Integer, Object>(); currentHandle = baseWireHandle; primitiveData = emptyStream; } @@ -2572,7 +2570,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, /** * Loads the Java class corresponding to the class descriptor {@code * osClass} that has just been read from the source stream. - * + * * @param osClass * an ObjectStreamClass read from the source stream. * @return a Class corresponding to the descriptor {@code osClass}. @@ -2581,18 +2579,24 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @throws IOException * if an I/O error occurs while creating the class. * @see ObjectOutputStream#annotateClass(Class) - * @since Android 1.0 */ protected Class<?> resolveClass(ObjectStreamClass osClass) throws IOException, ClassNotFoundException { - String className = osClass.getName(); - // if it is primitive class, for example, long.class - Class<?> cls = PRIMITIVE_CLASSES.get(className); + // fastpath: obtain cached value + Class<?> cls = osClass.forClass(); if (null == cls) { - // not primitive class - // Use the first non-null ClassLoader on the stack. If null, use the - // system class loader - return Class.forName(className, true, callerClassLoader); + // slowpath: resolve the class + String className = osClass.getName(); + + // if it is primitive class, for example, long.class + cls = PRIMITIVE_CLASSES.get(className); + + if (null == cls) { + // not primitive class + // Use the first non-null ClassLoader on the stack. If null, use + // the system class loader + cls = Class.forName(className, true, callerClassLoader); + } } return cls; } @@ -2602,7 +2606,7 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * object} with a new object. Object substitution has to be activated first * with calling {@code enableResolveObject(true)}. This implementation just * returns {@code object}. - * + * * @param object * the original object for which a replacement may be defined. * @return the replacement object for {@code object}. @@ -2612,262 +2616,71 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * @see #enableResolveObject * @see ObjectOutputStream#enableReplaceObject * @see ObjectOutputStream#replaceObject - * @since Android 1.0 */ protected Object resolveObject(Object object) throws IOException { // By default no object replacement. Subclasses can override return object; } - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new {@code byte} value - * {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * {@code instance}'s declaring class - * @param fieldName - * Name of the field to set - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. + // BEGIN android-added + + /* + * These methods set the value of a field named fieldName of instance. The + * field is declared by declaringClass. The field is the same type as the + * value parameter. + * + * these methods could be implemented non-natively on top of + * java.lang.reflect at the expense of extra object creation + * (java.lang.reflect.Field). Otherwise Serialization could not fetch + * private fields, except by the use of a native method like this one. + * + * @throws NoSuchFieldError If the field does not exist. */ private static native void setField(Object instance, Class<?> declaringClass, String fieldName, byte value) throws NoSuchFieldError; - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new {@code char} value - * {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * {@code instance}'s declaring class - * @param fieldName - * Name of the field to set - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. - */ + private static native void setField(Object instance, Class<?> declaringClass, String fieldName, char value) throws NoSuchFieldError; - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new {@code double} value - * {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * {@code instance}'s declaring class - * @param fieldName - * Name of the field to set - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. - */ + private static native void setField(Object instance, Class<?> declaringClass, String fieldName, double value) throws NoSuchFieldError; - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new {@code float} value - * {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * {@code instance}'s declaring class - * @param fieldName - * Name of the field to set - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. - */ private static native void setField(Object instance, Class<?> declaringClass, String fieldName, float value) throws NoSuchFieldError; - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new {@code int} value - * {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * {@code instance}'s declaring class - * @param fieldName - * Name of the field to set - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. - */ private static native void setField(Object instance, Class<?> declaringClass, String fieldName, int value) throws NoSuchFieldError; - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new {@code long} value - * {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * {@code instance}'s declaring class - * @param fieldName - * Name of the field to set - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. - */ private static native void setField(Object instance, Class<?> declaringClass, String fieldName, long value) throws NoSuchFieldError; - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new value {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * Class which declares the field - * @param fieldName - * Name of the field to set - * @param fieldTypeName - * Name of the class defining the type of the field - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. - */ private static native void objSetField(Object instance, Class<?> declaringClass, String fieldName, String fieldTypeName, Object value) throws NoSuchFieldError; - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new {@code short} value - * {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * {@code instance}'s declaring class - * @param fieldName - * Name of the field to set - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. - */ private static native void setField(Object instance, Class<?> declaringClass, String fieldName, short value) throws NoSuchFieldError; - /** - * Set a given declared field named {@code fieldName} of - * {@code instance} to the new {@code boolean} value - * {@code value}. - * - * This method could be implemented non-natively on top of java.lang.reflect - * implementations that support the {@code setAccessible} API, at the - * expense of extra object creation (java.lang.reflect.Field). Otherwise - * Serialization could not set private fields, except by the use of a native - * method like this one. - * - * @param instance - * Object whose field to set - * @param declaringClass - * {@code instance}'s declaring class - * @param fieldName - * Name of the field to set - * @param value - * New value for the field - * - * @throws NoSuchFieldError - * If the field does not exist. - */ private static native void setField(Object instance, Class<?> declaringClass, String fieldName, boolean value) throws NoSuchFieldError; + // END android-added + /** * Skips {@code length} bytes on the source stream. This method should not * be used to skip bytes at any arbitrary position, just when reading * primitive data types (int, char etc). - * + * * @param length * the number of bytes to skip. * @return the number of bytes actually skipped. @@ -2875,7 +2688,6 @@ public class ObjectInputStream extends InputStream implements ObjectInput, * if an error occurs while skipping bytes on the source stream. * @throws NullPointerException * if the source stream is {@code null}. - * @since Android 1.0 */ public int skipBytes(int length) throws IOException { // To be used with available. Ok to call if reading primitive buffer @@ -2896,50 +2708,31 @@ public class ObjectInputStream extends InputStream implements ObjectInput, } /** - * Verify if the SUID for descriptor {@code loadedStreamClass}matches - * the SUID of the corresponding loaded class. - * + * Verify if the SUID & the base name for descriptor + * <code>loadedStreamClass</code>matches + * the SUID & the base name of the corresponding loaded class and + * init private fields. + * * @param loadedStreamClass * An ObjectStreamClass that was loaded from the stream. - * + * * @throws InvalidClassException * If the SUID of the stream class does not match the VM class */ - private void verifySUID(ObjectStreamClass loadedStreamClass) + private void verifyAndInit(ObjectStreamClass loadedStreamClass) throws InvalidClassException { + Class<?> localClass = loadedStreamClass.forClass(); - // Instances of java.lang.Class are always Serializable, even if their - // instances aren't (e.g. java.lang.Object.class). We cannot call lookup - // because it returns null if the parameter represents instances that - // cannot be serialized, and that is not what we want. If we are loading - // an instance of java.lang.Class, we better have the corresponding - // ObjectStreamClass. ObjectStreamClass localStreamClass = ObjectStreamClass .lookupStreamClass(localClass); + if (loadedStreamClass.getSerialVersionUID() != localStreamClass .getSerialVersionUID()) { throw new InvalidClassException(loadedStreamClass.getName(), Msg .getString("K00da", loadedStreamClass, //$NON-NLS-1$ localStreamClass)); } - } - /** - * Verify if the base name for descriptor {@code loadedStreamClass} - * matches the base name of the corresponding loaded class. - * - * @param loadedStreamClass - * An ObjectStreamClass that was loaded from the stream. - * - * @throws InvalidClassException - * If the base name of the stream class does not match the VM - * class - */ - private void verifyBaseName(ObjectStreamClass loadedStreamClass) - throws InvalidClassException { - Class<?> localClass = loadedStreamClass.forClass(); - ObjectStreamClass localStreamClass = ObjectStreamClass - .lookupStreamClass(localClass); String loadedClassBaseName = getBaseName(loadedStreamClass.getName()); String localClassBaseName = getBaseName(localStreamClass.getName()); @@ -2948,10 +2741,12 @@ public class ObjectInputStream extends InputStream implements ObjectInput, .getString("KA015", loadedClassBaseName, //$NON-NLS-1$ localClassBaseName)); } + + loadedStreamClass.initPrivateFields(localStreamClass); } private static String getBaseName(String fullName) { - int k = fullName.lastIndexOf("."); //$NON-NLS-1$ + int k = fullName.lastIndexOf('.'); if (k == -1 || k == (fullName.length() - 1)) { return fullName; diff --git a/luni/src/main/java/java/io/ObjectInputValidation.java b/luni/src/main/java/java/io/ObjectInputValidation.java index f1cae74..3dce15e 100644 --- a/luni/src/main/java/java/io/ObjectInputValidation.java +++ b/luni/src/main/java/java/io/ObjectInputValidation.java @@ -22,10 +22,7 @@ package java.io; * example, the validation of a whole graph of objects after all of them have * been loaded. * - * @see ObjectInputStream * @see ObjectInputStream#registerValidation(ObjectInputValidation, int) - * - * @since Android 1.0 */ public interface ObjectInputValidation { /** @@ -33,7 +30,6 @@ public interface ObjectInputValidation { * * @throws InvalidObjectException * if this object fails to validate itself. - * @since Android 1.0 */ public void validateObject() throws InvalidObjectException; } diff --git a/luni/src/main/java/java/io/ObjectOutput.java b/luni/src/main/java/java/io/ObjectOutput.java index cd68439..6680457 100644 --- a/luni/src/main/java/java/io/ObjectOutput.java +++ b/luni/src/main/java/java/io/ObjectOutput.java @@ -22,8 +22,6 @@ package java.io; * * @see ObjectOutputStream * @see ObjectInput - * - * @since Android 1.0 */ public interface ObjectOutput extends DataOutput { /** @@ -32,7 +30,6 @@ public interface ObjectOutput extends DataOutput { * * @throws IOException * if an error occurs while closing the target stream. - * @since Android 1.0 */ public void close() throws IOException; @@ -42,7 +39,6 @@ public interface ObjectOutput extends DataOutput { * * @throws IOException * if an error occurs while flushing the target stream. - * @since Android 1.0 */ public void flush() throws IOException; @@ -54,7 +50,6 @@ public interface ObjectOutput extends DataOutput { * the buffer to write. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void write(byte[] buffer) throws IOException; @@ -72,7 +67,6 @@ public interface ObjectOutput extends DataOutput { * stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void write(byte[] buffer, int offset, int count) throws IOException; @@ -85,7 +79,6 @@ public interface ObjectOutput extends DataOutput { * the byte to write. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void write(int value) throws IOException; @@ -96,7 +89,6 @@ public interface ObjectOutput extends DataOutput { * the object to write. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeObject(Object obj) throws IOException; } diff --git a/luni/src/main/java/java/io/ObjectOutputStream.java b/luni/src/main/java/java/io/ObjectOutputStream.java index 5da4950..e3c1471 100644 --- a/luni/src/main/java/java/io/ObjectOutputStream.java +++ b/luni/src/main/java/java/io/ObjectOutputStream.java @@ -20,27 +20,40 @@ package java.io; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.security.AccessController; import java.util.IdentityHashMap; -import org.apache.harmony.luni.util.PriviAction; + +// BEGIN android-note +// Harmony uses ObjectAccessors to access fields through JNI. Android has not +// yet migrated that API. As a consequence, there's a lot of changes here... +// END android-note + +// BEGIN android-removed +// import org.apache.harmony.misc.accessors.ObjectAccessor; +// import org.apache.harmony.misc.accessors.AccessorFactory; +// END android-removed + +import org.apache.harmony.luni.util.Msg; /** * A specialized {@link OutputStream} that is able to write (serialize) Java * objects as well as primitive data types (int, byte, char etc.). The data can * later be loaded using an ObjectInputStream. - * + * * @see ObjectInputStream * @see ObjectOutput * @see Serializable * @see Externalizable - * - * @since Android 1.0 */ public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants { /* + * Mask to zero SC_BLOC_DATA bit. + */ + private static final byte NOT_SC_BLOCK_DATA = (byte) (SC_BLOCK_DATA ^ 0xFF); + + /* * How many nested levels to writeObject. We may not need this. */ private int nestedLevels; @@ -107,136 +120,129 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, */ private boolean subclassOverridingImplementation; + + // BEGIN android-removed + // private ObjectAccessor accessor = AccessorFactory.getObjectAccessor(); + // END android-removed + /* - * cache for writeReplace methods + * Descriptor for java.lang.reflect.Proxy */ - private IdentityHashMap<Class<?>, Object> writeReplaceCache; + private final ObjectStreamClass proxyClassDesc = ObjectStreamClass.lookup(Proxy.class); /** * PutField is an inner class to provide access to the persistent fields * that are written to the target stream. - * - * @since Android 1.0 */ public static abstract class PutField { /** * Puts the value of the boolean field identified by {@code name} to the * persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, boolean value); /** * Puts the value of the character field identified by {@code name} to * the persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, char value); /** * Puts the value of the byte field identified by {@code name} to the * persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, byte value); /** * Puts the value of the short field identified by {@code name} to the * persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, short value); /** * Puts the value of the integer field identified by {@code name} to the * persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, int value); /** * Puts the value of the long field identified by {@code name} to the * persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, long value); /** * Puts the value of the float field identified by {@code name} to the * persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, float value); /** * Puts the value of the double field identified by {@code name} to the * persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, double value); /** * Puts the value of the Object field identified by {@code name} to the * persistent field. - * + * * @param name * the name of the field to serialize. * @param value * the value that is put to the persistent field. - * @since Android 1.0 */ public abstract void put(String name, Object value); /** * Writes the fields to the target stream {@code out}. - * + * * @param out * the target stream * @throws IOException * if an error occurs while writing to the target stream. * @deprecated This method is unsafe and may corrupt the target stream. * Use ObjectOutputStream#writeFields() instead. - * @since Android 1.0 */ @Deprecated public abstract void write(ObjectOutput out) throws IOException; @@ -246,14 +252,13 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Constructs a new {@code ObjectOutputStream}. This default constructor can * be used by subclasses that do not want to use the public constructor if * it allocates unneeded data. - * + * * @throws IOException * if an error occurs when creating this stream. * @throws SecurityException * if a security manager is installed and it denies subclassing * this class. * @see SecurityManager#checkPermission(java.security.Permission) - * @since Android 1.0 */ protected ObjectOutputStream() throws IOException, SecurityException { super(); @@ -271,17 +276,16 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Constructs a new ObjectOutputStream that writes to the OutputStream * {@code output}. - * + * * @param output * the non-null OutputStream to filter writes on. - * + * * @throws IOException * if an error occurs while writing the object stream * header * @throws SecurityException * if a security manager is installed and it denies subclassing * this class. - * @since Android 1.0 */ public ObjectOutputStream(OutputStream output) throws IOException { Class<?> implementationClass = getClass(); @@ -316,7 +320,6 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, this.enableReplace = false; this.protocolVersion = PROTOCOL_VERSION_2; this.subclassOverridingImplementation = false; - this.writeReplaceCache = new IdentityHashMap<Class<?>, Object>(); resetState(); this.nestedException = new StreamCorruptedException(); @@ -333,13 +336,12 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * stream. This optional data can be read when deserializing the class * descriptor (ObjectStreamClass) for this class from an input stream. By * default, no extra data is saved. - * + * * @param aClass * the class to annotate. * @throws IOException * if an error occurs while writing to the target stream. * @see ObjectInputStream#resolveClass(ObjectStreamClass) - * @since Android 1.0 */ protected void annotateClass(Class<?> aClass) throws IOException { // By default no extra info is saved. Subclasses can override @@ -349,13 +351,12 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Writes optional information for a proxy class to the target stream. This * optional data can be read when deserializing the proxy class from an * input stream. By default, no extra data is saved. - * + * * @param aClass * the proxy class to annotate. * @throws IOException * if an error occurs while writing to the target stream. * @see ObjectInputStream#resolveProxyClass(String[]) - * @since Android 1.0 */ protected void annotateProxyClass(Class<?> aClass) throws IOException { // By default no extra info is saved. Subclasses can override @@ -377,10 +378,9 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Closes this stream. Any buffered data is flushed. This implementation * closes the target stream. - * + * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -393,7 +393,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Computes the collection of emulated fields that users can manipulate to * store a representation different than the one declared by the class of * the object being dumped. - * + * * @see #writeFields * @see #writeFieldValues(EmulatedFieldsForDumping) */ @@ -405,13 +405,12 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Default method to write objects to this stream. Serializable fields * defined in the object's class and superclasses are written to the output * stream. - * + * * @throws IOException * if an error occurs while writing to the target stream. * @throws NotActiveException * if this method is not called from {@code writeObject()}. * @see ObjectInputStream#defaultReadObject - * @since Android 1.0 */ public void defaultWriteObject() throws IOException { // We can't be called from just anywhere. There are rules. @@ -424,13 +423,12 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes buffered data to the target stream. This is similar to {@code * flush} but the flush is not propagated to the target stream. - * + * * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ protected void drain() throws IOException { - if (primitiveTypes == null) { + if (primitiveTypes == null || primitiveTypesBuffer == null) { return; } @@ -462,7 +460,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Dumps the parameter {@code obj} only if it is {@code null} * or an object that has already been dumped previously. - * + * * @param obj * Object to check if an instance previously dumped by this * stream. @@ -470,14 +468,14 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * method does nothing). Integer, if {@code obj} is an * instance which has been dumped already. In this case this method * saves the cyclic reference. - * + * * @throws IOException * If an error occurs attempting to save {@code null} or * a cyclic reference. */ private Integer dumpCycle(Object obj) throws IOException { // If the object has been saved already, save its handle only - Integer handle = registeredObjectHandleFor(obj); + Integer handle = objectsWritten.get(obj); if (handle != null) { writeCyclicReference(handle); return handle; @@ -489,7 +487,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Enables object replacement for this stream. By default this is not * enabled. Only trusted subclasses (loaded with system class loader) are * allowed to change this status. - * + * * @param enable * {@code true} to enable object replacement; {@code false} to * disable it. @@ -499,7 +497,6 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * object replacement for this stream. * @see #replaceObject * @see ObjectInputStream#enableResolveObject - * @since Android 1.0 */ protected boolean enableReplaceObject(boolean enable) throws SecurityException { @@ -519,11 +516,10 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes buffered data to the target stream and calls the {@code flush} * method of the target stream. - * + * * @throws IOException * if an error occurs while writing to or flushing the output * stream. - * @since Android 1.0 */ @Override public void flush() throws IOException { @@ -531,212 +527,64 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, output.flush(); } - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * a boolean. - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. + // BEGIN android-added + /* + * These methods get the value of a field named fieldName of object + * instance. The field is declared by declaringClass. The field is the same + * type as the method return value. * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @return the value of the field + * these methods could be implemented non-natively on top of + * java.lang.reflect at the expense of extra object creation + * (java.lang.reflect.Field). Otherwise Serialization could not fetch + * private fields, except by the use of a native method like this one. * * @throws NoSuchFieldError If the field does not exist. */ + private static native boolean getFieldBool(Object instance, Class<?> declaringClass, String fieldName); - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * a byte - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. - * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @return the value of the field - * - * @throws NoSuchFieldError If the field does not exist. - */ private static native byte getFieldByte(Object instance, Class<?> declaringClass, String fieldName); - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * a char. - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. - * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @return the value of the field - * - * @throws NoSuchFieldError If the field does not exist. - */ private static native char getFieldChar(Object instance, Class<?> declaringClass, String fieldName); - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * a double. - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. - * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @return the value of the field - * - * @throws NoSuchFieldError If the field does not exist. - */ private static native double getFieldDouble(Object instance, Class<?> declaringClass, String fieldName); - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * a float. - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. - * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @return the value of the field - * - * @throws NoSuchFieldError If the field does not exist. - */ private static native float getFieldFloat(Object instance, Class<?> declaringClass, String fieldName); - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * an int. - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. - * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @return the value of the field - * - * @throws NoSuchFieldError If the field does not exist. - */ private static native int getFieldInt(Object instance, Class<?> declaringClass, String fieldName); - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * a long. - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. - * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @return the value of the field - * - * @throws NoSuchFieldError If the field does not exist. - */ private static native long getFieldLong(Object instance, Class<?> declaringClass, String fieldName); - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * an Object type whose name is {@code fieldTypeName}. - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. - * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @param fieldTypeName Name of the class that defines the type of this field - * @return the value of the field - * - * @throws NoSuchFieldError If the field does not exist. - */ private static native Object getFieldObj(Object instance, Class<?> declaringClass, String fieldName, String fieldTypeName); - /** - * Get the value of field named - * {@code fieldName<code> of object <code>instance}. The - * field is declared by class {@code declaringClass}. The field is supposed to be - * a short. - * - * This method could be implemented non-natively on top of java.lang.reflect implementations - * that support the {@code setAccessible} API, at the expense of extra object creation - * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except - * by the use of a native method like this one. - * - * @param instance Object whose field value we want to fetch - * @param declaringClass The class that declares the field - * @param fieldName Name of the field we want to fetch - * @return the value of the field - * - * @throws NoSuchFieldError If the field does not exist. - */ private static native short getFieldShort(Object instance, Class<?> declaringClass, String fieldName); + // END android-added /** - * Return the next {@code int} handle to be used to indicate cyclic + * Return the next <code>Integer</code> handle to be used to indicate cyclic * references being saved to the stream. - * - * @return int, the next handle to represent the next cyclic reference + * + * @return the next handle to represent the next cyclic reference */ - private int nextHandle() { - return this.currentHandle++; + private Integer nextHandle() { + return Integer.valueOf(this.currentHandle++); } /** * Gets this stream's {@code PutField} object. This object provides access * to the persistent fields that are eventually written to the output * stream. It is used to transfer the values from the fields of the object - * that is currently being written to the persistent fields. - * + * that is currently being written to the persistent fields. + * * @return the PutField object from which persistent fields can be accessed * by name. * @throws IOException @@ -744,7 +592,6 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * @throws NotActiveException * if this method is not called from {@code writeObject()}. * @see ObjectInputStream#defaultReadObject - * @since Android 1.0 */ public PutField putFields() throws IOException { // We can't be called from just anywhere. There are rules. @@ -758,39 +605,25 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } /** - * Return the {@code Integer} handle used to tag object - * {@code obj} as an instance that has been dumped already. Return - * {@code null} if object {@code obj} has not been saved yet. - * - * @param obj - * the object - * @return null if object {@code obj} has not been saved yet. Integer - * The handle that this object was assigned when it was saved. - */ - private Integer registeredObjectHandleFor(Object obj) { - return objectsWritten.get(obj); - } - - /** * Assume object {@code obj} has not been dumped yet, and assign a * handle to it - * + * * @param obj * Non-null object being dumped. * @return the handle that this object is being assigned. - * + * * @see #nextHandle */ private Integer registerObjectWritten(Object obj) { - Integer handle = Integer.valueOf(nextHandle()); - registerObjectWritten(obj, handle); + Integer handle = nextHandle(); + objectsWritten.put(obj, handle); return handle; } /** * Remove the unshared object from the table, and restore any previous * handle. - * + * * @param obj * Non-null object being dumped. * @param previousHandle @@ -798,33 +631,18 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, */ private void removeUnsharedReference(Object obj, Integer previousHandle) { if (previousHandle != null) { - registerObjectWritten(obj, previousHandle); + objectsWritten.put(obj, previousHandle); } else { objectsWritten.remove(obj); } } /** - * Assume object {@code obj} has not been dumped yet, and assign a - * handle to it, {@code handle}. - * - * @param obj - * Non-null object being dumped. - * @param handle - * An Integer, the handle to this object - * - * @see #nextHandle - */ - private void registerObjectWritten(Object obj, Integer handle) { - objectsWritten.put(obj, handle); - } - - /** * Allows trusted subclasses to substitute the specified original {@code * object} with a new object. Object substitution has to be activated first * with calling {@code enableReplaceObject(true)}. This implementation just * returns {@code object}. - * + * * @param object * the original object for which a replacement may be defined. * @return the replacement object for {@code object}. @@ -834,7 +652,6 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * @see #enableReplaceObject * @see ObjectInputStream#enableResolveObject * @see ObjectInputStream#resolveObject - * @since Android 1.0 */ protected Object replaceObject(Object object) throws IOException { // By default no object replacement. Subclasses can override @@ -847,11 +664,10 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * point. Objects previously written are no longer remembered, so they will * be written again (instead of a cyclical reference) if found in the object * graph. - * + * * @throws IOException * if {@code reset()} is called during the serialization of an * object. - * @since Android 1.0 */ public void reset() throws IOException { // First we flush what we have @@ -869,7 +685,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Reset the collection of objects already dumped by the receiver. If the * objects are found again in the object graph, the receiver will dump them * again, instead of a handle (cyclic reference). - * + * */ private void resetSeenObjects() { objectsWritten = new IdentityHashMap<Object, Integer>(); @@ -880,7 +696,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Reset the receiver. The collection of objects already dumped by the * receiver is reset, and internal structures are also reset so that the * receiver knows it is in a fresh clean state. - * + * */ private void resetState() { resetSeenObjects(); @@ -889,7 +705,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Sets the specified protocol version to be used by this stream. - * + * * @param version * the protocol version to be used. Use a {@code * PROTOCOL_VERSION_x} constant from {@code @@ -900,13 +716,16 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * if an I/O error occurs. * @see ObjectStreamConstants#PROTOCOL_VERSION_1 * @see ObjectStreamConstants#PROTOCOL_VERSION_2 - * @since Android 1.0 */ public void useProtocolVersion(int version) throws IOException { + if (!objectsWritten.isEmpty()) { + // KA028=Cannot set protocol version when stream in use + throw new IllegalStateException(Msg.getString("KA028")); //$NON-NLS-1$ + } if (version != ObjectStreamConstants.PROTOCOL_VERSION_1 && version != ObjectStreamConstants.PROTOCOL_VERSION_2) { - throw new IllegalArgumentException(org.apache.harmony.luni.util.Msg - .getString("K00b3", version)); //$NON-NLS-1$ + // K00b3=Unknown protocol\: {0} + throw new IllegalArgumentException(Msg.getString("K00b3", version)); //$NON-NLS-1$ } protocolVersion = version; } @@ -914,12 +733,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes the entire contents of the byte array {@code buffer} to the output * stream. Blocks until all bytes are written. - * + * * @param buffer * the buffer to write. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ @Override public void write(byte[] buffer) throws IOException { @@ -931,7 +749,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Writes {@code count} bytes from the byte array {@code buffer} starting at * offset {@code index} to the target stream. Blocks until all bytes are * written. - * + * * @param buffer * the buffer to write. * @param offset @@ -941,7 +759,6 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ @Override public void write(byte[] buffer, int offset, int length) throws IOException { @@ -953,12 +770,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Writes a single byte to the target stream. Only the least significant * byte of the integer {@code value} is written to the stream. Blocks until * the byte is actually written. - * + * * @param value * the byte to write. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ @Override public void write(int value) throws IOException { @@ -968,12 +784,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a boolean to the target stream. - * + * * @param value * the boolean value to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeBoolean(boolean value) throws IOException { checkWritePrimitiveTypes(); @@ -982,12 +797,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a byte (8 bit) to the target stream. - * + * * @param value * the byte to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeByte(int value) throws IOException { checkWritePrimitiveTypes(); @@ -998,12 +812,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Writes the string {@code value} as a sequence of bytes to the target * stream. Only the least significant byte of each character in the string * is written. - * + * * @param value * the string to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeBytes(String value) throws IOException { checkWritePrimitiveTypes(); @@ -1012,12 +825,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a character (16 bit) to the target stream. - * + * * @param value * the character to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeChar(int value) throws IOException { checkWritePrimitiveTypes(); @@ -1027,12 +839,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes the string {@code value} as a sequence of characters to the target * stream. - * + * * @param value * the string to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeChars(String value) throws IOException { checkWritePrimitiveTypes(); @@ -1042,14 +853,14 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Write a class descriptor {@code classDesc} (an * {@code ObjectStreamClass}) to the stream. - * + * * @param classDesc * The class descriptor (an {@code ObjectStreamClass}) to * be dumped * @param unshared * Write the object unshared * @return the handle assigned to the class descriptor - * + * * @throws IOException * If an IO exception happened when writing the class * descriptor. @@ -1066,12 +877,16 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } if (handle == null) { Class<?> classToWrite = classDesc.forClass(); - Integer previousHandle = objectsWritten.get(classDesc); + Integer previousHandle = null; + if (unshared) { + previousHandle = objectsWritten.get(classDesc); + } // If we got here, it is a new (non-null) classDesc that will have // to be registered as well - handle = registerObjectWritten(classDesc); + handle = nextHandle(); + objectsWritten.put(classDesc, handle); - if (Proxy.isProxyClass(classToWrite)) { + if (classDesc.isProxy()) { output.writeByte(TC_PROXYCLASSDESC); Class<?>[] interfaces = classToWrite.getInterfaces(); output.writeInt(interfaces.length); @@ -1080,7 +895,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } annotateProxyClass(classToWrite); output.writeByte(TC_ENDBLOCKDATA); - writeClassDescForClass(Proxy.class); + writeClassDesc(proxyClassDesc, false); if (unshared) { // remove reference to unshared object removeUnsharedReference(classDesc, previousHandle); @@ -1112,31 +927,12 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } /** - * Writes a class descriptor (an {@code ObjectStreamClass}) that - * corresponds to the {@code java.lang.Class objClass} to the stream. - * - * @param objClass - * The class for which a class descriptor (an - * {@code ObjectStreamClass}) will be dumped. - * @return the handle assigned to the class descriptor - * - * @throws IOException - * If an IO exception happened when writing the class - * descriptor. - * - */ - private Integer writeClassDescForClass(Class<?> objClass) - throws IOException { - return writeClassDesc(ObjectStreamClass.lookup(objClass), false); - } - - /** * Writes a handle representing a cyclic reference (object previously * dumped). - * + * * @param handle * The Integer handle that represents an object previously seen - * + * * @throws IOException * If an IO exception happened when writing the cyclic * reference. @@ -1148,12 +944,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a double (64 bit) to the target stream. - * + * * @param value * the double to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeDouble(double value) throws IOException { checkWritePrimitiveTypes(); @@ -1164,17 +959,17 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Writes a collection of field descriptors (name, type name, etc) for the * class descriptor {@code classDesc} (an * {@code ObjectStreamClass}) - * + * * @param classDesc * The class descriptor (an {@code ObjectStreamClass}) * for which to write field information * @param externalizable * true if the descriptors are externalizable - * + * * @throws IOException * If an IO exception happened when writing the field * descriptors. - * + * * @see #writeObject(Object) */ private void writeFieldDescriptors(ObjectStreamClass classDesc, @@ -1207,13 +1002,12 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * Writes the fields of the object currently being written to the target * stream. The field values are buffered in the currently active {@code * PutField} object, which can be accessed by calling {@code putFields()}. - * + * * @throws IOException * if an error occurs while writing to the target stream. * @throws NotActiveException * if there are no fields to write to the target stream. * @see #putFields - * @since Android 1.0 */ public void writeFields() throws IOException { // Has to have fields to write @@ -1226,14 +1020,14 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a collection of field values for the emulated fields * {@code emulatedFields} - * + * * @param emulatedFields * an {@code EmulatedFieldsForDumping}, concrete subclass * of {@code PutField} - * + * * @throws IOException * If an IO exception happened when writing the field values. - * + * * @see #writeFields * @see #writeObject(Object) */ @@ -1279,32 +1073,37 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } } + /** * Writes a collection of field values for the fields described by class * descriptor {@code classDesc} (an {@code ObjectStreamClass}). * This is the default mechanism, when emulated fields (an * {@code PutField}) are not used. Actual values to dump are fetched * directly from object {@code obj}. - * + * * @param obj * Instance from which to fetch field values to dump. * @param classDesc * A class descriptor (an {@code ObjectStreamClass}) * defining which fields should be dumped. - * + * * @throws IOException * If an IO exception happened when writing the field values. - * + * * @see #writeObject(Object) */ private void writeFieldValues(Object obj, ObjectStreamClass classDesc) throws IOException { ObjectStreamField[] fields = classDesc.fields(); Class<?> declaringClass = classDesc.forClass(); - for (int i = 0; i < fields.length; i++) { + for(ObjectStreamField fieldDesc : fields) { try { + + // BEGIN android-changed + // // get associated Field + // long fieldID = fieldDesc.getFieldID(accessor, declaringClass); + // Code duplication starts, just because Java is typed - ObjectStreamField fieldDesc = fields[i]; if (fieldDesc.isPrimitive()) { switch (fieldDesc.getTypeCode()) { case 'B': @@ -1346,14 +1145,15 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } } else { // Object type (array included). - Object field = getFieldObj(obj, declaringClass, fieldDesc + Object objField = getFieldObj(obj, declaringClass, fieldDesc .getName(), fieldDesc.getTypeString()); if (fieldDesc.isUnshared()) { - writeUnshared(field); + writeUnshared(objField); } else { - writeObject(field); + writeObject(objField); } } + // END android-changed } catch (NoSuchFieldError nsf) { // The user defined serialPersistentFields but did not provide // the glue to transfer values, @@ -1366,12 +1166,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a float (32 bit) to the target stream. - * + * * @param value * the float to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeFloat(float value) throws IOException { checkWritePrimitiveTypes(); @@ -1386,19 +1185,19 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * (corresponding to class descriptor {@code classDesc}) defines * private instance method {@code writeObject} it will be used to * dump field values. - * + * * @param object * Instance from which to fetch field values to dump. * @param classDesc * A class descriptor (an {@code ObjectStreamClass}) * defining which fields should be dumped. - * + * * @throws IOException * If an IO exception happened when writing the field values in * the hierarchy. * @throws NotActiveException * If the given object is not active - * + * * @see #defaultWriteObject * @see #writeObject(Object) */ @@ -1423,14 +1222,9 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, // See if the object has a writeObject method. If so, run it boolean executed = false; - Class<?> targetClass = classDesc.forClass(); try { - final Method method = ObjectStreamClass - .getPrivateWriteObjectMethod(targetClass); - if (method != null) { - // We have to be able to fetch its value, even if it is - // private - AccessController.doPrivileged(new PriviAction<Object>(method)); + if (classDesc.hasMethodWriteObject()){ + final Method method = classDesc.getMethodWriteObject(); try { method.invoke(object, new Object[] { this }); executed = true; @@ -1447,6 +1241,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } } + if (executed) { drain(); output.writeByte(TC_ENDBLOCKDATA); @@ -1466,12 +1261,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes an integer (32 bit) to the target stream. - * + * * @param value * the integer to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeInt(int value) throws IOException { checkWritePrimitiveTypes(); @@ -1480,12 +1274,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a long (64 bit) to the target stream. - * + * * @param value * the long to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeLong(long value) throws IOException { checkWritePrimitiveTypes(); @@ -1497,7 +1290,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * component type {@code componentType} into the receiver. It is * assumed the array has not been dumped yet. Return an {@code Integer} * that represents the handle for this object (array) which is dumped here. - * + * * @param array * The array object to dump * @param arrayClass @@ -1507,20 +1300,19 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * A {@code java.lang.Class} representing the array * component type * @return the handle assigned to the array - * + * * @throws IOException * If an IO exception happened when writing the array. */ - private Integer writeNewArray(Object array, Class<?> arrayClass, + private Integer writeNewArray(Object array, Class<?> arrayClass, ObjectStreamClass arrayClDesc, Class<?> componentType, boolean unshared) throws IOException { output.writeByte(TC_ARRAY); - writeClassDescForClass(arrayClass); + writeClassDesc(arrayClDesc, false); - Integer previousHandle = objectsWritten.get(array); - Integer handle = registerObjectWritten(array); - if (unshared) { - // remove reference to unshared object - removeUnsharedReference(array, previousHandle); + Integer handle = nextHandle(); + + if (!unshared) { + objectsWritten.put(array, handle); } // Now we have code duplication just because Java is typed. We have to @@ -1585,6 +1377,10 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, Object[] objectArray = (Object[]) array; output.writeInt(objectArray.length); for (int i = 0; i < objectArray.length; i++) { + // TODO: This place is the opportunity for enhancement + // We can implement writing elements through fast-path, + // without setting up the context (see writeObject()) for + // each element with public API writeObject(objectArray[i]); } } @@ -1597,11 +1393,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * descriptor ({@code ObjectStreamClass}) that corresponds to them. * Return an {@code Integer} that represents the handle for this * object (class) which is dumped here. - * + * * @param object * The {@code java.lang.Class} object to dump * @return the handle assigned to the class being dumped - * + * * @throws IOException * If an IO exception happened when writing the class. */ @@ -1614,21 +1410,20 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, // We cannot call lookup because it returns null if the parameter // represents instances that cannot be serialized, and that is not what // we want. + ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(object); // The handle for the classDesc is NOT the handle for the class object // being dumped. We must allocate a new handle and return it. - if (object.isEnum()) { - writeEnumDesc(object, unshared); + if (clDesc.isEnum()) { + writeEnumDesc(object, clDesc, unshared); } else { - writeClassDesc(ObjectStreamClass.lookupStreamClass(object), - unshared); + writeClassDesc(clDesc, unshared); } - Integer previousHandle = objectsWritten.get(object); - Integer handle = registerObjectWritten(object); - if (unshared) { - // remove reference to unshared object - removeUnsharedReference(object, previousHandle); + Integer handle = nextHandle(); + + if (!unshared) { + objectsWritten.put(object, handle); } return handle; @@ -1640,10 +1435,10 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * descriptors for the superclass chain will be dumped as well. Return an * {@code Integer} that represents the handle for this object (class * descriptor) which is dumped here. - * + * * @param classDesc * The {@code ObjectStreamClass} object to dump - * + * * @throws IOException * If an IO exception happened when writing the class * descriptor. @@ -1653,15 +1448,15 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, output.writeUTF(classDesc.getName()); output.writeLong(classDesc.getSerialVersionUID()); byte flags = classDesc.getFlags(); - boolean externalizable = false; - externalizable = ObjectStreamClass.isExternalizable(classDesc - .forClass()); - if (protocolVersion != PROTOCOL_VERSION_1) { - // Change for 1.2. Objects can be saved in old format - // (PROTOCOL_VERSION_1) or in the 1.2 format (PROTOCOL_VERSION_2). - // Nested "if" check to optimize checking. Second check is more - // expensive. - if (externalizable) { + + boolean externalizable = classDesc.isExternalizable(); + + if (externalizable) { + if (protocolVersion == PROTOCOL_VERSION_1) { + flags &= NOT_SC_BLOCK_DATA; + } else { + // Change for 1.2. Objects can be saved in old format + // (PROTOCOL_VERSION_1) or in the 1.2 format (PROTOCOL_VERSION_2). flags |= SC_BLOCK_DATA; } } @@ -1676,12 +1471,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a class descriptor to the target stream. - * + * * @param classDesc * the class descriptor to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ protected void writeClassDescriptor(ObjectStreamClass classDesc) throws IOException { @@ -1695,14 +1489,14 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * This is used to dump the exception instance that happened (if any) when * dumping the original object graph. The set of seen objects will be reset * just before and just after dumping this exception object. - * + * * When exceptions are found normally in the object graph, they are dumped * as a regular object, and not by this method. In that case, the set of * "known objects" is not reset. - * + * * @param ex * Exception object to dump - * + * * @throws IOException * If an IO exception happened when writing the exception * object. @@ -1719,13 +1513,13 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * the receiver. It is assumed the object has not been dumped yet. Return an * {@code Integer} that represents the handle for this object which * is dumped here. - * + * * If the object implements {@code Externalizable} its * {@code writeExternal} is called. Otherwise, all fields described * by the class hierarchy is dumped. Each class can define how its declared * instance fields are dumped by defining a private method * {@code writeObject} - * + * * @param object * The object to dump * @param theClass @@ -1734,11 +1528,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * @param unshared * Write the object unshared * @return the handle assigned to the object - * + * * @throws IOException * If an IO exception happened when writing the object. */ - private Integer writeNewObject(Object object, Class<?> theClass, + private Integer writeNewObject(Object object, Class<?> theClass, ObjectStreamClass clDesc, boolean unshared) throws IOException { // Not String, not null, not array, not cyclic reference @@ -1746,8 +1540,8 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, currentPutField = null; // null it, to make sure one will be computed if // needed - boolean externalizable = ObjectStreamClass.isExternalizable(theClass); - boolean serializable = ObjectStreamClass.isSerializable(theClass); + boolean externalizable = clDesc.isExternalizable(); + boolean serializable = clDesc.isSerializable(); if (!externalizable && !serializable) { // Object is neither externalizable nor serializable. Error throw new NotSerializableException(theClass.getName()); @@ -1755,16 +1549,20 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, // Either serializable or externalizable, now we can save info output.writeByte(TC_OBJECT); - writeClassDescForClass(theClass); - Integer previousHandle = objectsWritten.get(object); - Integer handle = registerObjectWritten(object); + writeClassDesc(clDesc, false); + Integer previousHandle = null; + if (unshared) { + previousHandle = objectsWritten.get(object); + } + Integer handle = nextHandle(); + objectsWritten.put(object, handle); // This is how we know what to do in defaultWriteObject. And it is also // used by defaultWriteObject to check if it was called from an invalid // place. // It allows writeExternal to call defaultWriteObject and have it work. currentObject = object; - currentClass = ObjectStreamClass.lookup(theClass); + currentClass = clDesc; try { if (externalizable) { boolean noBlockData = protocolVersion == PROTOCOL_VERSION_1; @@ -1808,11 +1606,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * String has not been dumped yet. Return an {@code Integer} that * represents the handle for this object (String) which is dumped here. * Strings are saved encoded with {@link DataInput modified UTF-8}. - * + * * @param object * the string to dump. * @return the handle assigned to the String being dumped - * + * * @throws IOException * If an IO exception happened when writing the String. */ @@ -1828,19 +1626,19 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } output.writeUTFBytes(object, count); - Integer previousHandle = objectsWritten.get(object); - Integer handle = registerObjectWritten(object); - if (unshared) { - // remove reference to unshared object - removeUnsharedReference(object, previousHandle); + Integer handle = nextHandle(); + + if (!unshared) { + objectsWritten.put(object, handle); } + return handle; } /** * Write a special tag that indicates the value {@code null} into the * receiver. - * + * * @throws IOException * If an IO exception happened when writing the tag for * {@code null}. @@ -1851,13 +1649,12 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes an object to the target stream. - * + * * @param object * the object to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see ObjectInputStream#readObject() - * @since Android 1.0 */ public final void writeObject(Object object) throws IOException { writeObject(object, false); @@ -1868,13 +1665,12 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * to {@code writeObject}, except that it always writes a new object to the * stream versus the use of back-referencing for identical objects by * {@code writeObject}. - * + * * @param object * the object to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. * @see ObjectInputStream#readUnshared() - * @since Android 1.0 */ public void writeUnshared(Object object) throws IOException { writeObject(object, true); @@ -1919,7 +1715,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Write object {@code object} into the receiver's underlying stream. - * + * * @param object * The object to write * @param unshared @@ -1931,10 +1727,10 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, * A boolean indicating if stream-based replacement should be * computed (if supported) for the object. * @return the handle assigned to the final object being dumped - * + * * @throws IOException * If an IO exception happened when writing the object - * + * * @see ObjectInputStream#readObject() */ private Integer writeObjectInternal(Object object, boolean unshared, @@ -1955,6 +1751,8 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, // Non-null object, first time seen... Class<?> objClass = object.getClass(); + ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(objClass); + nestedLevels++; try { @@ -1969,58 +1767,41 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } } - if (ObjectStreamClass.isSerializable(object.getClass()) + if (clDesc.isSerializable() && computeClassBasedReplacement) { - Object writeReplaceMethod = writeReplaceCache.get(objClass); - if (writeReplaceMethod != this) { - if (writeReplaceMethod == null) { - final Method writeReplace = ObjectStreamClass - .methodWriteReplace(objClass); - if (writeReplace == null) { - writeReplaceCache.put(objClass, this); - writeReplaceMethod = null; + if(clDesc.hasMethodWriteReplace()){ + Method methodWriteReplace = clDesc.getMethodWriteReplace(); + Object replObj = null; + try { + replObj = methodWriteReplace.invoke(object, (Object[]) null); + } catch (IllegalAccessException iae) { + replObj = object; + } catch (InvocationTargetException ite) { + // WARNING - Not sure this is the right thing to do + // if we can't run the method + Throwable target = ite.getTargetException(); + if (target instanceof ObjectStreamException) { + throw (ObjectStreamException) target; + } else if (target instanceof Error) { + throw (Error) target; } else { - // Has replacement method - AccessController - .doPrivileged(new PriviAction<Object>( - writeReplace)); - writeReplaceCache.put(objClass, writeReplace); - writeReplaceMethod = writeReplace; + throw (RuntimeException) target; } } - if (writeReplaceMethod != null) { - Object classBasedReplacement; - try { - classBasedReplacement = ((Method) writeReplaceMethod) - .invoke(object, (Object[]) null); - } catch (IllegalAccessException iae) { - classBasedReplacement = object; - } catch (InvocationTargetException ite) { - // WARNING - Not sure this is the right thing to do - // if we can't run the method - Throwable target = ite.getTargetException(); - if (target instanceof ObjectStreamException) { - throw (ObjectStreamException) target; - } else if (target instanceof Error) { - throw (Error) target; - } else { - throw (RuntimeException) target; - } - } - if (classBasedReplacement != object) { - // All over, class-based replacement off this time. - Integer replacementHandle = writeObjectInternal( - classBasedReplacement, false, false, - computeStreamReplacement); - // Make the original object also map to the same - // handle. - if (replacementHandle != null) { - registerObjectWritten(object, replacementHandle); - } - return replacementHandle; + if (replObj != object) { + // All over, class-based replacement off this time. + Integer replacementHandle = writeObjectInternal( + replObj, false, false, + computeStreamReplacement); + // Make the original object also map to the same + // handle. + if (replacementHandle != null) { + objectsWritten.put(object, replacementHandle); } + return replacementHandle; } } + } // We get here either if class-based replacement was not needed or @@ -2036,7 +1817,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, computeClassBasedReplacement, false); // Make the original object also map to the same handle. if (replacementHandle != null) { - registerObjectWritten(object, replacementHandle); + objectsWritten.put(object, replacementHandle); } return replacementHandle; } @@ -2061,7 +1842,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, // Is it an Array ? if (objClass.isArray()) { - return writeNewArray(object, objClass, objClass + return writeNewArray(object, objClass, clDesc, objClass .getComponentType(), unshared); } @@ -2070,20 +1851,23 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, } // Not a String or Class or Array. Default procedure. - return writeNewObject(object, objClass, unshared); + return writeNewObject(object, objClass, clDesc, unshared); } finally { nestedLevels--; } } // write for Enum Class Desc only, which is different from other classes - private ObjectStreamClass writeEnumDesc(Class<?> theClass, boolean unshared) + private ObjectStreamClass writeEnumDesc(Class<?> theClass, ObjectStreamClass classDesc, boolean unshared) throws IOException { // write classDesc, classDesc for enum is different - ObjectStreamClass classDesc = ObjectStreamClass.lookup(theClass); + // set flag for enum, the flag is (SC_SERIALIZABLE | SC_ENUM) classDesc.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM)); - Integer previousHandle = objectsWritten.get(classDesc); + Integer previousHandle = null; + if (unshared) { + previousHandle = objectsWritten.get(classDesc); + } Integer handle = null; if (!unshared) { handle = dumpCycle(classDesc); @@ -2092,7 +1876,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, Class<?> classToWrite = classDesc.forClass(); // If we got here, it is a new (non-null) classDesc that will have // to be registered as well - registerObjectWritten(classDesc); + objectsWritten.put(classDesc, nextHandle()); output.writeByte(TC_CLASSDESC); if (protocolVersion == PROTOCOL_VERSION_1) { @@ -2109,11 +1893,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, drain(); // flush primitive types in the annotation output.writeByte(TC_ENDBLOCKDATA); // write super class - ObjectStreamClass superClass = classDesc.getSuperclass(); - if (null != superClass) { + ObjectStreamClass superClassDesc = classDesc.getSuperclass(); + if (null != superClassDesc) { // super class is also enum - superClass.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM)); - writeEnumDesc(superClass.forClass(), unshared); + superClassDesc.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM)); + writeEnumDesc(superClassDesc.forClass(), superClassDesc, unshared); } else { output.writeByte(TC_NULL); } @@ -2137,18 +1921,26 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, // write enum only theClass = theClass.getSuperclass(); } - ObjectStreamClass classDesc = writeEnumDesc(theClass, unshared); + ObjectStreamClass classDesc = ObjectStreamClass.lookup(theClass); + writeEnumDesc(theClass, classDesc, unshared); - Integer previousHandle = objectsWritten.get(object); - Integer handle = registerObjectWritten(object); + Integer previousHandle = null; + if (unshared) { + previousHandle = objectsWritten.get(object); + } + Integer handle = nextHandle(); + objectsWritten.put(object, handle); ObjectStreamField[] fields = classDesc.getSuperclass().fields(); Class<?> declaringClass = classDesc.getSuperclass().forClass(); // Only write field "name" for enum class, which is the second field of // enum, that is fields[1]. Ignore all non-fields and fields.length < 2 if (null != fields && fields.length > 1) { + // BEGIN android-changed String str = (String) getFieldObj(object, declaringClass, fields[1] .getName(), fields[1].getTypeString()); + // END android-changed + Integer strhandle = null; if (!unshared) { strhandle = dumpCycle(str); @@ -2169,31 +1961,26 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Method to be overridden by subclasses to write {@code object} to the * target stream. - * + * * @param object * the object to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ protected void writeObjectOverride(Object object) throws IOException { - // BEGIN android-changed - // copied from newer version of harmony if (!subclassOverridingImplementation) { // Subclasses must override. throw new IOException(); } - // END android-changed } /** * Writes a short (16 bit) to the target stream. - * + * * @param value * the short to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeShort(int value) throws IOException { checkWritePrimitiveTypes(); @@ -2202,10 +1989,9 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes the {@link ObjectOutputStream} header to the target stream. - * + * * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ protected void writeStreamHeader() throws IOException { output.writeShort(STREAM_MAGIC); @@ -2215,12 +2001,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, /** * Writes a string encoded with {@link DataInput modified UTF-8} to the * target stream. - * + * * @param value * the string to write to the target stream. * @throws IOException * if an error occurs while writing to the target stream. - * @since Android 1.0 */ public void writeUTF(String value) throws IOException { checkWritePrimitiveTypes(); diff --git a/luni/src/main/java/java/io/ObjectStreamClass.java b/luni/src/main/java/java/io/ObjectStreamClass.java index 37b1f17..ac356ea 100644 --- a/luni/src/main/java/java/io/ObjectStreamClass.java +++ b/luni/src/main/java/java/io/ObjectStreamClass.java @@ -22,6 +22,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; import java.security.AccessController; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -33,18 +34,17 @@ import java.util.WeakHashMap; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; +import org.apache.harmony.luni.util.ThreadLocalCache; /** * Represents a descriptor for identifying a class during serialization and * deserialization. Information contained in the descriptor includes the name * and SUID of the class as well as field names and types. Information inherited * from the superclasses is also taken into account. - * + * * @see ObjectOutputStream * @see ObjectInputStream * @see java.lang.Class - * - * @since Android 1.0 */ public class ObjectStreamClass implements Serializable { @@ -55,6 +55,8 @@ public class ObjectStreamClass implements Serializable { // Name of the field that contains the SUID value (if present) private static final String UID_FIELD_NAME = "serialVersionUID"; //$NON-NLS-1$ + static final long CONSTRUCTOR_IS_NOT_RESOLVED = -1; + private static final int CLASS_MODIFIERS_MASK; private static final int FIELD_MODIFIERS_MASK; @@ -98,8 +100,6 @@ public class ObjectStreamClass implements Serializable { /** * Constant indicating that the class has no Serializable fields. - * - * @since Android 1.0 */ public static final ObjectStreamField[] NO_FIELDS = new ObjectStreamField[0]; @@ -135,9 +135,36 @@ public class ObjectStreamClass implements Serializable { static final Class<ObjectStreamClass> OBJECTSTREAMCLASSCLASS = ObjectStreamClass.class; - // Table mapping instances of java.lang.Class to to corresponding instances - // of ObjectStreamClass - private static final WeakHashMap<Class<?>, ObjectStreamClass> classesAndDescriptors = new WeakHashMap<Class<?>, ObjectStreamClass>(); + private transient Method methodWriteReplace; + + private transient Method methodReadResolve; + + private transient Method methodWriteObject; + + private transient Method methodReadObject; + + private transient Method methodReadObjectNoData; + + /** + * Indicates whether the class properties resolved + * + * @see #resolveProperties() + */ + private transient boolean arePropertiesResolved; + + /** + * Cached class properties + * + * @see #resolveProperties() + * @see #isSerializable() + * @see #isExternalizable() + * @see #isProxy() + * @see #isEnum() + */ + private transient boolean isSerializable; + private transient boolean isExternalizable; + private transient boolean isProxy; + private transient boolean isEnum; // ClassDesc // @@ -167,6 +194,17 @@ public class ObjectStreamClass implements Serializable { // Array of ObjectStreamField describing the serialized fields of this class private transient ObjectStreamField[] loadFields; + // MethodID for deserialization constructor + private transient long constructor = CONSTRUCTOR_IS_NOT_RESOLVED; + + void setConstructor(long newConstructor) { + constructor = newConstructor; + } + + long getConstructor() { + return constructor; + } + /* * If an ObjectStreamClass describes an Externalizable class, it (the * descriptor) should not have field descriptors (ObjectStreamField) at all. @@ -183,22 +221,24 @@ public class ObjectStreamClass implements Serializable { } /** - * Adds an extra entry mapping a given class {@code cl} to its class - * descriptor, which will be computed (an ObjectStreamClass). If - * {@code computeSUID} is true, this method will compute the SUID for - * this class. - * + * Compute class descriptor for a given class <code>cl</code>. + * * @param cl * a java.langClass for which to compute the corresponding * descriptor - * @param computeSUID - * a boolean indicating if SUID should be computed or not. * @return the computer class descriptor */ - private static ObjectStreamClass addToCache(Class<?> cl, boolean computeSUID) { + private static ObjectStreamClass createClassDesc(Class<?> cl) { ObjectStreamClass result = new ObjectStreamClass(); + boolean isArray = cl.isArray(); + boolean serializable = isSerializable(cl); + boolean externalizable = isExternalizable(cl); + + result.isSerializable = serializable; + result.isExternalizable = externalizable; + // Now we fill in the values result.setName(cl.getName()); result.setClass(cl); @@ -208,45 +248,73 @@ public class ObjectStreamClass implements Serializable { } Field[] declaredFields = null; - if (computeSUID) { - // Lazy computation, to save speed & space - declaredFields = cl.getDeclaredFields(); - result.setSerialVersionUID((cl.isEnum() || (cl == Enum.class)) ? 0 - : computeSerialVersionUID(cl, declaredFields)); + + // Compute the SUID + if(serializable || externalizable) { + if (result.isEnum() || result.isProxy()) { + result.setSerialVersionUID(0L); + } else { + declaredFields = cl.getDeclaredFields(); + result.setSerialVersionUID(computeSerialVersionUID(cl, + declaredFields)); + } } - boolean serializable = isSerializable(cl); // Serializables need field descriptors - if (serializable && !cl.isArray()) { + if (serializable && !isArray) { if (declaredFields == null) { - declaredFields = cl.getDeclaredFields(); } result.buildFieldDescriptors(declaredFields); } else { // Externalizables or arrays do not need FieldDesc info - result.setFields(new ObjectStreamField[0]); + result.setFields(NO_FIELDS); + } + + // Copy all fields to loadFields - they should be read by default in + // ObjectInputStream.defaultReadObject() method + ObjectStreamField[] fields = result.getFields(); + + if (fields != null) { + ObjectStreamField[] loadFields = new ObjectStreamField[fields.length]; + + for (int i = 0; i < fields.length; ++i) { + loadFields[i] = new ObjectStreamField(fields[i].getName(), + fields[i].getType(), fields[i].isUnshared()); + + // resolve type string to init typeString field in + // ObjectStreamField + loadFields[i].getTypeString(); + } + result.setLoadFields(loadFields); } byte flags = 0; - boolean externalizable = isExternalizable(cl); if (externalizable) { flags |= ObjectStreamConstants.SC_EXTERNALIZABLE; + flags |= ObjectStreamConstants.SC_BLOCK_DATA; // use protocol version 2 by default } else if (serializable) { flags |= ObjectStreamConstants.SC_SERIALIZABLE; } - if (getPrivateWriteObjectMethod(cl) != null) { + result.methodWriteReplace = findMethod(cl, "writeReplace"); //$NON-NLS-1$ + result.methodReadResolve = findMethod(cl, "readResolve"); //$NON-NLS-1$ + result.methodWriteObject = findPrivateMethod(cl, "writeObject", //$NON-NLS-1$ + WRITE_PARAM_TYPES); + result.methodReadObject = findPrivateMethod(cl, "readObject", //$NON-NLS-1$ + READ_PARAM_TYPES); + result.methodReadObjectNoData = findPrivateMethod(cl, + "readObjectNoData", EMPTY_CONSTRUCTOR_PARAM_TYPES); //$NON-NLS-1$ + if (result.hasMethodWriteObject()) { flags |= ObjectStreamConstants.SC_WRITE_METHOD; } result.setFlags(flags); - classesAndDescriptors.put(cl, result); return result; } /** * Builds the collection of field descriptors for the receiver - * + * * @param declaredFields * collection of java.lang.reflect.Field for which to compute * field descriptors @@ -315,12 +383,12 @@ public class ObjectStreamClass implements Serializable { } fields = _fields; } - + /** * Compute and return the Serial Version UID of the class {@code cl}. * The value is computed based on the class name, superclass chain, field * names, method names, modifiers, etc. - * + * * @param cl * a java.lang.Class for which to compute the SUID * @param fields @@ -477,7 +545,7 @@ public class ObjectStreamClass implements Serializable { /* * write name, modifier & "descriptor" of all but private * ones - * + * * constructor.getName() returns the constructor name as * typed, not the VM name */ @@ -534,7 +602,7 @@ public class ObjectStreamClass implements Serializable { /** * Returns what the serializaton specification calls "descriptor" given a * field signature. - * + * * @param signature * a field signature * @return containing the descriptor @@ -546,7 +614,7 @@ public class ObjectStreamClass implements Serializable { /** * Return what the serializaton specification calls "descriptor" given a * method/constructor signature. - * + * * @param signature * a method or constructor signature * @return containing the descriptor @@ -558,7 +626,7 @@ public class ObjectStreamClass implements Serializable { /** * Return the java.lang.reflect.Field {@code serialPersistentFields} * if class {@code cl} implements it. Return null otherwise. - * + * * @param cl * a java.lang.Class which to test * @return {@code java.lang.reflect.Field} if the class has @@ -583,10 +651,9 @@ public class ObjectStreamClass implements Serializable { /** * Returns the class (java.lang.Class) for this descriptor. - * + * * @return the class in the local VM that this descriptor represents; * {@code null} if there is no corresponding class. - * @since Android 1.0 */ public Class<?> forClass() { if (resolvedClass != null) { @@ -597,7 +664,7 @@ public class ObjectStreamClass implements Serializable { /** * Return a String representing the signature for a Constructor {@code c}. - * + * * @param c * a java.lang.reflect.Constructor for which to compute the * signature @@ -608,12 +675,11 @@ public class ObjectStreamClass implements Serializable { /** * Gets a field descriptor of the class represented by this class * descriptor. - * + * * @param name * the name of the desired field. * @return the field identified by {@code name} or {@code null} if there is * no such field. - * @since Android 1.0 */ public ObjectStreamField getField(String name) { ObjectStreamField[] allFields = getFields(); @@ -629,20 +695,18 @@ public class ObjectStreamClass implements Serializable { /** * Returns the collection of field descriptors for the fields of the * corresponding class - * + * * @return the receiver's collection of declared fields for the class it * represents */ ObjectStreamField[] fields() { if (fields == null) { - synchronized(this){ - Class<?> forCl = forClass(); - if (forCl != null && isSerializable(forCl) && !forCl.isArray()) { - buildFieldDescriptors(forCl.getDeclaredFields()); - } else { - // Externalizables or arrays do not need FieldDesc info - setFields(new ObjectStreamField[0]); - } + Class<?> forCl = forClass(); + if (forCl != null && isSerializable() && !forCl.isArray()) { + buildFieldDescriptors(forCl.getDeclaredFields()); + } else { + // Externalizables or arrays do not need FieldDesc info + setFields(NO_FIELDS); } } return fields; @@ -651,10 +715,9 @@ public class ObjectStreamClass implements Serializable { /** * Returns a collection of field descriptors for the serialized fields of * the class represented by this class descriptor. - * + * * @return an array of field descriptors or an array of length zero if there * are no fields in this descriptor's class. - * @since Android 1.0 */ public ObjectStreamField[] getFields() { copyFieldAttributes(); @@ -662,9 +725,9 @@ public class ObjectStreamClass implements Serializable { } /** - * If a Class uses "serialPersistentFields" to define the serialized fields, + * If a Class uses "serialPersistentFields" to define the serialized fields, * this.loadFields cannot get the "unshared" information when deserializing - * fields using current implementation of ObjectInputStream. This method + * fields using current implementation of ObjectInputStream. This method * provides a way to copy the "unshared" attribute from this.fields. * */ @@ -672,7 +735,7 @@ public class ObjectStreamClass implements Serializable { if ((loadFields == null) || fields == null) { return; } - + for (int i = 0; i < loadFields.length; i++) { ObjectStreamField loadField = loadFields[i]; String name = loadField.getName(); @@ -690,7 +753,7 @@ public class ObjectStreamClass implements Serializable { /** * Returns the collection of field descriptors for the input fields of the * corresponding class - * + * * @return the receiver's collection of input fields for the class it * represents */ @@ -700,7 +763,7 @@ public class ObjectStreamClass implements Serializable { /** * Return a String representing the signature for a field {@code f}. - * + * * @param f * a java.lang.reflect.Field for which to compute the signature * @return the field's signature @@ -709,11 +772,11 @@ public class ObjectStreamClass implements Serializable { /** * Returns the flags for this descriptor, where possible combined values are - * + * * ObjectStreamConstants.SC_WRITE_METHOD * ObjectStreamConstants.SC_SERIALIZABLE * ObjectStreamConstants.SC_EXTERNALIZABLE - * + * * @return byte the receiver's flags for the class it represents */ byte getFlags() { @@ -722,7 +785,7 @@ public class ObjectStreamClass implements Serializable { /** * Return a String representing the signature for a method {@code m}. - * + * * @param m * a java.lang.reflect.Method for which to compute the signature * @return the method's signature @@ -731,9 +794,8 @@ public class ObjectStreamClass implements Serializable { /** * Returns the name of the class represented by this descriptor. - * + * * @return the fully qualified name of the class this descriptor represents. - * @since Android 1.0 */ public String getName() { return className; @@ -742,9 +804,8 @@ public class ObjectStreamClass implements Serializable { /** * Returns the Serial Version User ID of the class represented by this * descriptor. - * + * * @return the SUID for the class represented by this descriptor. - * @since Android 1.0 */ public long getSerialVersionUID() { return svUID; @@ -753,7 +814,7 @@ public class ObjectStreamClass implements Serializable { /** * Returns the descriptor (ObjectStreamClass) of the superclass of the class * represented by the receiver. - * + * * @return an ObjectStreamClass representing the superclass of the class * represented by the receiver. */ @@ -767,7 +828,7 @@ public class ObjectStreamClass implements Serializable { * compiler-generated, it is used by the serialization code to compute SUID. * This is unfortunate, since it may depend on compiler optimizations in * some cases. - * + * * @param cl * a java.lang.Class which to test * @return {@code true} if the class has <clinit> {@code false} @@ -776,84 +837,15 @@ public class ObjectStreamClass implements Serializable { private static native boolean hasClinit(Class<?> cl); /** - * Return true if the given class {@code cl} implements private - * method {@code readObject()}. - * - * @param cl - * a java.lang.Class which to test - * @return {@code true} if the class implements readObject - * {@code false} if the class does not implement readObject - */ - static Method getPrivateReadObjectMethod(Class<?> cl) { - try { - Method method = cl - .getDeclaredMethod("readObject", READ_PARAM_TYPES); //$NON-NLS-1$ - if (Modifier.isPrivate(method.getModifiers()) - && method.getReturnType() == VOID_CLASS) { - return method; - } - } catch (NoSuchMethodException nsm) { - // Ignored - } - return null; - } - - /** - * Return true if the given class {@code cl} implements private - * method {@code readObject()}. - * - * @param cl - * a java.lang.Class which to test - * @return {@code true} if the class implements readObject - * {@code false} if the class does not implement readObject - */ - static Method getPrivateReadObjectNoDataMethod(Class<?> cl) { - try { - Method method = cl.getDeclaredMethod("readObjectNoData", //$NON-NLS-1$ - EMPTY_CONSTRUCTOR_PARAM_TYPES); - if (Modifier.isPrivate(method.getModifiers()) - && method.getReturnType() == VOID_CLASS) { - return method; - } - } catch (NoSuchMethodException nsm) { - // Ignored - } - return null; - } - - /** - * Return true if the given class {@code cl} implements private - * method {@code writeObject()}. - * - * @param cl - * a java.lang.Class which to test - * @return {@code true} if the class implements writeObject - * {@code false} if the class does not implement writeObject - */ - static Method getPrivateWriteObjectMethod(Class<?> cl) { - try { - Method method = cl.getDeclaredMethod("writeObject", //$NON-NLS-1$ - WRITE_PARAM_TYPES); - if (Modifier.isPrivate(method.getModifiers()) - && method.getReturnType() == VOID_CLASS) { - return method; - } - } catch (NoSuchMethodException nsm) { - // Ignored - } - return null; - } - - /** * Return true if instances of class {@code cl} are Externalizable, * false otherwise. - * + * * @param cl * a java.lang.Class which to test * @return {@code true} if instances of the class are Externalizable * {@code false} if instances of the class are not * Externalizable - * + * * @see Object#hashCode */ static boolean isExternalizable(Class<?> cl) { @@ -865,7 +857,7 @@ public class ObjectStreamClass implements Serializable { * <code>typecode<code> describes a primitive type * * @param typecode a char describing the typecode - * @return {@code true} if the typecode represents a primitive type + * @return {@code true} if the typecode represents a primitive type * {@code false} if the typecode represents an Object type (including arrays) * * @see Object#hashCode @@ -877,13 +869,13 @@ public class ObjectStreamClass implements Serializable { /** * Return true if instances of class {@code cl} are Serializable, * false otherwise. - * + * * @param cl * a java.lang.Class which to test * @return {@code true} if instances of the class are Serializable * {@code false} if instances of the class are not * Serializable - * + * * @see Object#hashCode */ static boolean isSerializable(Class<?> cl) { @@ -891,8 +883,65 @@ public class ObjectStreamClass implements Serializable { } /** + * Resolves the class properties, if they weren't already + */ + private void resolveProperties() { + if (arePropertiesResolved) { + return; + } + + Class<?> cl = forClass(); + isProxy = Proxy.isProxyClass(cl); + isEnum = Enum.class.isAssignableFrom(cl); + isSerializable = isSerializable(cl); + isExternalizable = isExternalizable(cl); + + arePropertiesResolved = true; + } + + /** + * Answers whether the class for this descriptor is serializable + * + * @return true if class implements Serializable + */ + boolean isSerializable() { + resolveProperties(); + return isSerializable; + } + + /** + * Answers whether the class for this descriptor is serializable + * + * @return true if class implements Serializable + */ + boolean isExternalizable() { + resolveProperties(); + return isExternalizable; + } + + /** + * Answers whether the class for this descriptor is proxied class + * + * @return true if class is proxied + */ + boolean isProxy() { + resolveProperties(); + return isProxy; + } + + /** + * Answers whether the class for this descriptor is subclass of Enum + * + * @return true if class is subclass of Enum + */ + boolean isEnum() { + resolveProperties(); + return isEnum; + } + + /** * Return a little endian long stored in a given position of the buffer - * + * * @param buffer * a byte array with the byte representation of the number * @param position @@ -911,83 +960,67 @@ public class ObjectStreamClass implements Serializable { * Returns the descriptor corresponding to the class {@code cl}. If the * class is not serializable or externalizable then {@code null} is * returned. - * + * * @param cl * a java.langClass for which to obtain the corresponding * descriptor * @return the corresponding descriptor if the {@code cl} is serializable or * externalizable; {@code null} otherwise. - * @since Android 1.0 */ public static ObjectStreamClass lookup(Class<?> cl) { - boolean serializable = isSerializable(cl); - boolean externalizable = isExternalizable(cl); + ObjectStreamClass osc = lookupStreamClass(cl); - // Has to be either Serializable or Externalizable - if (!serializable && !externalizable) { - return null; + if (osc.isSerializable() || osc.isExternalizable()) { + return osc; } - return lookupStreamClass(cl, true); + return null; } /** * Return the descriptor (ObjectStreamClass) corresponding to the class * {@code cl}. Returns an ObjectStreamClass even if instances of the * class cannot be serialized - * + * * @param cl * a java.langClass for which to obtain the corresponding * descriptor * @return the corresponding descriptor */ static ObjectStreamClass lookupStreamClass(Class<?> cl) { - return lookupStreamClass(cl, isSerializable(cl) || isExternalizable(cl)); - } - /** - * Return the descriptor (ObjectStreamClass) corresponding to the class - * {@code cl}. Returns an ObjectStreamClass even if instances of the - * class cannot be serialized - * - * @param cl - * a {@code java.langClass} for which to obtain the - * corresponding descriptor - * @param computeSUID - * a boolean indicating if SUID should be computed or not. - * @return the corresponding descriptor - */ - private static synchronized ObjectStreamClass lookupStreamClass( - Class<?> cl, boolean computeSUID) { - // Synchronized because of the lookup table 'classesAndDescriptors' - ObjectStreamClass cachedValue = classesAndDescriptors.get(cl); - if (cachedValue != null) { - return cachedValue; + WeakHashMap<Class<?>,ObjectStreamClass> tlc = OSCThreadLocalCache.oscWeakHashMap.get(); + + ObjectStreamClass cachedValue = tlc.get(cl); + if (cachedValue == null) { + cachedValue = createClassDesc(cl); + tlc.put(cl, cachedValue); } - return addToCache(cl, computeSUID); + return cachedValue; + } /** - * Return the java.lang.reflect.Method {@code readResolve} if class - * {@code cl} implements it. Return null otherwise. - * + * Return the java.lang.reflect.Method if class <code>cl</code> implements + * <code>methodName</code> . Return null otherwise. + * * @param cl * a java.lang.Class which to test - * @return {@code java.lang.reflect.Method} if the class implements - * readResolve {@code null} if the class does not implement - * readResolve + * @return <code>java.lang.reflect.Method</code> if the class implements + * writeReplace <code>null</code> if the class does not implement + * writeReplace */ - static Method methodReadResolve(Class<?> cl) { + static Method findMethod(Class<?> cl, String methodName) { Class<?> search = cl; + Method method = null; while (search != null) { try { - Method method = search.getDeclaredMethod( - "readResolve", (Class[]) null); //$NON-NLS-1$ + method = search.getDeclaredMethod(methodName, (Class[]) null); if (search == cl || (method.getModifiers() & Modifier.PRIVATE) == 0) { + method.setAccessible(true); return method; } - return null; } catch (NoSuchMethodException nsm) { } search = search.getSuperclass(); @@ -996,37 +1029,81 @@ public class ObjectStreamClass implements Serializable { } /** - * Return the java.lang.reflect.Method {@code writeReplace} if class - * {@code cl} implements it. Return null otherwise. - * + * Return the java.lang.reflect.Method if class <code>cl</code> implements + * private <code>methodName</code> . Return null otherwise. + * * @param cl * a java.lang.Class which to test * @return {@code java.lang.reflect.Method} if the class implements * writeReplace {@code null} if the class does not implement * writeReplace */ - static Method methodWriteReplace(Class<?> cl) { - Class<?> search = cl; - while (search != null) { - try { - Method method = search.getDeclaredMethod( - "writeReplace", (Class[]) null); //$NON-NLS-1$ - if (search == cl - || (method.getModifiers() & Modifier.PRIVATE) == 0) { - return method; - } - return null; - } catch (NoSuchMethodException nsm) { - // Ignored + static Method findPrivateMethod(Class<?> cl, String methodName, + Class<?>[] param) { + try { + Method method = cl.getDeclaredMethod(methodName, param); + if (Modifier.isPrivate(method.getModifiers()) + && method.getReturnType() == VOID_CLASS) { + method.setAccessible(true); + return method; } - search = search.getSuperclass(); + } catch (NoSuchMethodException nsm) { + // Ignored } return null; } + boolean hasMethodWriteReplace() { + return (methodWriteReplace != null); + } + + Method getMethodWriteReplace() { + return methodWriteReplace; + } + + boolean hasMethodReadResolve() { + return (methodReadResolve != null); + } + + Method getMethodReadResolve() { + return methodReadResolve; + } + + boolean hasMethodWriteObject() { + return (methodWriteObject != null); + } + + Method getMethodWriteObject() { + return methodWriteObject; + } + + boolean hasMethodReadObject() { + return (methodReadObject != null); + } + + Method getMethodReadObject() { + return methodReadObject; + } + + boolean hasMethodReadObjectNoData() { + return (methodReadObjectNoData != null); + } + + Method getMethodReadObjectNoData() { + return methodReadObjectNoData; + } + + void initPrivateFields(ObjectStreamClass desc) { + methodWriteReplace = desc.methodWriteReplace; + methodReadResolve = desc.methodReadResolve; + methodWriteObject = desc.methodWriteObject; + methodReadObject = desc.methodReadObject; + methodReadObjectNoData = desc.methodReadObjectNoData; + } + /** * Set the class (java.lang.Class) that the receiver represents - * + * * @param c * aClass, the new class that the receiver describes */ @@ -1037,7 +1114,7 @@ public class ObjectStreamClass implements Serializable { /** * Set the collection of field descriptors for the fields of the * corresponding class - * + * * @param f * ObjectStreamField[], the receiver's new collection of declared * fields for the class it represents @@ -1049,7 +1126,7 @@ public class ObjectStreamClass implements Serializable { /** * Set the collection of field descriptors for the input fields of the * corresponding class - * + * * @param f * ObjectStreamField[], the receiver's new collection of input * fields for the class it represents @@ -1060,11 +1137,11 @@ public class ObjectStreamClass implements Serializable { /** * Set the flags for this descriptor, where possible combined values are - * + * * ObjectStreamConstants.SC_WRITE_METHOD * ObjectStreamConstants.SC_SERIALIZABLE * ObjectStreamConstants.SC_EXTERNALIZABLE - * + * * @param b * byte, the receiver's new flags for the class it represents */ @@ -1074,7 +1151,7 @@ public class ObjectStreamClass implements Serializable { /** * Set the name of the class represented by the receiver - * + * * @param newName * a String, the new fully qualified name of the class the * receiver represents @@ -1085,7 +1162,7 @@ public class ObjectStreamClass implements Serializable { /** * Set the Serial Version User ID of the class represented by the receiver - * + * * @param l * a long, the new SUID for the class represented by the receiver */ @@ -1096,7 +1173,7 @@ public class ObjectStreamClass implements Serializable { /** * Set the descriptor for the superclass of the class described by the * receiver - * + * * @param c * an ObjectStreamClass, the new ObjectStreamClass for the * superclass of the class represented by the receiver @@ -1124,13 +1201,24 @@ public class ObjectStreamClass implements Serializable { /** * Returns a string containing a concise, human-readable description of this * descriptor. - * + * * @return a printable representation of this descriptor. - * @since Android 1.0 */ @Override public String toString() { return getName() + ": static final long serialVersionUID =" //$NON-NLS-1$ + getSerialVersionUID() + "L;"; //$NON-NLS-1$ } + + static class OSCThreadLocalCache extends ThreadLocalCache { + + // thread-local cache for ObjectStreamClass.lookup + public static ThreadLocalCache<WeakHashMap<Class<?>,ObjectStreamClass>> oscWeakHashMap = new ThreadLocalCache<WeakHashMap<Class<?>,ObjectStreamClass>>() { + protected WeakHashMap<Class<?>,ObjectStreamClass> initialValue() { + return new WeakHashMap<Class<?>,ObjectStreamClass>(); + } + }; + + } + } diff --git a/luni/src/main/java/java/io/ObjectStreamConstants.java b/luni/src/main/java/java/io/ObjectStreamConstants.java index 8f7ad66..01b0109 100644 --- a/luni/src/main/java/java/io/ObjectStreamConstants.java +++ b/luni/src/main/java/java/io/ObjectStreamConstants.java @@ -19,168 +19,122 @@ package java.io; /** * A helper interface with constants used by the serialization implementation. - * - * @since Android 1.0 */ public abstract interface ObjectStreamConstants { /** * The stream header's magic number. - * - * @since Android 1.0 */ public static final short STREAM_MAGIC = (short) 0xaced; /** * The stream header's version number. - * - * @since Android 1.0 */ public static final short STREAM_VERSION = 5; // These are tags to indicate the stream contents - + /** * The minimum tag value. - * - * @since Android 1.0 */ public static final byte TC_BASE = 0x70; /** * Tag to mark a {@code null} object reference. - * - * @since Android 1.0 */ public static final byte TC_NULL = (byte) 0x70; /** * Tag to mark a reference to an object that has already been written to the * stream. - * - * @since Android 1.0 */ public static final byte TC_REFERENCE = (byte) 0x71; /** * Tag to mark a new class descriptor. - * - * @since Android 1.0 */ public static final byte TC_CLASSDESC = (byte) 0x72; /** * Tag to mark a new object. - * - * @since Android 1.0 */ public static final byte TC_OBJECT = (byte) 0x73; /** * Tag to mark a new string. - * - * @since Android 1.0 */ public static final byte TC_STRING = (byte) 0x74; /** * Tag to mark a new array. - * - * @since Android 1.0 */ public static final byte TC_ARRAY = (byte) 0x75; /** * Tag to mark a reference to a class. - * - * @since Android 1.0 */ public static final byte TC_CLASS = (byte) 0x76; /** * Tag to mark a block of optional data. The byte following this tag * indicates the size of the block. - * - * @since Android 1.0 */ public static final byte TC_BLOCKDATA = (byte) 0x77; /** * Tag to mark the end of block data blocks for an object. - * - * @since Android 1.0 */ public static final byte TC_ENDBLOCKDATA = (byte) 0x78; /** * Tag to mark a stream reset. - * - * @since Android 1.0 */ public static final byte TC_RESET = (byte) 0x79; /** * Tag to mark a long block of data. The long following this tag * indicates the size of the block. - * - * @since Android 1.0 */ public static final byte TC_BLOCKDATALONG = (byte) 0x7A; /** * Tag to mark an exception. - * - * @since Android 1.0 */ public static final byte TC_EXCEPTION = (byte) 0x7B; /** * Tag to mark a long string. - * - * @since Android 1.0 */ public static final byte TC_LONGSTRING = (byte) 0x7C; /** * Tag to mark a new proxy class descriptor. - * - * @since Android 1.0 */ public static final byte TC_PROXYCLASSDESC = (byte) 0x7D; /** * The maximum tag value. - * - * @since Android 1.0 */ public static final byte TC_MAX = 0x7E; /** * Handle for the first object that gets serialized. - * - * @since Android 1.0 */ public static final int baseWireHandle = 0x007e0000; /** * Stream protocol version 1. - * - * @since Android 1.0 */ public static final int PROTOCOL_VERSION_1 = 1; /** * Stream protocol version 2. - * - * @since Android 1.0 */ public static final int PROTOCOL_VERSION_2 = 2; /** * Permission constant to enable subclassing of ObjectInputStream and * ObjectOutputStream. - * - * @since Android 1.0 */ public static final SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION = new SerializablePermission( "enableSubclassImplementation"); //$NON-NLS-1$ @@ -188,8 +142,6 @@ public abstract interface ObjectStreamConstants { /** * Permission constant to enable object substitution during serialization * and deserialization. - * - * @since Android 1.0 */ public static final SerializablePermission SUBSTITUTION_PERMISSION = new SerializablePermission( "enableSubstitution"); //$NON-NLS-1$ @@ -199,47 +151,35 @@ public abstract interface ObjectStreamConstants { /** * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates * that a serializable class has its own {@code writeObject} method. - * - * @since Android 1.0 */ public static final byte SC_WRITE_METHOD = 0x01; // If SC_SERIALIZABLE /** * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates * that a class is serializable. - * - * @since Android 1.0 */ public static final byte SC_SERIALIZABLE = 0x02; /** * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates * that a class is externalizable. - * - * @since Android 1.0 */ public static final byte SC_EXTERNALIZABLE = 0x04; /** * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates * that an externalizable class is written in block data mode. - * - * @since Android 1.0 */ public static final byte SC_BLOCK_DATA = 0x08; // If SC_EXTERNALIZABLE /** * Tag to mark a new enum. - * - * @since Android 1.0 */ public static final byte TC_ENUM = 0x7E; /** * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates * that a class is an enum type. - * - * @since Android 1.0 */ public static final byte SC_ENUM = 0x10; } diff --git a/luni/src/main/java/java/io/ObjectStreamException.java b/luni/src/main/java/java/io/ObjectStreamException.java index a06b102..c3ad7dc 100644 --- a/luni/src/main/java/java/io/ObjectStreamException.java +++ b/luni/src/main/java/java/io/ObjectStreamException.java @@ -28,8 +28,6 @@ package java.io; * @see OptionalDataException * @see StreamCorruptedException * @see WriteAbortedException - * - * @since Android 1.0 */ public abstract class ObjectStreamException extends IOException { @@ -38,8 +36,6 @@ public abstract class ObjectStreamException extends IOException { /** * Constructs a new {@code ObjectStreamException} with its stack trace * filled in. - * - * @since Android 1.0 */ protected ObjectStreamException() { super(); @@ -51,7 +47,6 @@ public abstract class ObjectStreamException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ protected ObjectStreamException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/ObjectStreamField.java b/luni/src/main/java/java/io/ObjectStreamField.java index 95deb7b..3baebf7 100644 --- a/luni/src/main/java/java/io/ObjectStreamField.java +++ b/luni/src/main/java/java/io/ObjectStreamField.java @@ -17,22 +17,32 @@ package java.io; +// BEGIN android-note +// Harmony uses ObjectAccessors to access fields through JNI. Android has not +// yet migrated that API. +// END android-note + import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.Comparator; +// BEGIN android-removed +// import org.apache.harmony.misc.accessors.ObjectAccessor; +// END android-removed + /** * Describes a field for the purpose of serialization. Classes can define the * collection of fields that are serialized, which may be different from the set * of all declared fields. - * + * * @see ObjectOutputStream#writeFields() * @see ObjectInputStream#readFields() - * - * @since Android 1.0 */ public class ObjectStreamField implements Comparable<Object> { + static final int FIELD_IS_NOT_RESOLVED = -1; + static final int FIELD_IS_ABSENT = -2; + // Declared name of the field private String name; @@ -49,16 +59,32 @@ public class ObjectStreamField implements Comparable<Object> { private boolean isDeserialized; + private long assocFieldID = FIELD_IS_NOT_RESOLVED; + + // BEGIN android-removed + // long getFieldID(ObjectAccessor accessor, Class<?> declaringClass) { + // if (assocFieldID != FIELD_IS_NOT_RESOLVED) { + // return assocFieldID; + // } else { + // try { + // assocFieldID = accessor.getFieldID(declaringClass, name); + // } catch(NoSuchFieldError e) { + // assocFieldID = FIELD_IS_ABSENT; + // } + // return assocFieldID; + // } + // } + // END android-removed + /** * Constructs an ObjectStreamField with the specified name and type. - * + * * @param name * the name of the field. * @param cl * the type of the field. * @throws NullPointerException * if {@code name} or {@code cl} is {@code null}. - * @since Android 1.0 */ public ObjectStreamField(String name, Class<?> cl) { if (name == null || cl == null) { @@ -71,7 +97,7 @@ public class ObjectStreamField implements Comparable<Object> { /** * Constructs an ObjectStreamField with the specified name, type and the * indication if it is unshared. - * + * * @param name * the name of the field. * @param cl @@ -82,7 +108,6 @@ public class ObjectStreamField implements Comparable<Object> { * @throws NullPointerException * if {@code name} or {@code cl} is {@code null}. * @see ObjectOutputStream#writeUnshared(Object) - * @since Android 1.0 */ public ObjectStreamField(String name, Class<?> cl, boolean unshared) { if (name == null || cl == null) { @@ -97,7 +122,7 @@ public class ObjectStreamField implements Comparable<Object> { /** * Constructs an ObjectStreamField with the given name and the given type. * The type may be null. - * + * * @param signature * A String representing the type of the field * @param name @@ -117,13 +142,12 @@ public class ObjectStreamField implements Comparable<Object> { * of the compared fields has a primitive type and the other one not. If so, * the field with the primitive type is considered to be "smaller". If both * fields are equal, their names are compared. - * + * * @param o * the object to compare with. * @return -1 if this field is "smaller" than field {@code o}, 0 if both * fields are equal; 1 if this field is "greater" than field {@code * o}. - * @since Android 1.0 */ public int compareTo(Object o) { ObjectStreamField f = (ObjectStreamField) o; @@ -139,34 +163,14 @@ public class ObjectStreamField implements Comparable<Object> { // Either both primitives or both not primitives. Compare based on name. return this.getName().compareTo(f.getName()); } - + // BEGIN android-removed // There shouldn't be an implementation of these methods. - // /** - // * Indicates if this field descriptor is equal to {@code arg0}. Field - // * descriptors are equal if their name is equal. - // * - // * @param arg0 - // * the object to check equality with. - // * @return {@code true} if the name of this field descriptor is equal to the - // * name of {@code arg0}, {@code false} otherwise. - // * @since Android 1.0 - // */ // @Override // public boolean equals(Object arg0) { - // // BEGIN android-changed - // // copied from newer harmony version - // return (arg0 instanceof ObjectStreamField) && compareTo(arg0) == 0; - // // END android-changed + // return (arg0 instanceof ObjectStreamField) && (compareTo(arg0) == 0); // } - // - // /** - // * Returns a hash code for this field descriptor. The hash code of this - // * field's name is returned. - // * - // * @return the field's hash code. - // * @since Android 1.0 - // */ + // // @Override // public int hashCode() { // return getName().hashCode(); @@ -175,9 +179,8 @@ public class ObjectStreamField implements Comparable<Object> { /** * Gets the name of this field. - * + * * @return the field's name. - * @since Android 1.0 */ public String getName() { return name; @@ -185,9 +188,8 @@ public class ObjectStreamField implements Comparable<Object> { /** * Gets the offset of this field in the object. - * + * * @return this field's offset. - * @since Android 1.0 */ public int getOffset() { return offset; @@ -196,7 +198,7 @@ public class ObjectStreamField implements Comparable<Object> { /** * Return the type of the field the receiver represents, this is an internal * method - * + * * @return A Class object representing the type of the field */ // BEGIN android-note @@ -211,9 +213,8 @@ public class ObjectStreamField implements Comparable<Object> { /** * Gets the type of this field. - * + * * @return a {@code Class} object representing the type of the field. - * @since Android 1.0 */ public Class<?> getType() { Class<?> cl = getTypeInternal(); @@ -226,7 +227,7 @@ public class ObjectStreamField implements Comparable<Object> { /** * Gets a character code for the type of this field. The following codes are * used: - * + * * <pre> * B byte * C char @@ -239,9 +240,8 @@ public class ObjectStreamField implements Comparable<Object> { * Z boolean * [ array * </pre> - * + * * @return the field's type code. - * @since Android 1.0 */ public char getTypeCode() { Class<?> t = getTypeInternal(); @@ -278,10 +278,9 @@ public class ObjectStreamField implements Comparable<Object> { /** * Gets the type signature used by the VM to represent the type of this * field. - * + * * @return the signature of this field's class or {@code null} if this * field's type is primitive. - * @since Android 1.0 */ public String getTypeString() { if (isPrimitive()) { @@ -298,10 +297,9 @@ public class ObjectStreamField implements Comparable<Object> { /** * Indicates whether this field's type is a primitive type. - * + * * @return {@code true} if this field's type is primitive; {@code false} if * the type of this field is a regular class. - * @since Android 1.0 */ public boolean isPrimitive() { Class<?> t = getTypeInternal(); @@ -310,10 +308,9 @@ public class ObjectStreamField implements Comparable<Object> { /** * Sets this field's offset in the object. - * + * * @param newValue * the field's new offset. - * @since Android 1.0 */ protected void setOffset(int newValue) { this.offset = newValue; @@ -322,9 +319,8 @@ public class ObjectStreamField implements Comparable<Object> { /** * Returns a string containing a concise, human-readable description of this * field descriptor. - * + * * @return a printable representation of this descriptor. - * @since Android 1.0 */ @Override public String toString() { @@ -335,7 +331,7 @@ public class ObjectStreamField implements Comparable<Object> { /** * Sorts the fields for dumping. Primitive types come first, then regular * types. - * + * * @param fields * ObjectStreamField[] fields to be sorted */ @@ -396,9 +392,8 @@ public class ObjectStreamField implements Comparable<Object> { /** * Indicats whether this field is unshared. - * + * * @return {@code true} if this field is unshared, {@code false} otherwise. - * @since Android 1.0 */ public boolean isUnshared() { return unshared; diff --git a/luni/src/main/java/java/io/OptionalDataException.java b/luni/src/main/java/java/io/OptionalDataException.java index 891bfdd..39d3d5d 100644 --- a/luni/src/main/java/java/io/OptionalDataException.java +++ b/luni/src/main/java/java/io/OptionalDataException.java @@ -25,8 +25,6 @@ package java.io; * @see ObjectInputStream#available() * @see ObjectInputStream#readObject() * @see ObjectInputStream#skipBytes(int) - * - * @since Android 1.0 */ public class OptionalDataException extends ObjectStreamException { @@ -34,24 +32,18 @@ public class OptionalDataException extends ObjectStreamException { /** * {@code true} indicates that there is no more primitive data available. - * - * @since Android 1.0 */ public boolean eof; /** * The number of bytes of primitive data (int, char, long etc.) that are * available. - * - * @since Android 1.0 */ public int length; /** * Constructs a new {@code OptionalDataException} with its stack trace * filled in. - * - * @since Android 1.0 */ OptionalDataException() { super(); @@ -63,7 +55,6 @@ public class OptionalDataException extends ObjectStreamException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ OptionalDataException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/OutputStream.java b/luni/src/main/java/java/io/OutputStream.java index 5531ab5..2172411 100644 --- a/luni/src/main/java/java/io/OutputStream.java +++ b/luni/src/main/java/java/io/OutputStream.java @@ -32,17 +32,13 @@ import org.apache.harmony.luni.util.Msg; * <p> * Many specialized output streams for purposes like writing to a file already * exist in this package. - * + * * @see InputStream - * - * @since Android 1.0 */ public abstract class OutputStream implements Closeable, Flushable { /** * Default constructor. - * - * @since Android 1.0 */ public OutputStream() { super(); @@ -51,10 +47,9 @@ public abstract class OutputStream implements Closeable, Flushable { /** * Closes this stream. Implementations of this method should free any * resources used by the stream. This implementation does nothing. - * + * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ public void close() throws IOException { /* empty */ @@ -63,10 +58,9 @@ public abstract class OutputStream implements Closeable, Flushable { /** * Flushes this stream. Implementations of this method should ensure that * any buffered data is written out. This implementation does nothing. - * + * * @throws IOException * if an error occurs while flushing this stream. - * @since Android 1.0 */ public void flush() throws IOException { /* empty */ @@ -75,12 +69,11 @@ public abstract class OutputStream implements Closeable, Flushable { /** * Writes the entire contents of the byte array {@code buffer} to this * stream. - * + * * @param buffer * the buffer to be written. * @throws IOException * if an error occurs while writing to this stream. - * @since Android 1.0 */ public void write(byte[] buffer) throws IOException { // BEGIN android-note @@ -92,7 +85,7 @@ public abstract class OutputStream implements Closeable, Flushable { /** * Writes {@code count} bytes from the byte array {@code buffer} starting at * position {@code offset} to this stream. - * + * * @param buffer * the buffer to be written. * @param offset @@ -106,7 +99,6 @@ public abstract class OutputStream implements Closeable, Flushable { * if {@code offset < 0} or {@code count < 0}, or if * {@code offset + count} is bigger than the length of * {@code buffer}. - * @since Android 1.0 */ public void write(byte[] buffer, int offset, int count) throws IOException { // BEGIN android-note @@ -134,12 +126,11 @@ public abstract class OutputStream implements Closeable, Flushable { /** * Writes a single byte to this stream. Only the least significant byte of * the integer {@code oneByte} is written to the stream. - * + * * @param oneByte * the byte to be written. * @throws IOException * if an error occurs while writing to this stream. - * @since Android 1.0 */ public abstract void write(int oneByte) throws IOException; } diff --git a/luni/src/main/java/java/io/OutputStreamWriter.java b/luni/src/main/java/java/io/OutputStreamWriter.java index d6cc91e..6e6cc50 100644 --- a/luni/src/main/java/java/io/OutputStreamWriter.java +++ b/luni/src/main/java/java/io/OutputStreamWriter.java @@ -25,6 +25,7 @@ import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; import java.security.AccessController; +import org.apache.harmony.luni.util.HistoricalNamesUtil; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; @@ -35,10 +36,8 @@ import org.apache.harmony.luni.util.PriviAction; * "file.encoding" system property. {@code OutputStreamWriter} contains a buffer * of bytes to be written to target stream and converts these into characters as * needed. The buffer size is 8K. - * + * * @see InputStreamReader - * - * @since Android 1.0 */ public class OutputStreamWriter extends Writer { @@ -52,10 +51,9 @@ public class OutputStreamWriter extends Writer { * Constructs a new OutputStreamWriter using {@code out} as the target * stream to write converted characters to. The default character encoding * is used. - * + * * @param out * the non-null target stream to write converted bytes to. - * @since Android 1.0 */ public OutputStreamWriter(OutputStream out) { super(out); @@ -73,7 +71,7 @@ public class OutputStreamWriter extends Writer { * stream to write converted characters to and {@code enc} as the character * encoding. If the encoding cannot be found, an * UnsupportedEncodingException error is thrown. - * + * * @param out * the target stream to write converted bytes to. * @param enc @@ -82,7 +80,6 @@ public class OutputStreamWriter extends Writer { * if {@code enc} is {@code null}. * @throws UnsupportedEncodingException * if the encoding specified by {@code enc} cannot be found. - * @since Android 1.0 */ public OutputStreamWriter(OutputStream out, final String enc) throws UnsupportedEncodingException { @@ -104,12 +101,11 @@ public class OutputStreamWriter extends Writer { * Constructs a new OutputStreamWriter using {@code out} as the target * stream to write converted characters to and {@code cs} as the character * encoding. - * + * * @param out * the target stream to write converted bytes to. * @param cs * the {@code Charset} that specifies the character encoding. - * @since Android 1.0 */ public OutputStreamWriter(OutputStream out, Charset cs) { super(out); @@ -123,12 +119,11 @@ public class OutputStreamWriter extends Writer { * Constructs a new OutputStreamWriter using {@code out} as the target * stream to write converted characters to and {@code enc} as the character * encoder. - * + * * @param out * the target stream to write converted bytes to. * @param enc * the character encoder used for character conversion. - * @since Android 1.0 */ public OutputStreamWriter(OutputStream out, CharsetEncoder enc) { super(out); @@ -144,11 +139,9 @@ public class OutputStreamWriter extends Writer { * <p> * Only the first invocation of this method has any effect. Subsequent calls * do nothing. - * </p> - * + * * @throws IOException * if an error occurs while closing this writer. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -168,10 +161,9 @@ public class OutputStreamWriter extends Writer { * Flushes this writer. This implementation ensures that all buffered bytes * are written to the target stream. After writing the bytes, the target * stream is flushed as well. - * + * * @throws IOException * if an error occurs while flushing this writer. - * @since Android 1.0 */ @Override public void flush() throws IOException { @@ -197,17 +189,15 @@ public class OutputStreamWriter extends Writer { /** * Gets the name of the encoding that is used to convert characters to * bytes. - * + * * @return the string describing the converter or {@code null} if this * writer is closed. - * @since Android 1.0 */ public String getEncoding() { if (encoder == null) { return null; } - return InputStreamReader.HistoricalNamesUtil.getHistoricalName(encoder - .charset().name()); + return HistoricalNamesUtil.getHistoricalName(encoder.charset().name()); } /** @@ -215,7 +205,7 @@ public class OutputStreamWriter extends Writer { * to this writer. The characters are immediately converted to bytes by the * character converter and stored in a local buffer. If the buffer gets full * as a result of the conversion, this writer is flushed. - * + * * @param buf * the array containing characters to write. * @param offset @@ -229,7 +219,6 @@ public class OutputStreamWriter extends Writer { * @throws IOException * if this writer has already been closed or another I/O error * occurs. - * @since Android 1.0 */ @Override public void write(char[] buf, int offset, int count) throws IOException { @@ -273,12 +262,11 @@ public class OutputStreamWriter extends Writer { * of the integer {@code oneChar} are immediately converted to bytes by the * character converter and stored in a local buffer. If the buffer gets full * by converting this character, this writer is flushed. - * + * * @param oneChar * the character to write. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ @Override public void write(int oneChar) throws IOException { @@ -294,7 +282,7 @@ public class OutputStreamWriter extends Writer { * to this writer. The characters are immediately converted to bytes by the * character converter and stored in a local buffer. If the buffer gets full * as a result of the conversion, this writer is flushed. - * + * * @param str * the string containing characters to write. * @param offset @@ -308,7 +296,6 @@ public class OutputStreamWriter extends Writer { * if {@code offset < 0} or {@code count < 0}, or if * {@code offset + count} is bigger than the length of * {@code str}. - * @since Android 1.0 */ @Override public void write(String str, int offset, int count) throws IOException { diff --git a/luni/src/main/java/java/io/PipedInputStream.java b/luni/src/main/java/java/io/PipedInputStream.java index 5562c58..d06143d 100644 --- a/luni/src/main/java/java/io/PipedInputStream.java +++ b/luni/src/main/java/java/io/PipedInputStream.java @@ -23,10 +23,8 @@ import org.apache.harmony.luni.util.Msg; * Receives information from a communications pipe. When two threads want to * pass data back and forth, one creates a piped output stream and the other one * creates a piped input stream. - * + * * @see PipedOutputStream - * - * @since Android 1.0 */ public class PipedInputStream extends InputStream { @@ -36,29 +34,21 @@ public class PipedInputStream extends InputStream { /** * The circular buffer through which data is passed. - * - * @since Android 1.0 */ protected byte buffer[]; /** * The index in {@code buffer} where the next byte will be written. - * - * @since Android 1.0 */ protected int in = -1; /** * The index in {@code buffer} where the next byte will be read. - * - * @since Android 1.0 */ protected int out = 0; /** * The size of the default pipe in bytes. - * - * @since Android 1.0 */ protected static final int PIPE_SIZE = 1024; @@ -71,8 +61,6 @@ public class PipedInputStream extends InputStream { * Constructs a new unconnected {@code PipedInputStream}. The resulting * stream must be connected to a {@link PipedOutputStream} before data may * be read from it. - * - * @since Android 1.0 */ public PipedInputStream() { /* empty */ @@ -82,12 +70,11 @@ public class PipedInputStream extends InputStream { * Constructs a new {@code PipedInputStream} connected to the * {@link PipedOutputStream} {@code out}. Any data written to the output * stream can be read from the this input stream. - * + * * @param out * the piped output stream to connect to. * @throws IOException * if this stream or {@code out} are already connected. - * @since Android 1.0 */ public PipedInputStream(PipedOutputStream out) throws IOException { connect(out); @@ -97,11 +84,10 @@ public class PipedInputStream extends InputStream { * Returns the number of bytes that are available before this stream will * block. This implementation returns the number of bytes written to this * pipe that have not been read yet. - * + * * @return the number of bytes available before blocking. * @throws IOException * if an error occurs in this stream. - * @since Android 1.0 */ @Override public synchronized int available() throws IOException { @@ -114,10 +100,9 @@ public class PipedInputStream extends InputStream { /** * Closes this stream. This implementation releases the buffer used for the * pipe and notifies all threads waiting to read or write. - * + * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -134,12 +119,11 @@ public class PipedInputStream extends InputStream { * Connects this {@code PipedInputStream} to a {@link PipedOutputStream}. * Any data written to the output stream becomes readable in this input * stream. - * + * * @param src * the source output stream. * @throws IOException * if either stream is already connected. - * @since Android 1.0 */ public void connect(PipedOutputStream src) throws IOException { src.connect(this); @@ -155,15 +139,13 @@ public class PipedInputStream extends InputStream { * Separate threads should be used to read from a {@code PipedInputStream} * and to write to the connected {@link PipedOutputStream}. If the same * thread is used, a deadlock may occur. - * </p> - * + * * @return the byte read or -1 if the end of the source stream has been * reached. * @throws IOException * if this stream is closed or not connected to an output * stream, or if the thread writing to the connected output * stream is no longer alive. - * @since Android 1.0 */ @Override public synchronized int read() throws IOException { @@ -180,16 +162,15 @@ public class PipedInputStream extends InputStream { */ lastReader = Thread.currentThread(); try { - boolean first = true; + int attempts = 3; while (in == -1) { // Are we at end of stream? if (isClosed) { return -1; } - if (!first && lastWriter != null && !lastWriter.isAlive()) { + if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) { throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$ } - first = false; // Notify callers of receive() notifyAll(); wait(1000); @@ -219,8 +200,7 @@ public class PipedInputStream extends InputStream { * Separate threads should be used to read from a {@code PipedInputStream} * and to write to the connected {@link PipedOutputStream}. If the same * thread is used, a deadlock may occur. - * </p> - * + * * @param bytes * the array in which to store the bytes read. * @param offset @@ -278,16 +258,15 @@ public class PipedInputStream extends InputStream { */ lastReader = Thread.currentThread(); try { - boolean first = true; + int attempts = 3; while (in == -1) { // Are we at end of stream? if (isClosed) { return -1; } - if (!first && lastWriter != null && !lastWriter.isAlive()) { + if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) { throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$ } - first = false; // Notify callers of receive() notifyAll(); wait(1000); @@ -342,8 +321,7 @@ public class PipedInputStream extends InputStream { * {@code in} in the {@code buffer}. * <p> * This method blocks as long as {@code buffer} is full. - * </p> - * + * * @param oneByte * the byte to store in this pipe. * @throws InterruptedIOException diff --git a/luni/src/main/java/java/io/PipedOutputStream.java b/luni/src/main/java/java/io/PipedOutputStream.java index 3041f70..15ee930 100644 --- a/luni/src/main/java/java/io/PipedOutputStream.java +++ b/luni/src/main/java/java/io/PipedOutputStream.java @@ -23,10 +23,8 @@ import org.apache.harmony.luni.util.Msg; * Places information on a communications pipe. When two threads want to pass * data back and forth, one creates a piped output stream and the other one * creates a piped input stream. - * + * * @see PipedInputStream - * - * @since Android 1.0 */ public class PipedOutputStream extends OutputStream { @@ -39,8 +37,6 @@ public class PipedOutputStream extends OutputStream { * Constructs a new unconnected {@code PipedOutputStream}. The resulting * stream must be connected to a {@link PipedInputStream} before data can be * written to it. - * - * @since Android 1.0 */ public PipedOutputStream() { super(); @@ -50,12 +46,11 @@ public class PipedOutputStream extends OutputStream { * Constructs a new {@code PipedOutputStream} connected to the * {@link PipedInputStream} {@code dest}. Any data written to this stream * can be read from the target stream. - * + * * @param dest * the piped input stream to connect to. * @throws IOException * if this stream or {@code dest} are already connected. - * @since Android 1.0 */ public PipedOutputStream(PipedInputStream dest) throws IOException { super(); @@ -65,10 +60,9 @@ public class PipedOutputStream extends OutputStream { /** * Closes this stream. If this stream is connected to an input stream, the * input stream is closed and the pipe is disconnected. - * + * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -82,12 +76,11 @@ public class PipedOutputStream extends OutputStream { /** * Connects this stream to a {@link PipedInputStream}. Any data written to * this output stream becomes readable in the input stream. - * + * * @param stream * the destination input stream. * @throws IOException * if either stream is already connected. - * @since Android 1.0 */ public void connect(PipedInputStream stream) throws IOException { if (null == stream) { @@ -109,10 +102,9 @@ public class PipedOutputStream extends OutputStream { /** * Notifies the readers of this {@link PipedInputStream} that bytes can be * read. This method does nothing if this stream is not connected. - * + * * @throws IOException * if an I/O error occurs while flushing this stream. - * @since Android 1.0 */ @Override public void flush() throws IOException { @@ -131,8 +123,7 @@ public class PipedOutputStream extends OutputStream { * Separate threads should be used to write to a {@code PipedOutputStream} * and to read from the connected {@link PipedInputStream}. If the same * thread is used, a deadlock may occur. - * </p> - * + * * @param buffer * the buffer to write. * @param offset @@ -151,7 +142,6 @@ public class PipedOutputStream extends OutputStream { * if this stream is not connected, if the target stream is * closed or if the thread reading from the target stream is no * longer alive. This case is currently not handled correctly. - * @since Android 1.0 */ @Override public void write(byte[] buffer, int offset, int count) throws IOException { @@ -173,8 +163,7 @@ public class PipedOutputStream extends OutputStream { * Separate threads should be used to write to a {@code PipedOutputStream} * and to read from the connected {@link PipedInputStream}. If the same * thread is used, a deadlock may occur. - * </p> - * + * * @param oneByte * the byte to write. * @throws InterruptedIOException @@ -185,7 +174,6 @@ public class PipedOutputStream extends OutputStream { * if this stream is not connected, if the target stream is * closed or if the thread reading from the target stream is no * longer alive. This case is currently not handled correctly. - * @since Android 1.0 */ @Override public void write(int oneByte) throws IOException { diff --git a/luni/src/main/java/java/io/PipedReader.java b/luni/src/main/java/java/io/PipedReader.java index a0af9a5..251ac90 100644 --- a/luni/src/main/java/java/io/PipedReader.java +++ b/luni/src/main/java/java/io/PipedReader.java @@ -23,10 +23,8 @@ import org.apache.harmony.luni.util.Msg; * Receives information on a communications pipe. When two threads want to pass * data back and forth, one creates a piped writer and the other creates a piped * reader. - * + * * @see PipedWriter - * - * @since Android 1.0 */ public class PipedReader extends Reader { @@ -66,9 +64,8 @@ public class PipedReader extends Reader { * Constructs a new unconnected {@code PipedReader}. The resulting reader * must be connected to a {@code PipedWriter} before data may be read from * it. - * + * * @see PipedWriter - * @since Android 1.0 */ public PipedReader() { data = new char[PIPE_SIZE]; @@ -78,12 +75,11 @@ public class PipedReader extends Reader { * Constructs a new {@code PipedReader} connected to the {@link PipedWriter} * {@code out}. Any data written to the writer can be read from the this * reader. - * + * * @param out * the {@code PipedWriter} to connect to. * @throws IOException * if {@code out} is already connected. - * @since Android 1.0 */ public PipedReader(PipedWriter out) throws IOException { this(); @@ -93,10 +89,9 @@ public class PipedReader extends Reader { /** * Closes this reader. This implementation releases the buffer used for * the pipe and notifies all threads waiting to read or write. - * + * * @throws IOException * if an error occurs while closing this reader. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -112,13 +107,12 @@ public class PipedReader extends Reader { /** * Connects this {@code PipedReader} to a {@link PipedWriter}. Any data * written to the writer becomes readable in this reader. - * + * * @param src * the writer to connect to. * @throws IOException * if this reader is closed or already connected, or if {@code * src} is already connected. - * @since Android 1.0 */ public void connect(PipedWriter src) throws IOException { synchronized (lock) { @@ -128,7 +122,7 @@ public class PipedReader extends Reader { /** * Establishes the connection to the PipedWriter. - * + * * @throws IOException * If this Reader is already connected. */ @@ -154,13 +148,11 @@ public class PipedReader extends Reader { * Separate threads should be used to read from a {@code PipedReader} and to * write to the connected {@link PipedWriter}. If the same thread is used, * a deadlock may occur. - * </p> - * + * * @return the character read or -1 if the end of the reader has been * reached. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -179,8 +171,7 @@ public class PipedReader extends Reader { * Separate threads should be used to read from a {@code PipedReader} and to * write to the connected {@link PipedWriter}. If the same thread is used, a * deadlock may occur. - * </p> - * + * * @param buffer * the character array in which to store the characters read. * @param offset @@ -298,14 +289,13 @@ public class PipedReader extends Reader { * called, {@code false} if unknown or blocking will occur. This * implementation returns {@code true} if the internal buffer contains * characters that can be read. - * + * * @return always {@code false}. * @throws IOException * if this reader is closed or not connected, or if some other * I/O error occurs. * @see #read() * @see #read(char[], int, int) - * @since Android 1.0 */ @Override public boolean ready() throws IOException { @@ -326,10 +316,10 @@ public class PipedReader extends Reader { * <P> * If the buffer is full and the thread sending #receive is interrupted, the * InterruptedIOException will be thrown. - * + * * @param oneChar * the char to store into the pipe. - * + * * @throws IOException * If the stream is already closed or another IOException * occurs. @@ -380,14 +370,14 @@ public class PipedReader extends Reader { * <P> * If the buffer is full and the thread sending #receive is interrupted, the * InterruptedIOException will be thrown. - * + * * @param chars * the char array to store into the pipe. * @param offset * offset to start reading from * @param count * total characters to read - * + * * @throws IOException * If the stream is already closed or another IOException * occurs. diff --git a/luni/src/main/java/java/io/PipedWriter.java b/luni/src/main/java/java/io/PipedWriter.java index 98a73c9..5fc968d 100644 --- a/luni/src/main/java/java/io/PipedWriter.java +++ b/luni/src/main/java/java/io/PipedWriter.java @@ -23,10 +23,8 @@ import org.apache.harmony.luni.util.Msg; * Places information on a communications pipe. When two threads want to pass * data back and forth, one creates a piped writer and the other creates a piped * reader. - * + * * @see PipedReader - * - * @since Android 1.0 */ public class PipedWriter extends Writer { /** @@ -40,9 +38,8 @@ public class PipedWriter extends Writer { * Constructs a new unconnected {@code PipedWriter}. The resulting writer * must be connected to a {@code PipedReader} before data may be written to * it. - * + * * @see PipedReader - * @since Android 1.0 */ public PipedWriter() { super(); @@ -52,12 +49,11 @@ public class PipedWriter extends Writer { * Constructs a new {@code PipedWriter} connected to the {@link PipedReader} * {@code dest}. Any data written to this writer can be read from {@code * dest}. - * + * * @param dest * the {@code PipedReader} to connect to. * @throws IOException * if {@code dest} is already connected. - * @since Android 1.0 */ public PipedWriter(PipedReader dest) throws IOException { super(dest); @@ -68,10 +64,9 @@ public class PipedWriter extends Writer { * Closes this writer. If a {@link PipedReader} is connected to this writer, * it is closed as well and the pipe is disconnected. Any data buffered in * the reader can still be read. - * + * * @throws IOException * if an error occurs while closing this writer. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -88,13 +83,12 @@ public class PipedWriter extends Writer { /** * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data * written to this writer becomes readable in the reader. - * + * * @param stream * the reader to connect to. * @throws IOException * if this writer is closed or already connected, or if {@code * stream} is already connected. - * @since Android 1.0 */ public void connect(PipedReader stream) throws IOException { synchronized (lock) { @@ -112,10 +106,9 @@ public class PipedWriter extends Writer { /** * Notifies the readers of this {@code PipedReader} that characters can be read. This * method does nothing if this Writer is not connected. - * + * * @throws IOException * if an I/O error occurs while flushing this writer. - * @since Android 1.0 */ @Override public void flush() throws IOException { @@ -132,8 +125,7 @@ public class PipedWriter extends Writer { * Separate threads should be used to write to a {@code PipedWriter} and to * read from the connected {@code PipedReader}. If the same thread is used, * a deadlock may occur. - * </p> - * + * * @param buffer * the buffer to write. * @param offset @@ -155,7 +147,6 @@ public class PipedWriter extends Writer { * correctly. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ @Override public void write(char[] buffer, int offset, int count) throws IOException { @@ -194,8 +185,7 @@ public class PipedWriter extends Writer { * Separate threads should be used to write to a {@code PipedWriter} and to * read from the connected {@code PipedReader}. If the same thread is used, * a deadlock may occur. - * </p> - * + * * @param c * the character to write. * @throws InterruptedIOException @@ -207,7 +197,6 @@ public class PipedWriter extends Writer { * reader is closed or if the thread reading from the target * reader is no longer alive. This case is currently not handled * correctly. - * @since Android 1.0 */ @Override public void write(int c) throws IOException { diff --git a/luni/src/main/java/java/io/PrintStream.java b/luni/src/main/java/java/io/PrintStream.java index 0aae645..29d460e 100644 --- a/luni/src/main/java/java/io/PrintStream.java +++ b/luni/src/main/java/java/io/PrintStream.java @@ -18,6 +18,7 @@ package java.io; import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; import java.security.AccessController; import java.util.Formatter; import java.util.IllegalFormatException; @@ -33,8 +34,6 @@ import org.apache.harmony.luni.util.PriviAction; * so that they can be read back in. No {@code IOException} is thrown by this * class. Instead, callers should use {@link #checkError()} to see if a problem * has occurred in this stream. - * - * @since Android 1.0 */ public class PrintStream extends FilterOutputStream implements Appendable, Closeable { @@ -63,12 +62,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, * Constructs a new {@code PrintStream} with {@code out} as its target * stream. By default, the new print stream does not automatically flush its * contents to the target stream when a newline is encountered. - * + * * @param out * the target output stream. * @throws NullPointerException * if {@code out} is {@code null}. - * @since Android 1.0 */ public PrintStream(OutputStream out) { super(out); @@ -82,7 +80,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * stream. The parameter {@code autoflush} determines if the print stream * automatically flushes its contents to the target stream when a newline is * encountered. - * + * * @param out * the target output stream. * @param autoflush @@ -90,7 +88,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * newline sequence. * @throws NullPointerException * if {@code out} is {@code null}. - * @since Android 1.0 */ public PrintStream(OutputStream out, boolean autoflush) { super(out); @@ -105,7 +102,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * stream and using the character encoding {@code enc} while writing. The * parameter {@code autoflush} determines if the print stream automatically * flushes its contents to the target stream when a newline is encountered. - * + * * @param out * the target output stream. * @param autoflush @@ -117,7 +114,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * if {@code out} or {@code enc} are {@code null}. * @throws UnsupportedEncodingException * if the encoding specified by {@code enc} is not supported. - * @since Android 1.0 */ public PrintStream(OutputStream out, boolean autoflush, String enc) throws UnsupportedEncodingException { @@ -126,7 +122,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, throw new NullPointerException(); } this.autoflush = autoflush; - if (!Charset.isSupported(enc)) { + try { + if (!Charset.isSupported(enc)) { + throw new UnsupportedEncodingException(enc); + } + } catch (IllegalCharsetNameException e) { throw new UnsupportedEncodingException(enc); } encoding = enc; @@ -135,7 +135,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Constructs a new {@code PrintStream} with {@code file} as its target. The * virtual machine's default character set is used for character encoding. - * + * * @param file * the target file. If the file already exists, its contents are * removed, otherwise a new file is created. @@ -144,7 +144,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * @throws SecurityException * if a security manager exists and it denies writing to the * target file. - * @since Android 1.0 */ public PrintStream(File file) throws FileNotFoundException { super(new FileOutputStream(file)); @@ -153,7 +152,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Constructs a new {@code PrintStream} with {@code file} as its target. The * character set named {@code csn} is used for character encoding. - * + * * @param file * the target file. If the file already exists, its contents are * removed, otherwise a new file is created. @@ -168,7 +167,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * target file. * @throws UnsupportedEncodingException * if the encoding specified by {@code csn} is not supported. - * @since Android 1.0 */ public PrintStream(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { @@ -186,7 +184,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * Constructs a new {@code PrintStream} with the file identified by * {@code fileName} as its target. The virtual machine's default character * set is used for character encoding. - * + * * @param fileName * the target file's name. If the file already exists, its * contents are removed, otherwise a new file is created. @@ -195,7 +193,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * @throws SecurityException * if a security manager exists and it denies writing to the * target file. - * @since Android 1.0 */ public PrintStream(String fileName) throws FileNotFoundException { this(new File(fileName)); @@ -205,7 +202,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * Constructs a new {@code PrintStream} with the file identified by * {@code fileName} as its target. The character set named {@code csn} is * used for character encoding. - * + * * @param fileName * the target file's name. If the file already exists, its * contents are removed, otherwise a new file is created. @@ -220,7 +217,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * target file. * @throws UnsupportedEncodingException * if the encoding specified by {@code csn} is not supported. - * @since Android 1.0 */ public PrintStream(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { @@ -229,12 +225,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Flushes this stream and returns the value of the error flag. - * + * * @return {@code true} if either an {@code IOException} has been thrown * previously or if {@code setError()} has been called; * {@code false} otherwise. - * @see #setError() - * @since Android 1.0 + * @see #setError() */ public boolean checkError() { if (out != null) { @@ -247,8 +242,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * Closes this print stream. Flushes this stream and then closes the target * stream. If an I/O error occurs, this stream's error state is set to * {@code true}. - * - * @since Android 1.0 */ @Override public synchronized void close() { @@ -267,8 +260,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * Ensures that all pending data is sent out to the target stream. It also * flushes the target stream. If an I/O error occurs, this stream's error * state is set to {@code true}. - * - * @since Android 1.0 */ @Override public synchronized void flush() { @@ -288,7 +279,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * target stream using the specified format string and arguments. For the * locale, the default value of the current virtual machine instance is * used. - * + * * @param format * the format string used for {@link java.util.Formatter#format}. * @param args @@ -302,7 +293,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * error regarding the format string or arguments is detected. * @throws NullPointerException * if {@code format} is {@code null}. - * @since Android 1.0 */ public PrintStream format(String format, Object... args) { return format(Locale.getDefault(), format, args); @@ -311,7 +301,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Writes a string formatted by an intermediate {@link Formatter} to this * stream using the specified locale, format string and arguments. - * + * * @param l * the locale used in the method. No localization will be applied * if {@code l} is {@code null}. @@ -328,7 +318,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * error regarding the format string or arguments is detected. * @throws NullPointerException * if {@code format} is {@code null}. - * @since Android 1.0 */ public PrintStream format(Locale l, String format, Object... args) { if (format == null) { @@ -342,7 +331,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * Prints a formatted string. The behavior of this method is the same as * this stream's {@code #format(String, Object...)} method. For the locale, * the default value of the current virtual machine instance is used. - * + * * @param format * the format string used for * {@link java.util.Formatter#format}. @@ -357,7 +346,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * error regarding the format string or arguments is detected. * @throws NullPointerException * if {@code format} is {@code null}. - * @since Android 1.0 */ public PrintStream printf(String format, Object... args) { return format(format, args); @@ -366,7 +354,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints a formatted string. The behavior of this method is the same as * this stream's {@code #format(Locale, String, Object...)} method. - * + * * @param l * the locale used in the method. No localization will be applied * if {@code l} is {@code null}. @@ -383,7 +371,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * error regarding the format string or arguments is detected. * @throws NullPointerException * if {@code format} is {@code null}. - * @since Android 1.0 */ public PrintStream printf(Locale l, String format, Object... args) { return format(l, format, args); @@ -399,11 +386,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified character array * to the target stream. - * + * * @param charArray * the character array to print to the target stream. * @see #print(String) - * @since Android 1.0 */ public void print(char[] charArray) { print(new String(charArray, 0, charArray.length)); @@ -412,11 +398,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified character to the target * stream. - * + * * @param ch * the character to print to the target stream. * @see #print(String) - * @since Android 1.0 */ public void print(char ch) { print(String.valueOf(ch)); @@ -425,11 +410,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified double to the target * stream. - * + * * @param dnum * the double value to print to the target stream. * @see #print(String) - * @since Android 1.0 */ public void print(double dnum) { print(String.valueOf(dnum)); @@ -438,12 +422,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified float to the target * stream. - * + * * @param fnum * the float value to print to the target stream. * @see #print(String) - * @since Android 1.0 - */ + */ public void print(float fnum) { print(String.valueOf(fnum)); } @@ -451,12 +434,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified integer to the target * stream. - * + * * @param inum * the integer value to print to the target stream. * @see #print(String) - * @since Android 1.0 - */ + */ public void print(int inum) { print(String.valueOf(inum)); } @@ -464,12 +446,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified long to the target * stream. - * + * * @param lnum * the long value to print to the target stream. * @see #print(String) - * @since Android 1.0 - */ + */ public void print(long lnum) { print(String.valueOf(lnum)); } @@ -477,12 +458,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified object to the target * stream. - * + * * @param obj * the object to print to the target stream. * @see #print(String) - * @since Android 1.0 - */ + */ public void print(Object obj) { print(String.valueOf(obj)); } @@ -494,12 +474,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, * {@code write(int)}. * <p> * If an I/O error occurs, this stream's error state is set to {@code true}. - * </p> - * + * * @param str * the string to print to the target stream. * @see #write(int) - * @since Android 1.0 */ public synchronized void print(String str) { if (out == null) { @@ -525,12 +503,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified boolean to the target * stream. - * + * * @param bool * the boolean value to print the target stream. * @see #print(String) - * @since Android 1.0 - */ + */ public void print(boolean bool) { print(String.valueOf(bool)); } @@ -538,8 +515,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the system property * {@code "line.separator"} to the target stream. - * - * @since Android 1.0 */ public void println() { newline(); @@ -549,11 +524,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, * Prints the string representation of the specified character array * followed by the system property {@code "line.separator"} to the target * stream. - * + * * @param charArray * the character array to print to the target stream. * @see #print(String) - * @since Android 1.0 */ public void println(char[] charArray) { println(new String(charArray, 0, charArray.length)); @@ -562,11 +536,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified character followed by * the system property {@code "line.separator"} to the target stream. - * + * * @param ch * the character to print to the target stream. * @see #print(String) - * @since Android 1.0 */ public void println(char ch) { println(String.valueOf(ch)); @@ -575,11 +548,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified double followed by the * system property {@code "line.separator"} to the target stream. - * + * * @param dnum * the double value to print to the target stream. * @see #print(String) - * @since Android 1.0 */ public void println(double dnum) { println(String.valueOf(dnum)); @@ -588,12 +560,11 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified float followed by the * system property {@code "line.separator"} to the target stream. - * + * * @param fnum * the float value to print to the target stream. * @see #print(String) - * @since Android 1.0 - */ + */ public void println(float fnum) { println(String.valueOf(fnum)); } @@ -601,12 +572,12 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified integer followed by the * system property {@code "line.separator"} to the target stream. - * + * * @param inum * the integer value to print to the target stream. * @see #print(String) * @since Android 1.0 - */ + */ public void println(int inum) { println(String.valueOf(inum)); } @@ -614,12 +585,12 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified long followed by the * system property {@code "line.separator"} to the target stream. - * + * * @param lnum * the long value to print to the target stream. * @see #print(String) * @since Android 1.0 - */ + */ public void println(long lnum) { println(String.valueOf(lnum)); } @@ -627,12 +598,12 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified object followed by the * system property {@code "line.separator"} to the target stream. - * + * * @param obj * the object to print to the target stream. * @see #print(String) * @since Android 1.0 - */ + */ public void println(Object obj) { println(String.valueOf(obj)); } @@ -645,7 +616,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * <p> * If an I/O error occurs, this stream's error state is set to {@code true}. * </p> - * + * * @param str * the string to print to the target stream. * @see #write(int) @@ -659,20 +630,17 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Prints the string representation of the specified boolean followed by the * system property {@code "line.separator"} to the target stream. - * + * * @param bool * the boolean value to print to the target stream. * @see #print(String) - * @since Android 1.0 - */ + */ public void println(boolean bool) { println(String.valueOf(bool)); } /** * Sets the error flag of this print stream to {@code true}. - * - * @since Android 1.0 */ protected void setError() { ioError = true; @@ -685,8 +653,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * <p> * This stream's error flag is set to {@code true} if this stream is closed * or an I/O error occurs. - * </p> - * + * * @param buffer * the buffer to be written. * @param offset @@ -697,7 +664,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * if {@code offset < 0} or {@code count < 0}, or if {@code * offset + count} is bigger than the length of {@code buffer}. * @see #flush() - * @since Android 1.0 */ @Override public void write(byte[] buffer, int offset, int count) { @@ -738,11 +704,9 @@ public class PrintStream extends FilterOutputStream implements Appendable, * <p> * This stream's error flag is set to {@code true} if it is closed or an I/O * error occurs. - * </p> - * + * * @param oneByte * the byte to be written - * @since Android 1.0 */ @Override public synchronized void write(int oneByte) { @@ -763,11 +727,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, /** * Appends the character {@code c} to the target stream. This method works * the same way as {@link #print(char)}. - * + * * @param c * the character to append to the target stream. * @return this stream. - * @since Android 1.0 */ public PrintStream append(char c) { print(c); @@ -779,11 +742,10 @@ public class PrintStream extends FilterOutputStream implements Appendable, * method works the same way as {@code PrintStream.print(csq.toString())}. * If {@code csq} is {@code null}, then the string "null" is written to the * target stream. - * + * * @param csq * the character sequence appended to the target stream. * @return this stream. - * @since Android 1.0 */ public PrintStream append(CharSequence csq) { if (null == csq) { @@ -800,7 +762,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, * PrintStream.print(csq.subsequence(start, end).toString())}. If {@code * csq} is {@code null}, then the specified subsequence of the string "null" * will be written to the target stream. - * + * * @param csq * the character sequence appended to the target stream. * @param start @@ -814,7 +776,6 @@ public class PrintStream extends FilterOutputStream implements Appendable, * if {@code start > end}, {@code start < 0}, {@code end < 0} or * either {@code start} or {@code end} are greater or equal than * the length of {@code csq}. - * @since Android 1.0 */ public PrintStream append(CharSequence csq, int start, int end) { if (null == csq) { diff --git a/luni/src/main/java/java/io/PrintWriter.java b/luni/src/main/java/java/io/PrintWriter.java index 0c5189d..f87707d 100644 --- a/luni/src/main/java/java/io/PrintWriter.java +++ b/luni/src/main/java/java/io/PrintWriter.java @@ -25,24 +25,16 @@ import java.util.Locale; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; -// BEGIN android-note -// added @return comment to #printf(Locale l, String format, Object... args) -// END android-note - /** * Wraps either an existing {@link OutputStream} or an existing {@link Writer} * and provides convenience methods for printing common data types in a human * readable format. No {@code IOException} is thrown by this class. Instead, * callers should use {@link #checkError()} to see if a problem has occurred in * this writer. - * - * @since Android 1.0 */ public class PrintWriter extends Writer { /** * The writer to print data to. - * - * @since Android 1.0 */ protected Writer out; @@ -64,12 +56,11 @@ public class PrintWriter extends Writer { * Constructs a new {@code PrintWriter} with {@code out} as its target * stream. By default, the new print writer does not automatically flush its * contents to the target stream when a newline is encountered. - * + * * @param out * the target output stream. * @throws NullPointerException * if {@code out} is {@code null}. - * @since Android 1.0 */ public PrintWriter(OutputStream out) { this(new OutputStreamWriter(out), false); @@ -80,7 +71,7 @@ public class PrintWriter extends Writer { * stream. The parameter {@code autoflush} determines if the print writer * automatically flushes its contents to the target stream when a newline is * encountered. - * + * * @param out * the target output stream. * @param autoflush @@ -88,7 +79,6 @@ public class PrintWriter extends Writer { * newline sequence. * @throws NullPointerException * if {@code out} is {@code null}. - * @since Android 1.0 */ public PrintWriter(OutputStream out, boolean autoflush) { this(new OutputStreamWriter(out), autoflush); @@ -98,12 +88,11 @@ public class PrintWriter extends Writer { * Constructs a new {@code PrintWriter} with {@code wr} as its target * writer. By default, the new print writer does not automatically flush its * contents to the target writer when a newline is encountered. - * + * * @param wr * the target writer. * @throws NullPointerException * if {@code wr} is {@code null}. - * @since Android 1.0 */ public PrintWriter(Writer wr) { this(wr, false); @@ -114,7 +103,7 @@ public class PrintWriter extends Writer { * writer. The parameter {@code autoflush} determines if the print writer * automatically flushes its contents to the target writer when a newline is * encountered. - * + * * @param wr * the target writer. * @param autoflush @@ -122,7 +111,6 @@ public class PrintWriter extends Writer { * newline sequence. * @throws NullPointerException * if {@code out} is {@code null}. - * @since Android 1.0 */ public PrintWriter(Writer wr, boolean autoflush) { super(wr); @@ -135,7 +123,7 @@ public class PrintWriter extends Writer { * virtual machine's default character set is used for character encoding. * The print writer does not automatically flush its contents to the target * file when a newline is encountered. The output to the file is buffered. - * + * * @param file * the target file. If the file already exists, its contents are * removed, otherwise a new file is created. @@ -144,7 +132,6 @@ public class PrintWriter extends Writer { * @throws SecurityException * if a security manager exists and it denies writing to the * target file. - * @since Android 1.0 */ public PrintWriter(File file) throws FileNotFoundException { // BEGIN android-modified @@ -160,7 +147,7 @@ public class PrintWriter extends Writer { * character set named {@code csn} is used for character encoding. * The print writer does not automatically flush its contents to the target * file when a newline is encountered. The output to the file is buffered. - * + * * @param file * the target file. If the file already exists, its contents are * removed, otherwise a new file is created. @@ -175,7 +162,6 @@ public class PrintWriter extends Writer { * target file. * @throws UnsupportedEncodingException * if the encoding specified by {@code csn} is not supported. - * @since Android 1.0 */ public PrintWriter(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { @@ -193,7 +179,7 @@ public class PrintWriter extends Writer { * used for character encoding. The print writer does not automatically * flush its contents to the target file when a newline is encountered. The * output to the file is buffered. - * + * * @param fileName * the target file's name. If the file already exists, its * contents are removed, otherwise a new file is created. @@ -202,7 +188,6 @@ public class PrintWriter extends Writer { * @throws SecurityException * if a security manager exists and it denies writing to the * target file. - * @since Android 1.0 */ public PrintWriter(String fileName) throws FileNotFoundException { // BEGIN android-modified @@ -219,7 +204,7 @@ public class PrintWriter extends Writer { * character encoding. The print writer does not automatically flush its * contents to the target file when a newline is encountered. The output to * the file is buffered. - * + * * @param fileName * the target file's name. If the file already exists, its * contents are removed, otherwise a new file is created. @@ -234,7 +219,6 @@ public class PrintWriter extends Writer { * target file. * @throws UnsupportedEncodingException * if the encoding specified by {@code csn} is not supported. - * @since Android 1.0 */ public PrintWriter(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { @@ -248,12 +232,11 @@ public class PrintWriter extends Writer { /** * Flushes this writer and returns the value of the error flag. - * + * * @return {@code true} if either an {@code IOException} has been thrown * previously or if {@code setError()} has been called; * {@code false} otherwise. - * @see #setError() - * @since Android 1.0 + * @see #setError() */ public boolean checkError() { if (out != null) { @@ -265,8 +248,6 @@ public class PrintWriter extends Writer { /** * Closes this print writer. Flushes this writer and then closes the target. * If an I/O error occurs, this writer's error flag is set to {@code true}. - * - * @since Android 1.0 */ @Override public void close() { @@ -286,8 +267,6 @@ public class PrintWriter extends Writer { * Ensures that all pending data is sent out to the target. It also * flushes the target. If an I/O error occurs, this writer's error * state is set to {@code true}. - * - * @since Android 1.0 */ @Override public void flush() { @@ -309,7 +288,7 @@ public class PrintWriter extends Writer { * target using the specified format string and arguments. For the locale, * the default value of the current virtual machine instance is used. If * automatic flushing is enabled then the buffer is flushed as well. - * + * * @param format * the format string used for {@link java.util.Formatter#format}. * @param args @@ -323,7 +302,6 @@ public class PrintWriter extends Writer { * error regarding the format string or arguments is detected. * @throws NullPointerException * if {@code format} is {@code null}. - * @since Android 1.0 */ public PrintWriter format(String format, Object... args) { return format(Locale.getDefault(), format, args); @@ -333,7 +311,7 @@ public class PrintWriter extends Writer { * Writes a string formatted by an intermediate {@code Formatter} to the * target using the specified locale, format string and arguments. If * automatic flushing is enabled then this writer is flushed. - * + * * @param l * the locale used in the method. No localization will be applied * if {@code l} is {@code null}. @@ -350,7 +328,6 @@ public class PrintWriter extends Writer { * error regarding the format string or arguments is detected. * @throws NullPointerException * if {@code format} is {@code null}. - * @since Android 1.0 */ public PrintWriter format(Locale l, String format, Object... args) { if (format == null) { @@ -367,7 +344,7 @@ public class PrintWriter extends Writer { * Prints a formatted string. The behavior of this method is the same as * this writer's {@code #format(String, Object...)} method. For the locale, * the default value of the current virtual machine instance is used. - * + * * @param format * the format string used for {@link java.util.Formatter#format}. * @param args @@ -381,7 +358,6 @@ public class PrintWriter extends Writer { * error regarding the format string or arguments is detected. * @throws NullPointerException * if {@code format} is {@code null}. - * @since Android 1.0 */ public PrintWriter printf(String format, Object... args) { return format(format, args); @@ -390,7 +366,7 @@ public class PrintWriter extends Writer { /** * Prints a formatted string. The behavior of this method is the same as * this writer's {@code #format(Locale, String, Object...)} method. - * + * * @param l * the locale used in the method. No localization will be applied * if {@code l} is {@code null}. @@ -407,7 +383,6 @@ public class PrintWriter extends Writer { * error regarding the format string or arguments is detected. * @throws NullPointerException * if {@code format} is {@code null}. - * @since Android 1.0 */ public PrintWriter printf(Locale l, String format, Object... args) { return format(l, format, args); @@ -426,11 +401,10 @@ public class PrintWriter extends Writer { /** * Prints the string representation of the specified character array * to the target. - * + * * @param charArray * the character array to print to the target. * @see #print(String) - * @since Android 1.0 */ public void print(char[] charArray) { print(new String(charArray, 0, charArray.length)); @@ -439,11 +413,10 @@ public class PrintWriter extends Writer { /** * Prints the string representation of the specified character to the * target. - * + * * @param ch * the character to print to the target. * @see #print(String) - * @since Android 1.0 */ public void print(char ch) { print(String.valueOf(ch)); @@ -451,23 +424,21 @@ public class PrintWriter extends Writer { /** * Prints the string representation of the specified double to the target. - * + * * @param dnum * the double value to print to the target. * @see #print(String) - * @since Android 1.0 */ public void print(double dnum) { print(String.valueOf(dnum)); } - /** + /** * Prints the string representation of the specified float to the target. - * + * * @param fnum * the float value to print to the target. * @see #print(String) - * @since Android 1.0 */ public void print(float fnum) { print(String.valueOf(fnum)); @@ -475,23 +446,21 @@ public class PrintWriter extends Writer { /** * Prints the string representation of the specified integer to the target. - * + * * @param inum * the integer value to print to the target. * @see #print(String) - * @since Android 1.0 - */ + */ public void print(int inum) { print(String.valueOf(inum)); } /** * Prints the string representation of the specified long to the target. - * + * * @param lnum * the long value to print to the target. * @see #print(String) - * @since Android 1.0 */ public void print(long lnum) { print(String.valueOf(lnum)); @@ -499,12 +468,11 @@ public class PrintWriter extends Writer { /** * Prints the string representation of the specified object to the target. - * + * * @param obj * the object to print to the target. * @see #print(String) - * @since Android 1.0 - */ + */ public void print(Object obj) { print(String.valueOf(obj)); } @@ -515,12 +483,10 @@ public class PrintWriter extends Writer { * The bytes are then written to the target with {@code write(int)}. * <p> * If an I/O error occurs, this writer's error flag is set to {@code true}. - * </p> - * + * * @param str * the string to print to the target. * @see #write(int) - * @since Android 1.0 */ public void print(String str) { write(str != null ? str : String.valueOf((Object) null)); @@ -528,12 +494,11 @@ public class PrintWriter extends Writer { /** * Prints the string representation of the specified boolean to the target. - * + * * @param bool * the boolean value to print the target. * @see #print(String) - * @since Android 1.0 - */ + */ public void print(boolean bool) { print(String.valueOf(bool)); } @@ -542,8 +507,6 @@ public class PrintWriter extends Writer { * Prints the string representation of the system property {@code * "line.separator"} to the target. Flushes this writer if the autoflush * flag is set to {@code true}. - * - * @since Android 1.0 */ public void println() { synchronized (lock) { @@ -555,11 +518,10 @@ public class PrintWriter extends Writer { * Prints the string representation of the specified character array * followed by the system property {@code "line.separator"} to the target. * Flushes this writer if the autoflush flag is set to {@code true}. - * + * * @param charArray * the character array to print to the target. * @see #print(String) - * @since Android 1.0 */ public void println(char[] charArray) { println(new String(charArray, 0, charArray.length)); @@ -569,11 +531,10 @@ public class PrintWriter extends Writer { * Prints the string representation of the specified character followed by * the system property {@code "line.separator"} to the target. Flushes this * writer if the autoflush flag is set to {@code true}. - * + * * @param ch * the character to print to the target. * @see #print(String) - * @since Android 1.0 */ public void println(char ch) { println(String.valueOf(ch)); @@ -583,11 +544,10 @@ public class PrintWriter extends Writer { * Prints the string representation of the specified double followed by the * system property {@code "line.separator"} to the target. Flushes this * writer if the autoflush flag is set to {@code true}. - * + * * @param dnum * the double value to print to the target. * @see #print(String) - * @since Android 1.0 */ public void println(double dnum) { println(String.valueOf(dnum)); @@ -597,12 +557,11 @@ public class PrintWriter extends Writer { * Prints the string representation of the specified float followed by the * system property {@code "line.separator"} to the target. Flushes this * writer if the autoflush flag is set to {@code true}. - * + * * @param fnum * the float value to print to the target. * @see #print(String) - * @since Android 1.0 - */ + */ public void println(float fnum) { println(String.valueOf(fnum)); } @@ -611,12 +570,11 @@ public class PrintWriter extends Writer { * Prints the string representation of the specified integer followed by the * system property {@code "line.separator"} to the target. Flushes this * writer if the autoflush flag is set to {@code true}. - * + * * @param inum * the integer value to print to the target. * @see #print(String) - * @since Android 1.0 - */ + */ public void println(int inum) { println(String.valueOf(inum)); } @@ -625,12 +583,11 @@ public class PrintWriter extends Writer { * Prints the string representation of the specified long followed by the * system property {@code "line.separator"} to the target. Flushes this * writer if the autoflush flag is set to {@code true}. - * + * * @param lnum * the long value to print to the target. * @see #print(String) - * @since Android 1.0 - */ + */ public void println(long lnum) { println(String.valueOf(lnum)); } @@ -639,12 +596,11 @@ public class PrintWriter extends Writer { * Prints the string representation of the specified object followed by the * system property {@code "line.separator"} to the target. Flushes this * writer if the autoflush flag is set to {@code true}. - * + * * @param obj * the object to print to the target. * @see #print(String) - * @since Android 1.0 - */ + */ public void println(Object obj) { println(String.valueOf(obj)); } @@ -657,12 +613,10 @@ public class PrintWriter extends Writer { * is flushed if the autoflush flag is set to {@code true}. * <p> * If an I/O error occurs, this writer's error flag is set to {@code true}. - * </p> - * + * * @param str * the string to print to the target. * @see #write(int) - * @since Android 1.0 */ public void println(String str) { synchronized (lock) { @@ -675,20 +629,17 @@ public class PrintWriter extends Writer { * Prints the string representation of the specified boolean followed by the * system property {@code "line.separator"} to the target. Flushes this * writer if the autoflush flag is set to {@code true}. - * + * * @param bool * the boolean value to print to the target. * @see #print(String) - * @since Android 1.0 - */ + */ public void println(boolean bool) { println(String.valueOf(bool)); } /** * Sets the error flag of this writer to {@code true}. - * - * @since Android 1.0 */ protected void setError() { synchronized (lock) { @@ -698,10 +649,9 @@ public class PrintWriter extends Writer { /** * Writes the character buffer {@code buf} to the target. - * + * * @param buf * the non-null array containing characters to write. - * @since Android 1.0 */ @Override public void write(char[] buf) { @@ -717,8 +667,7 @@ public class PrintWriter extends Writer { * <p> * This writer's error flag is set to {@code true} if this writer is closed * or an I/O error occurs. - * </p> - * + * * @param buf * the buffer to write to the target. * @param offset @@ -728,7 +677,6 @@ public class PrintWriter extends Writer { * @throws IndexOutOfBoundsException * if {@code offset < 0} or {@code count < 0}, or if {@code * offset + count} is greater than the length of {@code buf}. - * @since Android 1.0 */ @Override public void write(char[] buf, int offset, int count) { @@ -744,11 +692,9 @@ public class PrintWriter extends Writer { * <p> * This writer's error flag is set to {@code true} if this writer is closed * or an I/O error occurs. - * </p> - * + * * @param oneChar * the character to write to the target. - * @since Android 1.0 */ @Override public void write(int oneChar) { @@ -774,10 +720,9 @@ public class PrintWriter extends Writer { /** * Writes the characters from the specified string to the target. - * + * * @param str * the non-null string containing the characters to write. - * @since Android 1.0 */ @Override public void write(String str) { @@ -787,7 +732,7 @@ public class PrintWriter extends Writer { /** * Writes {@code count} characters from {@code str} starting at {@code * offset} to the target. - * + * * @param str * the non-null string containing the characters to write. * @param offset @@ -797,7 +742,6 @@ public class PrintWriter extends Writer { * @throws IndexOutOfBoundsException * if {@code offset < 0} or {@code count < 0}, or if {@code * offset + count} is greater than the length of {@code str}. - * @since Android 1.0 */ @Override public void write(String str, int offset, int count) { @@ -805,12 +749,11 @@ public class PrintWriter extends Writer { } /** - * Appends the character {@code c} to the target. - * + * Appends the character {@code c} to the target. + * * @param c * the character to append to the target. * @return this writer. - * @since Android 1.0 */ @Override public PrintWriter append(char c) { @@ -823,11 +766,10 @@ public class PrintWriter extends Writer { * method works the same way as {@code PrintWriter.print(csq.toString())}. * If {@code csq} is {@code null}, then the string "null" is written * to the target. - * + * * @param csq * the character sequence appended to the target. * @return this writer. - * @since Android 1.0 */ @Override public PrintWriter append(CharSequence csq) { @@ -845,7 +787,7 @@ public class PrintWriter extends Writer { * PrintWriter.print(csq.subsequence(start, end).toString())}. If {@code * csq} is {@code null}, then the specified subsequence of the string "null" * will be written to the target. - * + * * @param csq * the character sequence appended to the target. * @param start @@ -859,7 +801,6 @@ public class PrintWriter extends Writer { * if {@code start > end}, {@code start < 0}, {@code end < 0} or * either {@code start} or {@code end} are greater or equal than * the length of {@code csq}. - * @since Android 1.0 */ @Override public PrintWriter append(CharSequence csq, int start, int end) { diff --git a/luni/src/main/java/java/io/PushbackInputStream.java b/luni/src/main/java/java/io/PushbackInputStream.java index c397c86..1784012 100644 --- a/luni/src/main/java/java/io/PushbackInputStream.java +++ b/luni/src/main/java/java/io/PushbackInputStream.java @@ -25,14 +25,10 @@ import org.apache.harmony.luni.util.Msg; * this useful. The number of bytes which may be pushed back can be specified * during construction. If the buffer of pushed back bytes is empty, bytes are * read from the underlying input stream. - * - * @since Android 1.0 */ public class PushbackInputStream extends FilterInputStream { /** * The buffer that contains pushed-back bytes. - * - * @since Android 1.0 */ protected byte[] buf; @@ -40,8 +36,6 @@ public class PushbackInputStream extends FilterInputStream { * The current position within {@code buf}. A value equal to * {@code buf.length} indicates that no bytes are available. A value of 0 * indicates that the buffer is full. - * - * @since Android 1.0 */ protected int pos; @@ -49,10 +43,9 @@ public class PushbackInputStream extends FilterInputStream { * Constructs a new {@code PushbackInputStream} with the specified input * stream as source. The size of the pushback buffer is set to the default * value of 1 byte. - * + * * @param in * the source input stream. - * @since Android 1.0 */ public PushbackInputStream(InputStream in) { super(in); @@ -63,14 +56,13 @@ public class PushbackInputStream extends FilterInputStream { /** * Constructs a new {@code PushbackInputStream} with {@code in} as source * input stream. The size of the pushback buffer is set to {@code size}. - * + * * @param in * the source input stream. * @param size * the size of the pushback buffer. * @throws IllegalArgumentException * if {@code size} is negative. - * @since Android 1.0 */ public PushbackInputStream(InputStream in, int size) { super(in); @@ -85,12 +77,11 @@ public class PushbackInputStream extends FilterInputStream { * Returns the number of bytes that are available before this stream will * block. This is the sum of the bytes available in the pushback buffer and * those available from the source stream. - * + * * @return the number of bytes available before blocking. * @throws IOException * if this stream is closed or an I/O error occurs in the source * stream. - * @since Android 1.0 */ @Override public int available() throws IOException { @@ -103,10 +94,9 @@ public class PushbackInputStream extends FilterInputStream { /** * Closes this stream. This implementation closes the source stream * and releases the pushback buffer. - * + * * @throws IOException * if an error occurs while closing this stream. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -121,11 +111,10 @@ public class PushbackInputStream extends FilterInputStream { * Indicates whether this stream supports the {@code mark(int)} and * {@code reset()} methods. {@code PushbackInputStream} does not support * them, so it returns {@code false}. - * + * * @return always {@code false}. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -138,13 +127,12 @@ public class PushbackInputStream extends FilterInputStream { * available bytes then a byte from the source input stream is returned. * Blocks until one byte has been read, the end of the source stream is * detected or an exception is thrown. - * + * * @return the byte read or -1 if the end of the source stream has been * reached. * @throws IOException * if this stream is closed or an I/O error occurs while reading * from this stream. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -166,7 +154,7 @@ public class PushbackInputStream extends FilterInputStream { * from the pushback buffer first, then from the source stream if more bytes * are required. Blocks until {@code count} bytes have been read, the end of * the source stream is detected or an exception is thrown. - * + * * @param buffer * the array in which to store the bytes read from this stream. * @param offset @@ -185,7 +173,6 @@ public class PushbackInputStream extends FilterInputStream { * reading from this stream. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ @Override public int read(byte[] buffer, int offset, int length) throws IOException { @@ -234,13 +221,12 @@ public class PushbackInputStream extends FilterInputStream { /** * Skips {@code count} bytes in this stream. This implementation skips bytes * in the pushback buffer first and then in the source stream if necessary. - * + * * @param count * the number of bytes to skip. * @return the number of bytes actually skipped. * @throws IOException * if this stream is closed or another I/O error occurs. - * @since Android 1.0 */ @Override public long skip(long count) throws IOException { @@ -270,14 +256,12 @@ public class PushbackInputStream extends FilterInputStream { * contents of {@code buffer}, an {@code IOException} is thrown. Parts of * {@code buffer} may have already been copied to the pushback buffer when * the exception is thrown. - * </p> - * + * * @param buffer * the buffer containing the bytes to push back to this stream. * @throws IOException * if the free space in the internal pushback buffer is not * sufficient to store the contents of {@code buffer}. - * @since Android 1.0 */ public void unread(byte[] buffer) throws IOException { unread(buffer, 0, buffer.length); @@ -294,8 +278,7 @@ public class PushbackInputStream extends FilterInputStream { * subset of {@code buffer}, an {@code IOException} is thrown. Parts of * {@code buffer} may have already been copied to the pushback buffer when * the exception is thrown. - * </p> - * + * * @param buffer * the buffer containing the bytes to push back to this stream. * @param offset @@ -309,7 +292,6 @@ public class PushbackInputStream extends FilterInputStream { * @throws IOException * if the free space in the internal pushback buffer is not * sufficient to store the selected contents of {@code buffer}. - * @since Android 1.0 */ public void unread(byte[] buffer, int offset, int length) throws IOException { @@ -345,14 +327,12 @@ public class PushbackInputStream extends FilterInputStream { * <p> * If this stream's internal pushback buffer cannot store the byte, an * {@code IOException} is thrown. - * </p> - * + * * @param oneByte * the byte to push back to this stream. * @throws IOException * if this stream is closed or the internal pushback buffer is * full. - * @since Android 1.0 */ public void unread(int oneByte) throws IOException { if (buf == null) { @@ -367,11 +347,10 @@ public class PushbackInputStream extends FilterInputStream { /** * Marks the current position in this stream. Setting a mark is not * supported in this class; this implementation does nothing. - * + * * @param readlimit * the number of bytes that can be read from this stream before * the mark is invalidated; this parameter is ignored. - * @since Android 1.0 */ @Override public void mark(int readlimit) { @@ -382,10 +361,9 @@ public class PushbackInputStream extends FilterInputStream { * Resets this stream to the last marked position. Resetting the stream is * not supported in this class; this implementation always throws an * {@code IOException}. - * + * * @throws IOException * if this method is called. - * @since Android 1.0 */ @Override public void reset() throws IOException { diff --git a/luni/src/main/java/java/io/PushbackReader.java b/luni/src/main/java/java/io/PushbackReader.java index 484caf3..606ecb4 100644 --- a/luni/src/main/java/java/io/PushbackReader.java +++ b/luni/src/main/java/java/io/PushbackReader.java @@ -25,8 +25,6 @@ import org.apache.harmony.luni.util.Msg; * find this useful. The number of characters which may be pushed back can be * specified during construction. If the buffer of pushed back bytes is empty, * characters are read from the underlying reader. - * - * @since Android 1.0 */ public class PushbackReader extends FilterReader { /** @@ -45,10 +43,9 @@ public class PushbackReader extends FilterReader { * Constructs a new {@code PushbackReader} with the specified reader as * source. The size of the pushback buffer is set to the default value of 1 * character. - * + * * @param in * the source reader. - * @since Android 1.0 */ public PushbackReader(Reader in) { super(in); @@ -59,14 +56,13 @@ public class PushbackReader extends FilterReader { /** * Constructs a new {@code PushbackReader} with {@code in} as source reader. * The size of the pushback buffer is set to {@code size}. - * + * * @param in * the source reader. * @param size * the size of the pushback buffer. * @throws IllegalArgumentException * if {@code size} is negative. - * @since Android 1.0 */ public PushbackReader(Reader in, int size) { super(in); @@ -80,10 +76,9 @@ public class PushbackReader extends FilterReader { /** * Closes this reader. This implementation closes the source reader * and releases the pushback buffer. - * + * * @throws IOException * if an error occurs while closing this reader. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -97,13 +92,12 @@ public class PushbackReader extends FilterReader { * Marks the current position in this stream. Setting a mark is not * supported in this class; this implementation always throws an * {@code IOException}. - * + * * @param readAheadLimit * the number of character that can be read from this reader * before the mark is invalidated; this parameter is ignored. * @throws IOException * if this method is called. - * @since Android 1.0 */ @Override public void mark(int readAheadLimit) throws IOException { @@ -114,11 +108,10 @@ public class PushbackReader extends FilterReader { * Indicates whether this reader supports the {@code mark(int)} and * {@code reset()} methods. {@code PushbackReader} does not support them, so * it returns {@code false}. - * + * * @return always {@code false}. * @see #mark(int) * @see #reset() - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -132,13 +125,12 @@ public class PushbackReader extends FilterReader { * available characters then a character from the source reader is returned. * Blocks until one character has been read, the end of the source reader is * detected or an exception is thrown. - * + * * @return the character read or -1 if the end of the source reader has been * reached. * @throws IOException * if this reader is closed or an I/O error occurs while reading * from this reader. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -164,7 +156,7 @@ public class PushbackReader extends FilterReader { * read from the pushback buffer first, then from the source reader if more * bytes are required. Blocks until {@code count} characters have been read, * the end of the source reader is detected or an exception is thrown. - * + * * @param buffer * the array in which to store the characters read from this * reader. @@ -182,7 +174,6 @@ public class PushbackReader extends FilterReader { * @throws IOException * if this reader is closed or another I/O error occurs while * reading from this reader. - * @since Android 1.0 */ @Override public int read(char[] buffer, int offset, int count) throws IOException { @@ -236,7 +227,7 @@ public class PushbackReader extends FilterReader { * Indicates whether this reader is ready to be read without blocking. * Returns {@code true} if this reader will not block when {@code read} is * called, {@code false} if unknown or blocking will occur. - * + * * @return {@code true} if the receiver will not block when * {@code read()} is called, {@code false} if unknown * or blocking will occur. @@ -244,7 +235,6 @@ public class PushbackReader extends FilterReader { * if this reader is closed or some other I/O error occurs. * @see #read() * @see #read(char[], int, int) - * @since Android 1.0 */ @Override public boolean ready() throws IOException { @@ -260,10 +250,9 @@ public class PushbackReader extends FilterReader { * Resets this reader to the last marked position. Resetting the reader is * not supported in this class; this implementation always throws an * {@code IOException}. - * + * * @throws IOException * if this method is called. - * @since Android 1.0 */ @Override public void reset() throws IOException { @@ -279,8 +268,7 @@ public class PushbackReader extends FilterReader { * contents of {@code buffer}, an {@code IOException} is thrown. Parts of * {@code buffer} may have already been copied to the pushback buffer when * the exception is thrown. - * </p> - * + * * @param buffer * the buffer containing the characters to push back to this * reader. @@ -288,7 +276,6 @@ public class PushbackReader extends FilterReader { * if this reader is closed or the free space in the internal * pushback buffer is not sufficient to store the contents of * {@code buffer}. - * @since Android 1.0 */ public void unread(char[] buffer) throws IOException { unread(buffer, 0, buffer.length); @@ -305,8 +292,7 @@ public class PushbackReader extends FilterReader { * subset of {@code buffer}, an {@code IOException} is thrown. Parts of * {@code buffer} may have already been copied to the pushback buffer when * the exception is thrown. - * </p> - * + * * @param buffer * the buffer containing the characters to push back to this * reader. @@ -324,7 +310,6 @@ public class PushbackReader extends FilterReader { * contents of {@code buffer}. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ public void unread(char[] buffer, int offset, int count) throws IOException { synchronized (lock) { @@ -361,14 +346,12 @@ public class PushbackReader extends FilterReader { * <p> * If this reader's internal pushback buffer cannot store the character, an * {@code IOException} is thrown. - * </p> - * + * * @param oneChar * the character to push back to this stream. * @throws IOException * if this reader is closed or the internal pushback buffer is * full. - * @since Android 1.0 */ public void unread(int oneChar) throws IOException { synchronized (lock) { @@ -386,14 +369,13 @@ public class PushbackReader extends FilterReader { * Skips {@code count} characters in this reader. This implementation skips * characters in the pushback buffer first and then in the source reader if * necessary. - * + * * @param count * the number of characters to skip. * @return the number of characters actually skipped. * @throws IllegalArgumentException if {@code count < 0}. * @throws IOException * if this reader is closed or another I/O error occurs. - * @since Android 1.0 */ @Override public long skip(long count) throws IOException { diff --git a/luni/src/main/java/java/io/RandomAccessFile.java b/luni/src/main/java/java/io/RandomAccessFile.java index 7152116..37d77f5 100644 --- a/luni/src/main/java/java/io/RandomAccessFile.java +++ b/luni/src/main/java/java/io/RandomAccessFile.java @@ -33,8 +33,6 @@ import org.apache.harmony.nio.FileChannelFactory; * opened in read/write mode, write operations are available as well. The * position of the next read or write operation can be moved forwards and * backwards after every operation. - * - * @since Android 1.0 */ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** @@ -51,7 +49,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { private IFileSystem fileSystem = Platform.getFileSystem(); private boolean isReadOnly; - + // BEGIN android-added private int options; // END android-added @@ -61,12 +59,11 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { private Object repositionLock = new RepositionLock(); - // BEGIN android-changed /** * Constructs a new {@code RandomAccessFile} based on {@code file} and opens - * it according to the access string in {@code mode}. + * it according to the access string in {@code mode}. * <p><a id="accessmode"/> - * {@code mode} may have one of following values: + * {@code mode} may have one of following values: * <table border="0"> * <tr> * <td>{@code "r"}</td> @@ -90,7 +87,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * file's content must be written synchronously to the target device.</td> * </tr> * </table> - * </p> + * * @param file * the file to open. * @param mode @@ -107,16 +104,17 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * access request according to {@code mode}. * @see java.lang.SecurityManager#checkRead(FileDescriptor) * @see java.lang.SecurityManager#checkWrite(FileDescriptor) - * @since Android 1.0 */ public RandomAccessFile(File file, String mode) throws FileNotFoundException { super(); + // BEGIN android-changed options = 0; - + // END android-changed + fd = new FileDescriptor(); - + if (mode.equals("r")) { //$NON-NLS-1$ isReadOnly = true; fd.readOnly = true; @@ -143,8 +141,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { security.checkWrite(file.getPath()); } } - + fd.descriptor = fileSystem.open(file.properPath(true), options); + // BEGIN android-removed + // channel = FileChannelFactory.getFileChannel(this, fd.descriptor, + // options); + // END android-removed // if we are in "rws" mode, attempt to sync file+metadata if (syncMetadata) { @@ -155,14 +157,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { } } } - // END android-changed /** * Constructs a new {@code RandomAccessFile} based on the file named {@code * fileName} and opens it according to the access string in {@code mode}. * The file path may be specified absolutely or relative to the system * property {@code "user.dir"}. - * + * * @param fileName * the name of the file to open. * @param mode @@ -179,7 +180,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * access request according to {@code mode}. * @see java.lang.SecurityManager#checkRead(FileDescriptor) * @see java.lang.SecurityManager#checkWrite(FileDescriptor) - * @since Android 1.0 */ public RandomAccessFile(String fileName, String mode) throws FileNotFoundException { @@ -188,10 +188,9 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Closes this file. - * + * * @throws IOException * if an error occurs while closing this file. - * @since Android 1.0 */ public void close() throws IOException { // BEGIN android-changed @@ -208,39 +207,34 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { // END android-changed } - // BEGIN android-changed /** * Gets this file's {@link FileChannel} object. * <p> - * The file channel's {@link FileChannel.#position() position} is the same + * The file channel's {@link FileChannel#position() position} is the same * as this file's file pointer offset (see {@link #getFilePointer()}). Any * changes made to this file's file pointer offset are also visible in the * file channel's position and vice versa. - * </p> - * + * * @return this file's file channel instance. - * @since Android 1.0 */ - public final FileChannel getChannel() { - synchronized(this) { - if(channel == null) { - channel = FileChannelFactory.getFileChannel(this, fd.descriptor, - options); - } - return channel; + public final synchronized FileChannel getChannel() { + // BEGIN android-added + if(channel == null) { + channel = FileChannelFactory.getFileChannel(this, fd.descriptor, + options); } + // END android-added + return channel; } - // END android-changed /** * Gets this file's {@link FileDescriptor}. This represents the operating * system resource for this random access file. - * + * * @return this file's file descriptor object. * @throws IOException * if an error occurs while getting the file descriptor of this * file. - * @since Android 1.0 */ public final FileDescriptor getFD() throws IOException { return fd; @@ -249,13 +243,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Gets the current position within this file. All reads and * writes take place at the current file pointer position. - * + * * @return the current offset in bytes from the beginning of the file. - * + * * @throws IOException * if an error occurs while getting the file pointer of this * file. - * @since Android 1.0 */ public long getFilePointer() throws IOException { openCheck(); @@ -265,7 +258,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Checks to see if the file is currently open. Returns silently if it is, * and throws an exception if it is not. - * + * * @throws IOException * the receiver is closed. */ @@ -277,11 +270,10 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Returns the length of this file in bytes. - * + * * @return the file's length in bytes. * @throws IOException * if this file is closed or some other I/O error occurs. - * @since Android 1.0 */ public long length() throws IOException { openCheck(); @@ -301,11 +293,10 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * as an integer in the range from 0 to 255. Returns -1 if the end of the * file has been reached. Blocks until one byte has been read, the end of * the file is detected or an exception is thrown. - * + * * @return the byte read or -1 if the end of the file has been reached. * @throws IOException * if this file is closed or another I/O error occurs. - * @since Android 1.0 */ public int read() throws IOException { openCheck(); @@ -321,14 +312,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * byte array {@code buffer}. The maximum number of bytes read corresponds * to the size of {@code buffer}. Blocks until at least one byte has been * read. - * + * * @param buffer * the byte array in which to store the bytes read. * @return the number of bytes actually read or -1 if the end of the file * has been reached. * @throws IOException * if this file is closed or another I/O error occurs. - * @since Android 1.0 */ public int read(byte[] buffer) throws IOException { return read(buffer, 0, buffer.length); @@ -339,7 +329,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * and stores them in the byte array {@code buffer} starting at {@code * offset}. Blocks until {@code count} bytes have been read, the end of the * file is reached or an exception is thrown. - * + * * @param buffer * the array in which to store the bytes read from this file. * @param offset @@ -354,7 +344,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * offset + count} is greater than the size of {@code buffer}. * @throws IOException * if this file is closed or another I/O error occurs. - * @since Android 1.0 */ public int read(byte[] buffer, int offset, int count) throws IOException { // have to have four comparisions to not miss integer overflow cases @@ -383,14 +372,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads a boolean from the current position in this file. Blocks until one * byte has been read, the end of the file is reached or an exception is * thrown. - * + * * @return the next boolean value from this file. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeBoolean(boolean) - * @since Android 1.0 */ public final boolean readBoolean() throws IOException { int temp = this.read(); @@ -404,14 +392,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads an 8-bit byte from the current position in this file. Blocks until * one byte has been read, the end of the file is reached or an exception is * thrown. - * + * * @return the next signed 8-bit byte value from this file. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeBoolean(boolean) - * @since Android 1.0 */ public final byte readByte() throws IOException { int temp = this.read(); @@ -425,15 +412,14 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads a 16-bit character from the current position in this file. Blocks until * two bytes have been read, the end of the file is reached or an exception is * thrown. - * + * * @return the next char value from this file. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeChar(int) - * @since Android 1.0 - */ + */ public final char readChar() throws IOException { byte[] buffer = new byte[2]; if (read(buffer, 0, buffer.length) != buffer.length) { @@ -446,14 +432,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads a 64-bit double from the current position in this file. Blocks * until eight bytes have been read, the end of the file is reached or an * exception is thrown. - * + * * @return the next double value from this file. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeDouble(double) - * @since Android 1.0 */ public final double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); @@ -463,14 +448,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads a 32-bit float from the current position in this file. Blocks * until four bytes have been read, the end of the file is reached or an * exception is thrown. - * + * * @return the next float value from this file. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeFloat(float) - * @since Android 1.0 */ public final float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); @@ -480,7 +464,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads bytes from this file into {@code buffer}. Blocks until {@code * buffer.length} number of bytes have been read, the end of the file is * reached or an exception is thrown. - * + * * @param buffer * the buffer to read bytes into. * @throws EOFException @@ -489,7 +473,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * if this file is closed or another I/O error occurs. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ public final void readFully(byte[] buffer) throws IOException { readFully(buffer, 0, buffer.length); @@ -499,7 +482,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Read bytes from this file into {@code buffer} starting at offset {@code * offset}. This method blocks until {@code count} number of bytes have been * read. - * + * * @param buffer * the buffer to read bytes into. * @param offset @@ -516,7 +499,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * if this file is closed or another I/O error occurs. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ public final void readFully(byte[] buffer, int offset, int count) throws IOException { @@ -547,14 +529,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads a 32-bit integer from the current position in this file. Blocks * until four bytes have been read, the end of the file is reached or an * exception is thrown. - * + * * @return the next int value from this file. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeInt(int) - * @since Android 1.0 */ public final int readInt() throws IOException { byte[] buffer = new byte[4]; @@ -573,13 +554,11 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * <p> * Blocks until a line terminating sequence has been read, the end of the * file is reached or an exception is thrown. - * </p> - * + * * @return the contents of the line or {@code null} if no characters have * been read before the end of the file has been reached. * @throws IOException * if this file is closed or another I/O error occurs. - * @since Android 1.0 */ public final String readLine() throws IOException { StringBuilder line = new StringBuilder(80); // Typical line length @@ -615,14 +594,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads a 64-bit long from the current position in this file. Blocks until * eight bytes have been read, the end of the file is reached or an * exception is thrown. - * + * * @return the next long value from this file. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeLong(long) - * @since Android 1.0 */ public final long readLong() throws IOException { byte[] buffer = new byte[8]; @@ -641,14 +619,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads a 16-bit short from the current position in this file. Blocks until * two bytes have been read, the end of the file is reached or an exception * is thrown. - * + * * @return the next short value from this file. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeShort(int) - * @since Android 1.0 */ public final short readShort() throws IOException { byte[] buffer = new byte[2]; @@ -662,14 +639,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads an unsigned 8-bit byte from the current position in this file and * returns it as an integer. Blocks until one byte has been read, the end of * the file is reached or an exception is thrown. - * + * * @return the next unsigned byte value from this file as an int. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeByte(int) - * @since Android 1.0 */ public final int readUnsignedByte() throws IOException { int temp = this.read(); @@ -683,14 +659,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Reads an unsigned 16-bit short from the current position in this file and * returns it as an integer. Blocks until two bytes have been read, the end of * the file is reached or an exception is thrown. - * + * * @return the next unsigned short value from this file as an int. * @throws EOFException * if the end of this file is detected. * @throws IOException * if this file is closed or another I/O error occurs. * @see #writeShort(int) - * @since Android 1.0 */ public final int readUnsignedShort() throws IOException { byte[] buffer = new byte[2]; @@ -706,7 +681,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * is determined by the first two bytes read from the file. Blocks until all * required bytes have been read, the end of the file is reached or an * exception is thrown. - * + * * @return the next string encoded in {@link DataInput modified UTF-8} from * this file. * @throws EOFException @@ -716,7 +691,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * @throws UTFDataFormatException * if the bytes read cannot be decoded into a character string. * @see #writeUTF(String) - * @since Android 1.0 */ public final String readUTF() throws IOException { int utfSize = readUnsignedShort(); @@ -736,13 +710,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * position may be greater than the current length of the file, but the * file's length will only change if the moving of the pointer is followed * by a {@code write} operation. - * + * * @param pos * the new file pointer position. * @throws IOException * if this file is closed, {@code pos < 0} or another I/O error * occurs. - * @since Android 1.0 */ public void seek(long pos) throws IOException { if (pos < 0) { @@ -761,14 +734,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * file to the new end are undefined. The file is truncated if its current * size is bigger than {@code newLength}. If the current file pointer * position is in the truncated part, it is set to the end of the file. - * + * * @param newLength * the new file length in bytes. * @throws IllegalArgumentException * if {@code newLength < 0}. * @throws IOException * if this file is closed or another I/O error occurs. - * @since Android 1.0 */ public void setLength(long newLength) throws IOException { openCheck(); @@ -793,13 +765,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * bytes are skipped if the end of the file is reached or an exception is * thrown during the operation. Nothing is done if {@code count} is * negative. - * + * * @param count * the number of bytes to skip. * @return the number of bytes actually skipped. * @throws IOException * if this file is closed or another I/O error occurs. - * @since Android 1.0 */ public int skipBytes(int count) throws IOException { if (count > 0) { @@ -815,7 +786,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Writes the entire contents of the byte array {@code buffer} to this file, * starting at the current file pointer. - * + * * @param buffer * the buffer to write. * @throws IOException @@ -824,7 +795,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * @see #read(byte[],int,int) * @see #readFully(byte[]) * @see #readFully(byte[],int,int) - * @since Android 1.0 */ public void write(byte[] buffer) throws IOException { write(buffer, 0, buffer.length); @@ -834,7 +804,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Writes {@code count} bytes from the byte array {@code buffer} to this * file, starting at the current file pointer and using {@code offset} as * the first position within {@code buffer} to get bytes. - * + * * @param buffer * the buffer to write to this file. * @param offset @@ -848,7 +818,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * if an I/O error occurs while writing to this file. * @see #read(byte[], int, int) * @see #readFully(byte[], int, int) - * @since Android 1.0 */ public void write(byte[] buffer, int offset, int count) throws IOException { // BEGIN android-changed @@ -883,13 +852,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Writes a byte to this file, starting at the current file pointer. Only * the least significant byte of the integer {@code oneByte} is written. - * + * * @param oneByte * the byte to write to this file. * @throws IOException * if this file is closed or another I/O error occurs. * @see #read() - * @since Android 1.0 */ public void write(int oneByte) throws IOException { openCheck(); @@ -907,13 +875,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Writes a boolean to this file, starting at the current file pointer. - * + * * @param val * the boolean to write to this file. * @throws IOException * if this file is closed or another I/O error occurs. * @see #readBoolean() - * @since Android 1.0 */ public final void writeBoolean(boolean val) throws IOException { write(val ? 1 : 0); @@ -922,14 +889,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Writes an 8-bit byte to this file, starting at the current file pointer. * Only the least significant byte of the integer {@code val} is written. - * + * * @param val * the byte to write to this file. * @throws IOException * if this file is closed or another I/O error occurs. * @see #readByte() * @see #readUnsignedByte() - * @since Android 1.0 */ public final void writeByte(int val) throws IOException { write(val & 0xFF); @@ -938,7 +904,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Writes the low order 8-bit bytes from a string to this file, starting at * the current file pointer. - * + * * @param str * the string containing the bytes to write to this file * @throws IOException @@ -947,7 +913,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * @see #read(byte[],int,int) * @see #readFully(byte[]) * @see #readFully(byte[],int,int) - * @since Android 1.0 */ public final void writeBytes(String str) throws IOException { byte bytes[] = new byte[str.length()]; @@ -957,18 +922,16 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { write(bytes); } - /** * Writes a 16-bit character to this file, starting at the current file * pointer. Only the two least significant bytes of the integer {@code val} * are written, with the high byte first. - * + * * @param val * the char to write to this file. * @throws IOException * if an I/O error occurs while writing to this file. * @see #readChar() - * @since Android 1.0 */ public final void writeChar(int val) throws IOException { byte[] buffer = new byte[2]; @@ -981,13 +944,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Writes the 16-bit characters from a string to this file, starting at the * current file pointer. Each character is written in the same way as with * {@link #writeChar(int)}, with its high byte first. - * + * * @param str * the string to write to this file. * @throws IOException * if an I/O error occurs while writing to this file. * @see #readChar() - * @since Android 1.0 */ public final void writeChars(String str) throws IOException { byte newBytes[] = new byte[str.length() * 2]; @@ -1003,13 +965,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Writes a 64-bit double to this file, starting at the current file * pointer. The eight bytes returned by * {@link Double#doubleToLongBits(double)} are written to this file. - * + * * @param val * the double to write to this file. * @throws IOException * if an I/O error occurs while writing to this file. * @see #readDouble() - * @since Android 1.0 */ public final void writeDouble(double val) throws IOException { writeLong(Double.doubleToLongBits(val)); @@ -1019,13 +980,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Writes a 32-bit float to this file, starting at the current file pointer. * The four bytes returned by {@link Float#floatToIntBits(float)} are * written to this file. - * + * * @param val * the float to write to this file. * @throws IOException * if an I/O error occurs while writing to this file. * @see #readFloat() - * @since Android 1.0 */ public final void writeFloat(float val) throws IOException { writeInt(Float.floatToIntBits(val)); @@ -1035,13 +995,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Writes a 32-bit integer to this file, starting at the current file * pointer. The four bytes of the integer are written with the highest byte * first. - * + * * @param val * the int to write to this file. * @throws IOException * if an I/O error occurs while writing to this file. * @see #readInt() - * @since Android 1.0 */ public final void writeInt(int val) throws IOException { byte[] buffer = new byte[4]; @@ -1056,13 +1015,12 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Writes a 64-bit long to this file, starting at the current file * pointer. The eight bytes of the long are written with the highest byte * first. - * + * * @param val * the long to write to this file. * @throws IOException * if an I/O error occurs while writing to this file. * @see #readLong() - * @since Android 1.0 */ public final void writeLong(long val) throws IOException { byte[] buffer = new byte[8]; @@ -1082,13 +1040,13 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * Writes a 16-bit short to this file, starting at the current file * pointer. Only the two least significant bytes of the integer {@code val} * are written, with the high byte first. - * + * * @param val * the short to write to this file. * @throws IOException * if an I/O error occurs while writing to this file. * @see #readShort() - * @since Android 1.0 + * @see DataInput#readUnsignedShort() */ public final void writeShort(int val) throws IOException { writeChar(val); @@ -1097,7 +1055,7 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { /** * Writes a string encoded with {@link DataInput modified UTF-8} to this * file, starting at the current file pointer. - * + * * @param str * the string to write in {@link DataInput modified UTF-8} * format. @@ -1106,7 +1064,6 @@ public class RandomAccessFile implements DataInput, DataOutput, Closeable { * @throws UTFDataFormatException * if the encoded string is longer than 65535 bytes. * @see #readUTF() - * @since Android 1.0 */ public final void writeUTF(String str) throws IOException { int utfCount = 0, length = str.length(); diff --git a/luni/src/main/java/java/io/Reader.java b/luni/src/main/java/java/io/Reader.java index 42fb9ee..1f78f5a 100644 --- a/luni/src/main/java/java/io/Reader.java +++ b/luni/src/main/java/java/io/Reader.java @@ -33,24 +33,18 @@ import java.nio.ReadOnlyBufferException; * <p> * Many specialized readers for purposes like reading from a file already exist * in this package. - * + * * @see Writer - * - * @since Android 1.0 */ public abstract class Reader implements Readable, Closeable { /** * The object used to synchronize access to the reader. - * - * @since Android 1.0 */ protected Object lock; /** * Constructs a new {@code Reader} with {@code this} as the object used to * synchronize critical sections. - * - * @since Android 1.0 */ protected Reader() { super(); @@ -60,12 +54,11 @@ public abstract class Reader implements Readable, Closeable { /** * Constructs a new {@code Reader} with {@code lock} used to synchronize * critical sections. - * + * * @param lock * the {@code Object} used to synchronize critical sections. * @throws NullPointerException * if {@code lock} is {@code null}. - * @since Android 1.0 */ protected Reader(Object lock) { if (lock == null) { @@ -77,10 +70,9 @@ public abstract class Reader implements Readable, Closeable { /** * Closes this reader. Implementations of this method should free any * resources associated with the reader. - * + * * @throws IOException * if an error occurs while closing this reader. - * @since Android 1.0 */ public abstract void close() throws IOException; @@ -92,8 +84,7 @@ public abstract class Reader implements Readable, Closeable { * <p> * This default implementation simply throws an {@code IOException}; * subclasses must provide their own implementation. - * </p> - * + * * @param readLimit * the number of characters that can be read before the mark is * invalidated. @@ -103,7 +94,6 @@ public abstract class Reader implements Readable, Closeable { * if an error occurs while setting a mark in this reader. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ public void mark(int readLimit) throws IOException { throw new IOException(); @@ -113,9 +103,8 @@ public abstract class Reader implements Readable, Closeable { * Indicates whether this reader supports the {@code mark()} and * {@code reset()} methods. This default implementation returns * {@code false}. - * + * * @return always {@code false}. - * @since Android 1.0 */ public boolean markSupported() { return false; @@ -125,12 +114,11 @@ public abstract class Reader implements Readable, Closeable { * Reads a single character from this reader and returns it as an integer * with the two higher-order bytes set to 0. Returns -1 if the end of the * reader has been reached. - * + * * @return the character read or -1 if the end of the reader has been * reached. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ public int read() throws IOException { synchronized (lock) { @@ -146,14 +134,13 @@ public abstract class Reader implements Readable, Closeable { * Reads characters from this reader and stores them in the character array * {@code buf} starting at offset 0. Returns the number of characters * actually read or -1 if the end of the reader has been reached. - * + * * @param buf * character array to store the characters read. * @return the number of characters read or -1 if the end of the reader has * been reached. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ public int read(char[] buf) throws IOException { // BEGIN android-note @@ -167,7 +154,7 @@ public abstract class Reader implements Readable, Closeable { * at {@code offset} in the character array {@code buf}. Returns the number * of characters actually read or -1 if the end of the reader has been * reached. - * + * * @param buf * the character array to store the characters read. * @param offset @@ -179,7 +166,6 @@ public abstract class Reader implements Readable, Closeable { * been reached. * @throws IOException * if this reader is closed or some other I/O error occurs. - * @since Android 1.0 */ public abstract int read(char[] buf, int offset, int count) throws IOException; @@ -192,14 +178,13 @@ public abstract class Reader implements Readable, Closeable { * Returns {@code true} if this reader will not block when {@code read} is * called, {@code false} if unknown or blocking will occur. This default * implementation always returns {@code false}. - * + * * @return always {@code false}. * @throws IOException * if this reader is closed or some other I/O error occurs. * @see #read() * @see #read(char[]) * @see #read(char[], int, int) - * @since Android 1.0 */ public boolean ready() throws IOException { return false; @@ -211,12 +196,11 @@ public abstract class Reader implements Readable, Closeable { * location. If this reader has not been marked, the behavior of * {@code reset()} is implementation specific. This default * implementation throws an {@code IOException}. - * + * * @throws IOException * always thrown in this default implementation. * @see #mark(int) * @see #markSupported() - * @since Android 1.0 */ public void reset() throws IOException { throw new IOException(); @@ -227,7 +211,7 @@ public abstract class Reader implements Readable, Closeable { * {@code read} methods will not return these characters unless {@code * reset()} is used. This method may perform multiple reads to read {@code * count} characters. - * + * * @param count * the maximum number of characters to skip. * @return the number of characters actually skipped. @@ -238,7 +222,6 @@ public abstract class Reader implements Readable, Closeable { * @see #mark(int) * @see #markSupported() * @see #reset() - * @since Android 1.0 */ public long skip(long count) throws IOException { if (count < 0) { @@ -267,7 +250,7 @@ public abstract class Reader implements Readable, Closeable { /** * Reads characters and puts them into the {@code target} character buffer. - * + * * @param target * the destination character buffer. * @return the number of characters put into {@code target} or -1 if the end @@ -278,7 +261,6 @@ public abstract class Reader implements Readable, Closeable { * if {@code target} is {@code null}. * @throws ReadOnlyBufferException * if {@code target} is read-only. - * @since Android 1.0 */ public int read(CharBuffer target) throws IOException { if (null == target) { diff --git a/luni/src/main/java/java/io/SequenceInputStream.java b/luni/src/main/java/java/io/SequenceInputStream.java index 1b946b5..3719021 100644 --- a/luni/src/main/java/java/io/SequenceInputStream.java +++ b/luni/src/main/java/java/io/SequenceInputStream.java @@ -28,8 +28,6 @@ import org.apache.harmony.luni.util.Msg; * Concatenates two or more existing {@link InputStream}s. Reads are taken from * the first stream until it ends, then the next stream is used, until the last * stream returns end of file. - * - * @since Android 1.0 */ public class SequenceInputStream extends InputStream { /** @@ -45,14 +43,13 @@ public class SequenceInputStream extends InputStream { /** * Constructs a new {@code SequenceInputStream} using the two streams * {@code s1} and {@code s2} as the sequence of streams to read from. - * + * * @param s1 * the first stream to get bytes from. * @param s2 * the second stream to get bytes from. * @throws NullPointerException * if {@code s1} is {@code null}. - * @since Android 1.0 */ public SequenceInputStream(InputStream s1, InputStream s2) { if (s1 == null) { @@ -68,12 +65,11 @@ public class SequenceInputStream extends InputStream { * Constructs a new SequenceInputStream using the elements returned from * Enumeration {@code e} as the stream sequence. The instances returned by * {@code e.nextElement()} must be of type {@link InputStream}. - * + * * @param e * the enumeration of {@code InputStreams} to get bytes from. * @throws NullPointerException * if any of the elements in {@code e} is {@code null}. - * @since Android 1.0 */ public SequenceInputStream(Enumeration<? extends InputStream> e) { this.e = e; @@ -87,12 +83,11 @@ public class SequenceInputStream extends InputStream { /** * Returns the number of bytes that are available before the current input stream will - * block. - * + * block. + * * @return the number of bytes available in the current input stream before blocking. * @throws IOException * if an I/O error occurs in the current input stream. - * @since Android 1.0 */ @Override public int available() throws IOException { @@ -103,11 +98,10 @@ public class SequenceInputStream extends InputStream { } /** - * Closes all streams in this sequence of input stream. - * + * Closes all streams in this sequence of input stream. + * * @throws IOException * if an error occurs while closing any of the input streams. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -119,7 +113,7 @@ public class SequenceInputStream extends InputStream { /** * Sets up the next InputStream or leaves it alone if there are none left. - * + * * @throws IOException */ private void nextStream() throws IOException { @@ -142,14 +136,13 @@ public class SequenceInputStream extends InputStream { * stream first; if the end of this stream has been reached, it reads from * the next one. Blocks until one byte has been read, the end of the last * input stream in the sequence has been reached, or an exception is thrown. - * + * * @return the byte read or -1 if either the end of the last stream in the * sequence has been reached or this input stream sequence is * closed. * @throws IOException * if an error occurs while reading the current source input * stream. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -179,7 +172,7 @@ public class SequenceInputStream extends InputStream { * If a substream has already reached the end when this call is made, it * will close that substream and start with the next one. If there are no * more substreams it will return -1. - * + * * @param buffer * the array in which to store the bytes read. * @param offset @@ -197,7 +190,6 @@ public class SequenceInputStream extends InputStream { * if an I/O error occurs. * @throws NullPointerException * if {@code buffer} is {@code null}. - * @since Android 1.0 */ @Override public int read(byte[] buffer, int offset, int count) throws IOException { diff --git a/luni/src/main/java/java/io/Serializable.java b/luni/src/main/java/java/io/Serializable.java index 17690e3..9cd7816 100644 --- a/luni/src/main/java/java/io/Serializable.java +++ b/luni/src/main/java/java/io/Serializable.java @@ -28,13 +28,9 @@ package java.io; * <p> * {@code private void writeObject(java.io.ObjectOutputStream out) throws * IOException} - * </p> * <p> * {@code private void readObject(java.io.ObjectInputStream in) throws * IOException, ClassNotFoundException} - * </p> - * - * @since Android 1.0 */ public interface Serializable { /* empty */ diff --git a/luni/src/main/java/java/io/StreamCorruptedException.java b/luni/src/main/java/java/io/StreamCorruptedException.java index 1181507..9d25727 100644 --- a/luni/src/main/java/java/io/StreamCorruptedException.java +++ b/luni/src/main/java/java/io/StreamCorruptedException.java @@ -25,8 +25,6 @@ package java.io; * * @see ObjectInputStream * @see OptionalDataException - * - * @since Android 1.0 */ public class StreamCorruptedException extends ObjectStreamException { @@ -35,8 +33,6 @@ public class StreamCorruptedException extends ObjectStreamException { /** * Constructs a new {@code StreamCorruptedException} with its stack trace * filled in. - * - * @since Android 1.0 */ public StreamCorruptedException() { super(); @@ -48,7 +44,6 @@ public class StreamCorruptedException extends ObjectStreamException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public StreamCorruptedException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/StreamTokenizer.java b/luni/src/main/java/java/io/StreamTokenizer.java index 391fca8..d39e5a8 100644 --- a/luni/src/main/java/java/io/StreamTokenizer.java +++ b/luni/src/main/java/java/io/StreamTokenizer.java @@ -23,51 +23,37 @@ package java.io; * and different comment styles. The class can be used for limited processing * of source code of programming languages like Java, although it is nowhere * near a full parser. - * - * @since Android 1.0 */ public class StreamTokenizer { /** * Contains a number if the current token is a number ({@code ttype} == * {@code TT_NUMBER}). - * - * @since Android 1.0 */ public double nval; /** * Contains a string if the current token is a word ({@code ttype} == * {@code TT_WORD}). - * - * @since Android 1.0 */ public String sval; /** * The constant representing the end of the stream. - * - * @since Android 1.0 */ public static final int TT_EOF = -1; /** * The constant representing the end of the line. - * - * @since Android 1.0 */ public static final int TT_EOL = '\n'; /** * The constant representing a number token. - * - * @since Android 1.0 */ public static final int TT_NUMBER = -2; /** * The constant representing a word token. - * - * @since Android 1.0 */ public static final int TT_WORD = -3; @@ -89,8 +75,6 @@ public class StreamTokenizer { * whether {@code eolIsSignificant} is {@code true}.</li> * <li> {@code TT_EOF} - the end of the stream has been reached.</li> * </ul> - * - * @since Android 1.0 */ public int ttype = TT_UNKNOWN; @@ -135,7 +119,7 @@ public class StreamTokenizer { * specification. */ private StreamTokenizer() { - /** + /* * Initialize the default state per specification. All byte values 'A' * through 'Z', 'a' through 'z', and '\u00A0' through '\u00FF' are * considered to be alphabetic. @@ -176,7 +160,6 @@ public class StreamTokenizer { * @throws NullPointerException * if {@code is} is {@code null}. * @deprecated Use {@link #StreamTokenizer(Reader)} - * @since Android 1.0 */ @Deprecated public StreamTokenizer(InputStream is) { @@ -205,7 +188,6 @@ public class StreamTokenizer { * * @param r * the source reader from which to parse tokens. - * @since Android 1.0 */ public StreamTokenizer(Reader r) { this(); @@ -221,7 +203,6 @@ public class StreamTokenizer { * * @param ch * the character to be considered a comment character. - * @since Android 1.0 */ public void commentChar(int ch) { if (0 <= ch && ch < tokenTypes.length) { @@ -235,7 +216,6 @@ public class StreamTokenizer { * * @param flag * {@code true} if EOL is significant, {@code false} otherwise. - * @since Android 1.0 */ public void eolIsSignificant(boolean flag) { isEOLSignificant = flag; @@ -245,7 +225,6 @@ public class StreamTokenizer { * Returns the current line number. * * @return this tokenizer's current line number. - * @since Android 1.0 */ public int lineno() { return lineNumber; @@ -258,7 +237,6 @@ public class StreamTokenizer { * @param flag * {@code true} if {@code sval} should be converted to lower * case, {@code false} otherwise. - * @since Android 1.0 */ public void lowerCaseMode(boolean flag) { forceLowercase = flag; @@ -272,7 +250,6 @@ public class StreamTokenizer { * @return the value of {@code ttype}. * @throws IOException * if an I/O error occurs while parsing the next token. - * @since Android 1.0 */ public int nextToken() throws IOException { if (pushBackToken) { @@ -507,7 +484,6 @@ public class StreamTokenizer { * * @param ch * the character to be considered an ordinary character. - * @since Android 1.0 */ public void ordinaryChar(int ch) { if (0 <= ch && ch < tokenTypes.length) { @@ -525,7 +501,6 @@ public class StreamTokenizer { * the first character in the range of ordinary characters. * @param hi * the last character in the range of ordinary characters. - * @since Android 1.0 */ public void ordinaryChars(int low, int hi) { if (low < 0) { @@ -541,8 +516,6 @@ public class StreamTokenizer { /** * Specifies that this tokenizer shall parse numbers. - * - * @since Android 1.0 */ public void parseNumbers() { for (int i = '0'; i <= '9'; i++) { @@ -555,8 +528,6 @@ public class StreamTokenizer { /** * Indicates that the current token should be pushed back and returned again * the next time {@code nextToken()} is called. - * - * @since Android 1.0 */ public void pushBack() { pushBackToken = true; @@ -568,7 +539,6 @@ public class StreamTokenizer { * * @param ch * the character to be considered a quote character. - * @since Android 1.0 */ public void quoteChar(int ch) { if (0 <= ch && ch < tokenTypes.length) { @@ -586,8 +556,6 @@ public class StreamTokenizer { /** * Specifies that all characters shall be treated as ordinary characters. - * - * @since Android 1.0 */ public void resetSyntax() { for (int i = 0; i < 256; i++) { @@ -602,7 +570,6 @@ public class StreamTokenizer { * @param flag * {@code true} if {@code //} should be recognized as the start * of a comment, {@code false} otherwise. - * @since Android 1.0 */ public void slashSlashComments(boolean flag) { slashSlashComments = flag; @@ -616,7 +583,6 @@ public class StreamTokenizer { * @param flag * {@code true} if {@code /*} should be recognized as the start * of a comment, {@code false} otherwise. - * @since Android 1.0 */ public void slashStarComments(boolean flag) { slashStarComments = flag; @@ -626,7 +592,6 @@ public class StreamTokenizer { * Returns the state of this tokenizer in a readable format. * * @return the current state of this tokenizer. - * @since Android 1.0 */ @Override public String toString() { @@ -648,8 +613,6 @@ public class StreamTokenizer { result.append(sval); break; default: - // BEGIN android-changed - // copied from a newer version of harmony if (ttype == TT_UNKNOWN || tokenTypes[ttype] == TOKEN_QUOTE) { result.append(sval); } else { @@ -657,7 +620,6 @@ public class StreamTokenizer { result.append((char) ttype); result.append('\''); } - // END android-changed } result.append("], line "); //$NON-NLS-1$ result.append(lineNumber); @@ -672,7 +634,6 @@ public class StreamTokenizer { * the first character in the range of whitespace characters. * @param hi * the last character in the range of whitespace characters. - * @since Android 1.0 */ public void whitespaceChars(int low, int hi) { if (low < 0) { @@ -695,7 +656,6 @@ public class StreamTokenizer { * the first character in the range of word characters. * @param hi * the last character in the range of word characters. - * @since Android 1.0 */ public void wordChars(int low, int hi) { if (low < 0) { diff --git a/luni/src/main/java/java/io/StringBufferInputStream.java b/luni/src/main/java/java/io/StringBufferInputStream.java index 6e20ab6..cc4ab81 100644 --- a/luni/src/main/java/java/io/StringBufferInputStream.java +++ b/luni/src/main/java/java/io/StringBufferInputStream.java @@ -22,31 +22,23 @@ import org.apache.harmony.luni.util.Msg; /** * A specialized {@link InputStream} that reads bytes from a {@code String} in * a sequential manner. - * + * * @deprecated Use {@link StringReader} - * - * @since Android 1.0 */ @Deprecated public class StringBufferInputStream extends InputStream { /** * The source string containing the data to read. - * - * @since Android 1.0 */ protected String buffer; /** * The total number of characters in the source string. - * - * @since Android 1.0 */ protected int count; /** * The current position within the source string. - * - * @since Android 1.0 */ protected int pos; @@ -54,12 +46,11 @@ public class StringBufferInputStream extends InputStream { * Construct a new {@code StringBufferInputStream} with {@code str} as * source. The size of the stream is set to the {@code length()} of the * string. - * + * * @param str * the source string for this stream. * @throws NullPointerException * if {@code str} is {@code null}. - * @since Android 1.0 */ public StringBufferInputStream(String str) { if (str == null) { @@ -72,9 +63,8 @@ public class StringBufferInputStream extends InputStream { /** * Returns the number of bytes that are available before this stream will * block. - * + * * @return the number of bytes available before blocking. - * @since Android 1.0 */ @Override public synchronized int available() { @@ -85,10 +75,9 @@ public class StringBufferInputStream extends InputStream { * Reads a single byte from the source string and returns it as an integer * in the range from 0 to 255. Returns -1 if the end of the source string * has been reached. - * + * * @return the byte read or -1 if the end of the source string has been * reached. - * @since Android 1.0 */ @Override public synchronized int read() { @@ -98,7 +87,7 @@ public class StringBufferInputStream extends InputStream { /** * Reads at most {@code length} bytes from the source string and stores them * in the byte array {@code b} starting at {@code offset}. - * + * * @param b * the byte array in which to store the bytes read. * @param offset @@ -114,7 +103,6 @@ public class StringBufferInputStream extends InputStream { * {@code b}. * @throws NullPointerException * if {@code b} is {@code null}. - * @since Android 1.0 */ @Override public synchronized int read(byte[] b, int offset, int length) { @@ -153,8 +141,6 @@ public class StringBufferInputStream extends InputStream { /** * Resets this stream to the beginning of the source string. - * - * @since Android 1.0 */ @Override public synchronized void reset() { @@ -166,11 +152,10 @@ public class StringBufferInputStream extends InputStream { * returns 0 if {@code n} is negative. Less than {@code n} characters are * skipped if the end of the source string is reached before the operation * completes. - * + * * @param n * the number of characters to skip. * @return the number of characters actually skipped. - * @since Android 1.0 */ @Override public synchronized long skip(long n) { diff --git a/luni/src/main/java/java/io/StringReader.java b/luni/src/main/java/java/io/StringReader.java index 3a19429..0a9e9bb 100644 --- a/luni/src/main/java/java/io/StringReader.java +++ b/luni/src/main/java/java/io/StringReader.java @@ -22,10 +22,8 @@ import org.apache.harmony.luni.util.Msg; /** * A specialized {@link Reader} that reads characters from a {@code String} in * a sequential manner. - * + * * @see StringWriter - * - * @since Android 1.0 */ public class StringReader extends Reader { private String str; @@ -40,13 +38,12 @@ public class StringReader extends Reader { * Construct a new {@code StringReader} with {@code str} as source. The size * of the reader is set to the {@code length()} of the string and the Object * to synchronize access through is set to {@code str}. - * + * * @param str * the source string for this reader. - * @since Android 1.0 */ public StringReader(String str) { - super(str); + super(); this.str = str; this.count = str.length(); } @@ -55,22 +52,15 @@ public class StringReader extends Reader { * Closes this reader. Once it is closed, read operations on this reader * will throw an {@code IOException}. Only the first invocation of this * method has any effect. - * - * @since Android 1.0 */ @Override public void close() { - synchronized (lock) { - if (isClosed()) { - return; - } - str = null; - } + str = null; } /** * Returns a boolean indicating whether this reader is closed. - * + * * @return {@code true} if closed, otherwise {@code false}. */ private boolean isClosed() { @@ -81,7 +71,7 @@ public class StringReader extends Reader { * Sets a mark position in this reader. The parameter {@code readLimit} is * ignored for this class. Calling {@code reset()} will reposition the * reader back to the marked position. - * + * * @param readLimit * ignored for {@code StringReader} instances. * @throws IllegalArgumentException @@ -90,7 +80,6 @@ public class StringReader extends Reader { * if this reader is closed. * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public void mark(int readLimit) throws IOException { @@ -109,9 +98,8 @@ public class StringReader extends Reader { /** * Indicates whether this reader supports the {@code mark()} and {@code * reset()} methods. This implementation returns {@code true}. - * + * * @return always {@code true}. - * @since Android 1.0 */ @Override public boolean markSupported() { @@ -122,12 +110,11 @@ public class StringReader extends Reader { * Reads a single character from the source string and returns it as an * integer with the two higher-order bytes set to 0. Returns -1 if the end * of the source string has been reached. - * + * * @return the character read or -1 if the end of the source string has been * reached. * @throws IOException * if this reader is closed. - * @since Android 1.0 */ @Override public int read() throws IOException { @@ -147,7 +134,7 @@ public class StringReader extends Reader { * them at {@code offset} in the character array {@code buf}. Returns the * number of characters actually read or -1 if the end of the source string * has been reached. - * + * * @param buf * the character array to store the characters read. * @param offset @@ -162,14 +149,12 @@ public class StringReader extends Reader { * {@code offset + len} is greater than the size of {@code buf}. * @throws IOException * if this reader is closed. - * @since Android 1.0 */ @Override public int read(char[] buf, int offset, int len) throws IOException { // BEGIN android-note // changed array notation to be consistent with the rest of harmony // END android-note - // avoid int overflow // BEGIN android-changed // Exception priorities (in case of multiple errors) differ from // RI, but are spec-compliant. @@ -178,14 +163,18 @@ public class StringReader extends Reader { if (buf == null) { throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$ } - if ((offset | len) < 0 || len > buf.length - offset) { - throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$ - } - // END android-changed synchronized (lock) { + // avoid int overflow + if ((offset | len) < 0 || len > buf.length - offset) { + throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$ + } + // END android-changed if (isClosed()) { throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$ } + if (len == 0) { + return 0; + } if (pos == this.count) { return -1; } @@ -200,13 +189,12 @@ public class StringReader extends Reader { /** * Indicates whether this reader is ready to be read without blocking. This * implementation always returns {@code true}. - * + * * @return always {@code true}. * @throws IOException * if this reader is closed. * @see #read() * @see #read(char[], int, int) - * @since Android 1.0 */ @Override public boolean ready() throws IOException { @@ -223,12 +211,11 @@ public class StringReader extends Reader { * Invocations of {@code read()} and {@code skip()} will occur from this new * location. If this reader has not been marked, it is reset to the * beginning of the source string. - * + * * @throws IOException * if this reader is closed. * @see #mark(int) * @see #markSupported() - * @since Android 1.0 */ @Override public void reset() throws IOException { @@ -244,7 +231,7 @@ public class StringReader extends Reader { * Skips {@code amount} characters in the source string. Subsequent calls of * {@code read} methods will not return these characters unless {@code * reset()} is used. - * + * * @param ns * the maximum number of characters to skip. * @return the number of characters actually skipped or 0 if {@code ns < 0}. @@ -253,7 +240,6 @@ public class StringReader extends Reader { * @see #mark(int) * @see #markSupported() * @see #reset() - * @since Android 1.0 */ @Override public long skip(long ns) throws IOException { diff --git a/luni/src/main/java/java/io/StringWriter.java b/luni/src/main/java/java/io/StringWriter.java index 01a6db8..45f6c16 100644 --- a/luni/src/main/java/java/io/StringWriter.java +++ b/luni/src/main/java/java/io/StringWriter.java @@ -26,10 +26,8 @@ import org.apache.harmony.luni.util.Msg; * in a sequential manner, appending them in the process. The result can later * be queried using the {@link #StringWriter(int)} or {@link #toString()} * methods. - * + * * @see StringReader - * - * @since Android 1.0 */ public class StringWriter extends Writer { @@ -40,8 +38,6 @@ public class StringWriter extends Writer { * allocated with the default size of 16 characters. The {@code * StringBuffer} is also the {@code lock} used to synchronize access to this * writer. - * - * @since Android 1.0 */ public StringWriter() { super(); @@ -54,10 +50,9 @@ public class StringWriter extends Writer { * allocated with a size of {@code initialSize} characters. The {@code * StringBuffer} is also the {@code lock} used to synchronize access to this * writer. - * + * * @param initialSize * the intial size of the target string buffer. - * @since Android 1.0 */ public StringWriter(int initialSize) { if (initialSize < 0) { @@ -71,10 +66,9 @@ public class StringWriter extends Writer { * Calling this method has no effect. In contrast to most {@code Writer} subclasses, * the other methods in {@code StringWriter} do not throw an {@code IOException} if * {@code close()} has been called. - * + * * @throws IOException * if an error occurs while closing this writer. - * @since Android 1.0 */ @Override public void close() throws IOException { @@ -83,8 +77,6 @@ public class StringWriter extends Writer { /** * Calling this method has no effect. - * - * @since Android 1.0 */ @Override public void flush() { @@ -94,33 +86,27 @@ public class StringWriter extends Writer { /** * Gets a reference to this writer's internal {@link StringBuffer}. Any * changes made to the returned buffer are reflected in this writer. - * + * * @return a reference to this writer's internal {@code StringBuffer}. - * @since Android 1.0 */ public StringBuffer getBuffer() { - synchronized (lock) { - return buf; - } + return buf; } /** * Gets a copy of the contents of this writer as a string. - * + * * @return this writer's contents as a string. - * @since Android 1.0 */ @Override public String toString() { - synchronized (lock) { - return buf.toString(); - } + return buf.toString(); } /** * Writes {@code count} characters starting at {@code offset} in {@code buf} * to this writer's {@code StringBuffer}. - * + * * @param cbuf * the non-null character array to write. * @param offset @@ -130,7 +116,6 @@ public class StringWriter extends Writer { * @throws IndexOutOfBoundsException * if {@code offset < 0} or {@code count < 0}, or if {@code * offset + count} is greater than the size of {@code buf}. - * @since Android 1.0 */ @Override public void write(char[] cbuf, int offset, int count) { @@ -147,45 +132,40 @@ public class StringWriter extends Writer { throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$ } // END android-changed - synchronized (lock) { - this.buf.append(cbuf, offset, count); + if (count == 0) { + return; } + buf.append(cbuf, offset, count); } /** * Writes one character to this writer's {@code StringBuffer}. Only the two * least significant bytes of the integer {@code oneChar} are written. - * + * * @param oneChar * the character to write to this writer's {@code StringBuffer}. - * @since Android 1.0 */ @Override public void write(int oneChar) { - synchronized (lock) { - buf.append((char) oneChar); - } + buf.append((char) oneChar); } /** * Writes the characters from the specified string to this writer's {@code * StringBuffer}. - * + * * @param str * the non-null string containing the characters to write. - * @since Android 1.0 */ @Override public void write(String str) { - synchronized (lock) { - buf.append(str); - } + buf.append(str); } /** * Writes {@code count} characters from {@code str} starting at {@code * offset} to this writer's {@code StringBuffer}. - * + * * @param str * the non-null string containing the characters to write. * @param offset @@ -195,24 +175,20 @@ public class StringWriter extends Writer { * @throws StringIndexOutOfBoundsException * if {@code offset < 0} or {@code count < 0}, or if {@code * offset + count} is greater than the length of {@code str}. - * @since Android 1.0 */ @Override public void write(String str, int offset, int count) { String sub = str.substring(offset, offset + count); - synchronized (lock) { - buf.append(sub); - } + buf.append(sub); } /** * Appends the character {@code c} to this writer's {@code StringBuffer}. * This method works the same way as {@link #write(int)}. - * + * * @param c * the character to append to the target stream. * @return this writer. - * @since Android 1.0 */ @Override public StringWriter append(char c) { @@ -225,18 +201,17 @@ public class StringWriter extends Writer { * StringBuffer}. This method works the same way as {@code * StringWriter.write(csq.toString())}. If {@code csq} is {@code null}, then * the string "null" is written to the target stream. - * + * * @param csq * the character sequence appended to the target. * @return this writer. - * @since Android 1.0 */ @Override public StringWriter append(CharSequence csq) { if (null == csq) { - append(TOKEN_NULL, 0, TOKEN_NULL.length()); + write(TOKEN_NULL); } else { - append(csq, 0, csq.length()); + write(csq.toString()); } return this; } @@ -247,7 +222,7 @@ public class StringWriter extends Writer { * StringWriter.writer(csq.subsequence(start, end).toString())}. If {@code * csq} is {@code null}, then the specified subsequence of the string "null" * will be written to the target. - * + * * @param csq * the character sequence appended to the target. * @param start @@ -261,7 +236,6 @@ public class StringWriter extends Writer { * if {@code start > end}, {@code start < 0}, {@code end < 0} or * either {@code start} or {@code end} are greater or equal than * the length of {@code csq}. - * @since Android 1.0 */ @Override public StringWriter append(CharSequence csq, int start, int end) { diff --git a/luni/src/main/java/java/io/SyncFailedException.java b/luni/src/main/java/java/io/SyncFailedException.java index 2f8d9c7..c4f7340 100644 --- a/luni/src/main/java/java/io/SyncFailedException.java +++ b/luni/src/main/java/java/io/SyncFailedException.java @@ -20,8 +20,6 @@ package java.io; /** * Signals that the {@link FileDescriptor#sync()} method has failed to * complete. - * - * @since Android 1.0 */ public class SyncFailedException extends IOException { @@ -33,7 +31,6 @@ public class SyncFailedException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public SyncFailedException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/UTFDataFormatException.java b/luni/src/main/java/java/io/UTFDataFormatException.java index 20a7abe..215e3e2 100644 --- a/luni/src/main/java/java/io/UTFDataFormatException.java +++ b/luni/src/main/java/java/io/UTFDataFormatException.java @@ -22,9 +22,7 @@ package java.io; * likely while reading some {@link DataInputStream}. * * @see DataInputStream#readUTF() - * - * @since Android 1.0 -*/ + */ public class UTFDataFormatException extends IOException { private static final long serialVersionUID = 420743449228280612L; @@ -32,8 +30,6 @@ public class UTFDataFormatException extends IOException { /** * Constructs a new {@code UTFDataFormatException} with its stack trace * filled in. - * - * @since Android 1.0 */ public UTFDataFormatException() { super(); @@ -45,7 +41,6 @@ public class UTFDataFormatException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public UTFDataFormatException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/UnsupportedEncodingException.java b/luni/src/main/java/java/io/UnsupportedEncodingException.java index deeab29..eca6c81 100644 --- a/luni/src/main/java/java/io/UnsupportedEncodingException.java +++ b/luni/src/main/java/java/io/UnsupportedEncodingException.java @@ -18,11 +18,8 @@ package java.io; /** - * Signals that a requested character encoding is not available, either because - * it is not included a specific Android system, or because the encoding name - * is simply incorrect. - * - * @since Android 1.0 + * Thrown when a program asks for a particular character converter that is + * unavailable. */ public class UnsupportedEncodingException extends IOException { @@ -31,8 +28,6 @@ public class UnsupportedEncodingException extends IOException { /** * Constructs a new {@code UnsupportedEncodingException} with its stack * trace filled in. - * - * @since Android 1.0 */ public UnsupportedEncodingException() { super(); @@ -44,7 +39,6 @@ public class UnsupportedEncodingException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public UnsupportedEncodingException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/io/WriteAbortedException.java b/luni/src/main/java/java/io/WriteAbortedException.java index 02c2f70..11ee1fe 100644 --- a/luni/src/main/java/java/io/WriteAbortedException.java +++ b/luni/src/main/java/java/io/WriteAbortedException.java @@ -26,8 +26,6 @@ package java.io; * object. * * @see ObjectInputStream#readObject() - * - * @since Android 1.0 */ public class WriteAbortedException extends ObjectStreamException { @@ -36,8 +34,6 @@ public class WriteAbortedException extends ObjectStreamException { /** * The exception that occured when writeObject() was attempting to serialize * the object. - * - * @since Android 1.0 */ public Exception detail; @@ -50,7 +46,6 @@ public class WriteAbortedException extends ObjectStreamException { * the detail message for this exception. * @param rootCause * the exception that was thrown when serializing the object. - * @since Android 1.0 */ public WriteAbortedException(String detailMessage, Exception rootCause) { super(detailMessage); @@ -64,7 +59,6 @@ public class WriteAbortedException extends ObjectStreamException { * time. * * @return the exception message. - * @since Android 1.0 */ @Override public String getMessage() { @@ -79,7 +73,6 @@ public class WriteAbortedException extends ObjectStreamException { * Gets the cause of this exception or {@code null} if there is no cause. * * @return the exception cause. - * @since Android 1.0 */ @Override public Throwable getCause() { diff --git a/luni/src/main/java/java/io/Writer.java b/luni/src/main/java/java/io/Writer.java index 5505e80..dfb37c5 100644 --- a/luni/src/main/java/java/io/Writer.java +++ b/luni/src/main/java/java/io/Writer.java @@ -31,10 +31,8 @@ package java.io; * <p> * Many specialized readers for purposes like reading from a file already exist * in this package. - * + * * @see Reader - * - * @since Android 1.0 */ public abstract class Writer implements Appendable, Closeable, Flushable { @@ -42,16 +40,12 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * The object used to synchronize access to the writer. - * - * @since Android 1.0 */ protected Object lock; /** * Constructs a new {@code Writer} with {@code this} as the object used to * synchronize critical sections. - * - * @since Android 1.0 */ protected Writer() { super(); @@ -61,12 +55,11 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * Constructs a new {@code Writer} with {@code lock} used to synchronize * critical sections. - * + * * @param lock * the {@code Object} used to synchronize critical sections. * @throws NullPointerException * if {@code lock} is {@code null}. - * @since Android 1.0 */ protected Writer(Object lock) { if (lock == null) { @@ -78,31 +71,28 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * Closes this writer. Implementations of this method should free any * resources associated with the writer. - * + * * @throws IOException * if an error occurs while closing this writer. - * @since Android 1.0 */ public abstract void close() throws IOException; /** * Flushes this writer. Implementations of this method should ensure that * all buffered characters are written to the target. - * + * * @throws IOException * if an error occurs while flushing this writer. - * @since Android 1.0 */ public abstract void flush() throws IOException; /** * Writes the entire character buffer {@code buf} to the target. - * + * * @param buf * the non-null array containing characters to write. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ public void write(char[] buf) throws IOException { // BEGIN android-note @@ -114,7 +104,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * Writes {@code count} characters starting at {@code offset} in {@code buf} * to the target. - * + * * @param buf * the non-null character array to write. * @param offset @@ -126,7 +116,6 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * offset + count} is greater than the size of {@code buf}. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ public abstract void write(char[] buf, int offset, int count) throws IOException; @@ -137,12 +126,11 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * Writes one character to the target. Only the two least significant bytes * of the integer {@code oneChar} are written. - * + * * @param oneChar * the character to write to the target. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ public void write(int oneChar) throws IOException { synchronized (lock) { @@ -154,12 +142,11 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * Writes the characters from the specified string to the target. - * + * * @param str * the non-null string containing the characters to write. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ public void write(String str) throws IOException { char buf[] = new char[str.length()]; @@ -172,7 +159,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * Writes {@code count} characters from {@code str} starting at {@code * offset} to the target. - * + * * @param str * the non-null string containing the characters to write. * @param offset @@ -184,7 +171,6 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * @throws IndexOutOfBoundsException * if {@code offset < 0} or {@code count < 0}, or if {@code * offset + count} is greater than the length of {@code str}. - * @since Android 1.0 */ public void write(String str, int offset, int count) throws IOException { if (count < 0) { // other cases tested by getChars() @@ -201,13 +187,12 @@ public abstract class Writer implements Appendable, Closeable, Flushable { /** * Appends the character {@code c} to the target. This method works the same * way as {@link #write(int)}. - * + * * @param c * the character to append to the target stream. * @return this writer. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ public Writer append(char c) throws IOException { write(c); @@ -219,13 +204,12 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * works the same way as {@code Writer.write(csq.toString())}. If {@code * csq} is {@code null}, then the string "null" is written to the target * stream. - * + * * @param csq * the character sequence appended to the target. * @return this writer. * @throws IOException * if this writer is closed or another I/O error occurs. - * @since Android 1.0 */ public Writer append(CharSequence csq) throws IOException { if (null == csq) { @@ -242,7 +226,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * Writer.writer(csq.subsequence(start, end).toString())}. If {@code * csq} is {@code null}, then the specified subsequence of the string "null" * will be written to the target. - * + * * @param csq * the character sequence appended to the target. * @param start @@ -258,7 +242,6 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * if {@code start > end}, {@code start < 0}, {@code end < 0} or * either {@code start} or {@code end} are greater or equal than * the length of {@code csq}. - * @since Android 1.0 */ public Writer append(CharSequence csq, int start, int end) throws IOException { diff --git a/luni/src/main/java/java/lang/AbstractMethodError.java b/luni/src/main/java/java/lang/AbstractMethodError.java index cdfa0ec..4d5238a 100644 --- a/luni/src/main/java/java/lang/AbstractMethodError.java +++ b/luni/src/main/java/java/lang/AbstractMethodError.java @@ -22,8 +22,6 @@ package java.lang; * <p> * Note that this can only occur when inconsistent class files have been loaded, * since invoking an abstract method is a compile time error. - * </p> - * @since Android 1.0 */ public class AbstractMethodError extends IncompatibleClassChangeError { @@ -32,8 +30,6 @@ public class AbstractMethodError extends IncompatibleClassChangeError { /** * Constructs a new {@code AbstractMethodError} that includes the current * stack trace. - * - * @since Android 1.0 */ public AbstractMethodError() { super(); @@ -42,10 +38,9 @@ public class AbstractMethodError extends IncompatibleClassChangeError { /** * Constructs a new {@code AbstractMethodError} with the current stack trace * and the specified detail message. - * + * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public AbstractMethodError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/AbstractStringBuilder.java b/luni/src/main/java/java/lang/AbstractStringBuilder.java index 39459a0..06f8c50 100644 --- a/luni/src/main/java/java/lang/AbstractStringBuilder.java +++ b/luni/src/main/java/java/lang/AbstractStringBuilder.java @@ -23,15 +23,13 @@ import java.util.Arrays; import org.apache.harmony.luni.util.Msg; /** - * <p> * A modifiable {@link CharSequence sequence of characters} for use in creating * and modifying Strings. This class is intended as a base class for * {@link StringBuffer} and {@link StringBuilder}. - * </p> * * @see StringBuffer * @see StringBuilder - * @since Android 1.0 + * @since 1.5 */ abstract class AbstractStringBuilder { @@ -95,8 +93,8 @@ abstract class AbstractStringBuilder { } private void enlargeBuffer(int min) { - int twice = (value.length << 1) + 2; - char[] newData = new char[min > twice ? min : twice]; + int newSize = ((value.length >> 1) + value.length) + 2; + char[] newData = new char[min > newSize ? min : newSize]; System.arraycopy(value, 0, newData, 0, count); value = newData; shared = false; @@ -106,9 +104,6 @@ abstract class AbstractStringBuilder { int newSize = count + 4; if (newSize > value.length) { enlargeBuffer(newSize); - } else if (shared) { - value = value.clone(); - shared = false; } value[count++] = 'n'; value[count++] = 'u'; @@ -120,9 +115,6 @@ abstract class AbstractStringBuilder { int newSize = count + chars.length; if (newSize > value.length) { enlargeBuffer(newSize); - } else if (shared) { - value = value.clone(); - shared = false; } System.arraycopy(chars, 0, value, count, chars.length); count = newSize; @@ -137,9 +129,6 @@ abstract class AbstractStringBuilder { int newSize = count + length; if (newSize > value.length) { enlargeBuffer(newSize); - } else if (shared) { - value = value.clone(); - shared = false; } System.arraycopy(chars, start, value, count, length); count = newSize; @@ -152,10 +141,6 @@ abstract class AbstractStringBuilder { if (count == value.length) { enlargeBuffer(count + 1); } - if (shared) { - value = value.clone(); - shared = false; - } value[count++] = ch; } @@ -168,9 +153,6 @@ abstract class AbstractStringBuilder { int newSize = count + adding; if (newSize > value.length) { enlargeBuffer(newSize); - } else if (shared) { - value = value.clone(); - shared = false; } // BEGIN android-changed string._getChars(0, adding, value, count); @@ -213,7 +195,7 @@ abstract class AbstractStringBuilder { /** * Returns the number of characters that can be held without growing. - * + * * @return the capacity * @see #ensureCapacity * @see #length @@ -224,7 +206,7 @@ abstract class AbstractStringBuilder { /** * Retrieves the character at the {@code index}. - * + * * @param index * the index of the character to retrieve. * @return the char value. @@ -296,20 +278,21 @@ abstract class AbstractStringBuilder { * value of either the {@code minimumCapacity} or the current capacity * multiplied by two plus two. Although this is the general policy, there is * no guarantee that the capacity will change. - * + * * @param min * the new minimum capacity to set. */ public void ensureCapacity(int min) { if (min > value.length) { - enlargeBuffer(min); + int twice = (value.length << 1) + 2; + enlargeBuffer(twice > min ? twice : min); } } /** * Copies the requested sequence of characters to the {@code char[]} passed * starting at {@code destStart}. - * + * * @param start * the inclusive start index of the characters to copy. * @param end @@ -343,7 +326,7 @@ abstract class AbstractStringBuilder { } } - final void insert0(int index, char chars[], int start, int length) { + final void insert0(int index, char[] chars, int start, int length) { if (0 <= index && index <= count) { // start + length could overflow, start/length maybe MaxInt if (start >= 0 && 0 <= length && length <= chars.length - start) { @@ -354,8 +337,9 @@ abstract class AbstractStringBuilder { } return; } - throw new StringIndexOutOfBoundsException("offset " + start - + ", len " + length + ", array.length " + chars.length); + throw new StringIndexOutOfBoundsException("offset " + start //$NON-NLS-1$ + + ", length " + length //$NON-NLS-1$ + + ", char[].length " + chars.length); //$NON-NLS-1$ } throw new StringIndexOutOfBoundsException(index); } @@ -401,7 +385,7 @@ abstract class AbstractStringBuilder { /** * The current length. - * + * * @return the number of characters contained in this instance. */ public int length() { @@ -481,15 +465,72 @@ abstract class AbstractStringBuilder { return; } if (!shared) { - for (int i = 0, end = count, mid = count / 2; i < mid; i++) { - char temp = value[--end]; - value[end] = value[i]; - value[i] = temp; + int end = count - 1; + char frontHigh = value[0]; + char endLow = value[end]; + boolean allowFrontSur = true, allowEndSur = true; + for (int i = 0, mid = count / 2; i < mid; i++, --end) { + char frontLow = value[i + 1]; + char endHigh = value[end - 1]; + boolean surAtFront = allowFrontSur && frontLow >= 0xdc00 + && frontLow <= 0xdfff && frontHigh >= 0xd800 + && frontHigh <= 0xdbff; + if (surAtFront && (count < 3)) { + return; + } + boolean surAtEnd = allowEndSur && endHigh >= 0xd800 + && endHigh <= 0xdbff && endLow >= 0xdc00 + && endLow <= 0xdfff; + allowFrontSur = allowEndSur = true; + if (surAtFront == surAtEnd) { + if (surAtFront) { + // both surrogates + value[end] = frontLow; + value[end - 1] = frontHigh; + value[i] = endHigh; + value[i + 1] = endLow; + frontHigh = value[i + 2]; + endLow = value[end - 2]; + i++; + end--; + } else { + // neither surrogates + value[end] = frontHigh; + value[i] = endLow; + frontHigh = frontLow; + endLow = endHigh; + } + } else { + if (surAtFront) { + // surrogate only at the front + value[end] = frontLow; + value[i] = endLow; + endLow = endHigh; + allowFrontSur = false; + } else { + // surrogate only at the end + value[end] = frontHigh; + value[i] = endHigh; + frontHigh = frontLow; + allowEndSur = false; + } + } + } + if ((count & 1) == 1 && (!allowFrontSur || !allowEndSur)) { + value[end] = allowFrontSur ? endLow : frontHigh; } } else { char[] newData = new char[value.length]; for (int i = 0, end = count; i < count; i++) { - newData[--end] = value[i]; + char high = value[i]; + if ((i + 1) < count && high >= 0xd800 && high <= 0xdbff) { + char low = value[i + 1]; + if (low >= 0xdc00 && low <= 0xdfff) { + newData[--end] = low; + i++; + } + } + newData[--end] = high; } value = newData; shared = false; @@ -498,7 +539,7 @@ abstract class AbstractStringBuilder { /** * Sets the character at the {@code index}. - * + * * @param index * the zero-based index of the character to replace. * @param ch @@ -522,7 +563,7 @@ abstract class AbstractStringBuilder { * Sets the current length to a new value. If the new length is larger than * the current length, then the new characters at the end of this object * will contain the {@code char} value of {@code \u0000}. - * + * * @param length * the new length of this StringBuffer. * @exception IndexOutOfBoundsException @@ -533,16 +574,16 @@ abstract class AbstractStringBuilder { if (length < 0) { throw new StringIndexOutOfBoundsException(length); } - if (count < length) { - if (length > value.length) { - enlargeBuffer(length); + if (length > value.length) { + enlargeBuffer(length); + } else { + if (shared) { + char[] newData = new char[value.length]; + System.arraycopy(value, 0, newData, 0, count); + value = newData; + shared = false; } else { - if (shared) { - char[] newData = new char[value.length]; - System.arraycopy(value, 0, newData, 0, count); - value = newData; - shared = false; - } else { + if (count < length) { Arrays.fill(value, count, length, (char) 0); } } @@ -553,7 +594,7 @@ abstract class AbstractStringBuilder { /** * Returns the String value of the subsequence from the {@code start} index * to the current end. - * + * * @param start * the inclusive start index to begin the subsequence. * @return a String containing the subsequence. @@ -567,8 +608,8 @@ abstract class AbstractStringBuilder { return ""; //$NON-NLS-1$ } - shared = true; - return new String(start, count - start, value); + // Remove String sharing for more performance + return new String(value, start, count - start); } throw new StringIndexOutOfBoundsException(start); } @@ -576,7 +617,7 @@ abstract class AbstractStringBuilder { /** * Returns the String value of the subsequence from the {@code start} index * to the {@code end} index. - * + * * @param start * the inclusive start index to begin the subsequence. * @param end @@ -592,7 +633,7 @@ abstract class AbstractStringBuilder { return ""; //$NON-NLS-1$ } - shared = true; + // Remove String sharing for more performance return new String(value, start, end - start); } throw new StringIndexOutOfBoundsException(); @@ -600,7 +641,7 @@ abstract class AbstractStringBuilder { /** * Returns the current String representation. - * + * * @return a String containing the characters in this instance. */ @Override @@ -608,8 +649,10 @@ abstract class AbstractStringBuilder { if (count == 0) { return ""; //$NON-NLS-1$ } - - if (count >= 256 && count <= (value.length >> 1)) { + // Optimize String sharing for more performance + int wasted = value.length - count; + if (wasted >= 256 + || (wasted >= INITIAL_CAPACITY && wasted >= (count >> 1))) { return new String(value, 0, count); } shared = true; @@ -619,7 +662,7 @@ abstract class AbstractStringBuilder { /** * Returns a {@code CharSequence} of the subsequence from the {@code start} * index to the {@code end} index. - * + * * @param start * the inclusive start index to begin the subsequence. * @param end @@ -628,6 +671,7 @@ abstract class AbstractStringBuilder { * @throws IndexOutOfBoundsException * if {@code start} is negative, greater than {@code end} or if * {@code end} is greater than the current {@link #length()}. + * @since 1.4 */ public CharSequence subSequence(int start, int end) { return substring(start, end); @@ -636,12 +680,13 @@ abstract class AbstractStringBuilder { /** * Searches for the first index of the specified character. The search for * the character starts at the beginning and moves towards the end. - * + * * @param string * the string to find. * @return the index of the specified character, -1 if the character isn't * found. * @see #lastIndexOf(String) + * @since 1.4 */ public int indexOf(String string) { return indexOf(string, 0); @@ -650,7 +695,7 @@ abstract class AbstractStringBuilder { /** * Searches for the index of the specified character. The search for the * character starts at the specified offset and moves towards the end. - * + * * @param subString * the string to find. * @param start @@ -658,6 +703,7 @@ abstract class AbstractStringBuilder { * @return the index of the specified character, -1 if the character isn't * found * @see #lastIndexOf(String,int) + * @since 1.4 */ public int indexOf(String subString, int start) { if (start < 0) { @@ -698,12 +744,15 @@ abstract class AbstractStringBuilder { /** * Searches for the last index of the specified character. The search for * the character starts at the end and moves towards the beginning. - * + * * @param string * the string to find. * @return the index of the specified character, -1 if the character isn't * found. - * @see String#lastIndexOf(String) + * @throws NullPointerException + * if {@code string} is {@code null}. + * @see String#lastIndexOf(java.lang.String) + * @since 1.4 */ public int lastIndexOf(String string) { return lastIndexOf(string, count); @@ -712,14 +761,17 @@ abstract class AbstractStringBuilder { /** * Searches for the index of the specified character. The search for the * character starts at the specified offset and moves towards the beginning. - * + * * @param subString * the string to find. * @param start * the starting offset. * @return the index of the specified character, -1 if the character isn't * found. + * @throws NullPointerException + * if {@code subString} is {@code null}. * @see String#lastIndexOf(String,int) + * @since 1.4 */ public int lastIndexOf(String subString, int start) { int subCount = subString.length(); @@ -762,6 +814,8 @@ abstract class AbstractStringBuilder { /** * Trims off any extra capacity beyond the current length. Note, this method * is NOT guaranteed to change the capacity of this object. + * + * @since 1.5 */ public void trimToSize() { if (count < value.length) { @@ -774,7 +828,7 @@ abstract class AbstractStringBuilder { /** * Retrieves the Unicode code point value at the {@code index}. - * + * * @param index * the index to the {@code char} code unit. * @return the Unicode code point value. @@ -783,6 +837,7 @@ abstract class AbstractStringBuilder { * {@link #length()}. * @see Character * @see Character#codePointAt(char[], int, int) + * @since 1.5 */ public int codePointAt(int index) { if (index < 0 || index >= count) { @@ -793,7 +848,7 @@ abstract class AbstractStringBuilder { /** * Retrieves the Unicode code point value that precedes the {@code index}. - * + * * @param index * the index to the {@code char} code unit within this object. * @return the Unicode code point value. @@ -801,7 +856,8 @@ abstract class AbstractStringBuilder { * if {@code index} is less than 1 or greater than * {@link #length()}. * @see Character - * @see Character#codePointBefore(char[], int) + * @see Character#codePointBefore(char[], int, int) + * @since 1.5 */ public int codePointBefore(int index) { if (index < 1 || index > count) { @@ -811,11 +867,9 @@ abstract class AbstractStringBuilder { } /** - * <p> * Calculates the number of Unicode code points between {@code beginIndex} * and {@code endIndex}. - * </p> - * + * * @param beginIndex * the inclusive beginning index of the subsequence. * @param endIndex @@ -827,6 +881,7 @@ abstract class AbstractStringBuilder { * {@link #length()}. * @see Character * @see Character#codePointCount(char[], int, int) + * @since 1.5 */ public int codePointCount(int beginIndex, int endIndex) { if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { @@ -837,11 +892,9 @@ abstract class AbstractStringBuilder { } /** - * <p> * Returns the index that is offset {@code codePointOffset} code points from * {@code index}. - * </p> - * + * * @param index * the index to calculate the offset from. * @param codePointOffset @@ -855,6 +908,7 @@ abstract class AbstractStringBuilder { * {@code codePointOffset}. * @see Character * @see Character#offsetByCodePoints(char[], int, int, int, int) + * @since 1.5 */ public int offsetByCodePoints(int index, int codePointOffset) { return Character.offsetByCodePoints(value, 0, count, index, diff --git a/luni/src/main/java/java/lang/Appendable.java b/luni/src/main/java/java/lang/Appendable.java index 1b4e702..ca4b532 100644 --- a/luni/src/main/java/java/lang/Appendable.java +++ b/luni/src/main/java/java/lang/Appendable.java @@ -27,16 +27,13 @@ import java.io.IOException; * <p> * {@code Appendable} itself does not guarantee thread safety. This * responsibility is up to the implementing class. - * </p> * <p> * Implementing classes can choose different exception handling mechanism. They * can choose to throw exceptions other than {@code IOException} or they do not * throw any exceptions at all and use error codes instead. - * </p> - * @since Android 1.0 */ public interface Appendable { - + /** * Appends the specified character. * @@ -45,7 +42,6 @@ public interface Appendable { * @return this {@code Appendable}. * @throws IOException * if an I/O error occurs. - * @since Android 1.0 */ Appendable append(char c) throws IOException; @@ -55,14 +51,12 @@ public interface Appendable { * limited size. * <p> * If {@code csq} is {@code null}, the characters "null" are appended. - * </p> - * + * * @param csq * the character sequence to append. * @return this {@code Appendable}. * @throws IOException * if an I/O error occurs. - * @since Android 1.0 */ Appendable append(CharSequence csq) throws IOException; @@ -73,7 +67,6 @@ public interface Appendable { * to calling {@code append(csq.subSequence(start, end))}. * <p> * If {@code csq} is {@code null}, the characters "null" are appended. - * </p> * * @param csq * the character sequence to append. @@ -89,7 +82,6 @@ public interface Appendable { * or {@code end} is greater than the length of {@code csq}. * @throws IOException * if an I/O error occurs. - * @since Android 1.0 */ Appendable append(CharSequence csq, int start, int end) throws IOException; } diff --git a/luni/src/main/java/java/lang/ArithmeticException.java b/luni/src/main/java/java/lang/ArithmeticException.java index 74671fc..a6ab2a0 100644 --- a/luni/src/main/java/java/lang/ArithmeticException.java +++ b/luni/src/main/java/java/lang/ArithmeticException.java @@ -19,8 +19,6 @@ package java.lang; /** * Thrown when the an invalid arithmetic operation is attempted. - * - * @since Android 1.0 */ public class ArithmeticException extends RuntimeException { @@ -29,8 +27,6 @@ public class ArithmeticException extends RuntimeException { /** * Constructs a new {@code ArithmeticException} that includes the current * stack trace. - * - * @since Android 1.0 */ public ArithmeticException() { super(); @@ -39,10 +35,9 @@ public class ArithmeticException extends RuntimeException { /** * Constructs a new {@code ArithmeticException} with the current stack trace * and the specified detail message. - * + * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public ArithmeticException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java b/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java index 0f231d3..d43a7e6 100644 --- a/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java +++ b/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java @@ -22,8 +22,6 @@ import org.apache.harmony.luni.util.Msg; /** * Thrown when the an array is indexed with a value less than zero, or greater * than or equal to the size of the array. - * - * @since Android 1.0 */ public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException { @@ -32,8 +30,6 @@ public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException { /** * Constructs a new {@code ArrayIndexOutOfBoundsException} that includes the * current stack trace. - * - * @since Android 1.0 */ public ArrayIndexOutOfBoundsException() { super(); @@ -46,7 +42,6 @@ public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException { * * @param index * the invalid index. - * @since Android 1.0 */ public ArrayIndexOutOfBoundsException(int index) { super(Msg.getString("K0052", index)); //$NON-NLS-1$ @@ -55,10 +50,9 @@ public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException { /** * Constructs a new {@code ArrayIndexOutOfBoundsException} with the current * stack trace and the specified detail message. - * + * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public ArrayIndexOutOfBoundsException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/ArrayStoreException.java b/luni/src/main/java/java/lang/ArrayStoreException.java index b69697a..6cb9c8f 100644 --- a/luni/src/main/java/java/lang/ArrayStoreException.java +++ b/luni/src/main/java/java/lang/ArrayStoreException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when a program attempts to store an element of an incompatible type in * an array. - * - * @since Android 1.0 */ public class ArrayStoreException extends RuntimeException { @@ -30,8 +28,6 @@ public class ArrayStoreException extends RuntimeException { /** * Constructs a new {@code ArrayStoreException} that includes the current * stack trace. - * - * @since Android 1.0 */ public ArrayStoreException() { super(); @@ -40,10 +36,9 @@ public class ArrayStoreException extends RuntimeException { /** * Constructs a new {@code ArrayStoreException} with the current stack trace * and the specified detail message. - * + * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public ArrayStoreException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/AssertionError.java b/luni/src/main/java/java/lang/AssertionError.java index 8d3368b..e4d4ed0 100644 --- a/luni/src/main/java/java/lang/AssertionError.java +++ b/luni/src/main/java/java/lang/AssertionError.java @@ -19,8 +19,8 @@ package java.lang; /** * Thrown when an assertion has failed. - * - * @since Android 1.0 + * + * @since 1.4 */ public class AssertionError extends Error { @@ -28,8 +28,6 @@ public class AssertionError extends Error { /** * Constructs a new {@code AssertionError} with no message. - * - * @since Android 1.0 */ public AssertionError() { super(); @@ -44,7 +42,6 @@ public class AssertionError extends Error { * @param detailMessage * the object to be converted into the detail message and * optionally the cause. - * @since Android 1.0 */ public AssertionError(Object detailMessage) { super(String.valueOf(detailMessage), @@ -58,7 +55,6 @@ public class AssertionError extends Error { * * @param detailMessage * the value to be converted into the message. - * @since Android 1.0 */ public AssertionError(boolean detailMessage) { this(String.valueOf(detailMessage)); @@ -70,7 +66,6 @@ public class AssertionError extends Error { * * @param detailMessage * the value to be converted into the message. - * @since Android 1.0 */ public AssertionError(char detailMessage) { this(String.valueOf(detailMessage)); @@ -82,7 +77,6 @@ public class AssertionError extends Error { * * @param detailMessage * the value to be converted into the message. - * @since Android 1.0 */ public AssertionError(int detailMessage) { this(Integer.toString(detailMessage)); @@ -94,7 +88,6 @@ public class AssertionError extends Error { * * @param detailMessage * the value to be converted into the message. - * @since Android 1.0 */ public AssertionError(long detailMessage) { this(Long.toString(detailMessage)); @@ -106,7 +99,6 @@ public class AssertionError extends Error { * * @param detailMessage * the value to be converted into the message. - * @since Android 1.0 */ public AssertionError(float detailMessage) { this(Float.toString(detailMessage)); @@ -118,7 +110,6 @@ public class AssertionError extends Error { * * @param detailMessage * the value to be converted into the message. - * @since Android 1.0 */ public AssertionError(double detailMessage) { this(Double.toString(detailMessage)); diff --git a/luni/src/main/java/java/lang/Boolean.java b/luni/src/main/java/java/lang/Boolean.java index c49c384..9c476a4 100644 --- a/luni/src/main/java/java/lang/Boolean.java +++ b/luni/src/main/java/java/lang/Boolean.java @@ -21,8 +21,8 @@ import java.io.Serializable; /** * The wrapper for the primitive type {@code boolean}. - * - * @since Android 1.0 + * + * @since 1.0 */ public final class Boolean implements Serializable, Comparable<Boolean> { @@ -36,8 +36,6 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * The {@link Class} object that represents the primitive type {@code * boolean}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final Class<Boolean> TYPE = (Class<Boolean>) new boolean[0] @@ -49,16 +47,12 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * The {@code Boolean} object that represents the primitive value * {@code true}. - * - * @since Android 1.0 */ public static final Boolean TRUE = new Boolean(true); /** * The {@code Boolean} object that represents the primitive value * {@code false}. - * - * @since Android 1.0 */ public static final Boolean FALSE = new Boolean(false); @@ -68,10 +62,9 @@ public final class Boolean implements Serializable, Comparable<Boolean> { * "true" using a non-case sensitive comparison, the result will be a * Boolean representing the primitive value {@code true}, otherwise it will * be a Boolean representing the primitive value {@code false}. - * + * * @param string * the string representing a boolean value. - * @since Android 1.0 */ public Boolean(String string) { this(parseBoolean(string)); @@ -80,10 +73,9 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * Constructs a new {@code Boolean} with the specified primitive boolean * value. - * + * * @param value * the primitive boolean value, {@code true} or {@code false}. - * @since Android 1.0 */ public Boolean(boolean value) { this.value = value; @@ -92,9 +84,8 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * Gets the primitive value of this boolean, either {@code true} or * {@code false}. - * + * * @return this object's primitive value, {@code true} or {@code false}. - * @since Android 1.0 */ public boolean booleanValue() { return value; @@ -104,12 +95,11 @@ public final class Boolean implements Serializable, Comparable<Boolean> { * Compares this instance with the specified object and indicates if they * are equal. In order to be equal, {@code o} must be an instance of * {@code Boolean} and have the same boolean value as this object. - * + * * @param o * the object to compare this boolean with. * @return {@code true} if the specified object is equal to this * {@code Boolean}; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object o) { @@ -120,7 +110,7 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * Compares this object to the specified boolean object to determine their * relative order. - * + * * @param that * the boolean object to compare this object to. * @return 0 if the value of this boolean and the value of {@code that} are @@ -129,7 +119,7 @@ public final class Boolean implements Serializable, Comparable<Boolean> { * negative value if the value if this boolean is {@code false} and * the value of {@code that} is {@code true}. * @see java.lang.Comparable - * @since Android 1.0 + * @since 1.5 */ public int compareTo(Boolean that) { if (that == null) { @@ -145,10 +135,9 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * Returns an integer hash code for this boolean. - * + * * @return this boolean's hash code, which is {@code 1231} for {@code true} * values and {@code 1237} for {@code false} values. - * @since Android 1.0 */ @Override public int hashCode() { @@ -158,10 +147,9 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * Returns a string containing a concise, human-readable description of this * boolean. - * + * * @return "true" if the value of this boolean is {@code true}, "false" * otherwise. - * @since Android 1.0 */ @Override public String toString() { @@ -171,14 +159,13 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * Returns the {@code boolean} value of the system property identified by * {@code string}. - * + * * @param string * the name of the requested system property. * @return {@code true} if the system property named by {@code string} * exists and it is equal to "true" using case insensitive * comparison, {@code false} otherwise. * @see System#getProperty(String) - * @since Android 1.0 */ public static boolean getBoolean(String string) { if (string == null || string.length() == 0) { @@ -189,25 +176,24 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * Parses the specified string as a {@code boolean}. - * + * * @param s * the string representation of a boolean value. * @return {@code true} if {@code s} is not {@code null} and is equal to * {@code "true"} using case insensitive comparison, {@code false} * otherwise. - * @since Android 1.0 + * @since 1.5 */ public static boolean parseBoolean(String s) { return "true".equalsIgnoreCase(s); //$NON-NLS-1$ } /** - * Converts the specified boolean to its string representation. - * + * Converts the specified boolean to its string representation. + * * @param value * the boolean to convert. * @return "true" if {@code value} is {@code true}, "false" otherwise. - * @since Android 1.0 */ public static String toString(boolean value) { return String.valueOf(value); @@ -215,13 +201,12 @@ public final class Boolean implements Serializable, Comparable<Boolean> { /** * Parses the specified string as a boolean value. - * + * * @param string * the string representation of a boolean value. * @return {@code Boolean.TRUE} if {@code string} is equal to "true" using * case insensitive comparison, {@code Boolean.FALSE} otherwise. * @see #parseBoolean(String) - * @since Android 1.0 */ public static Boolean valueOf(String string) { return parseBoolean(string) ? Boolean.TRUE : Boolean.FALSE; @@ -233,13 +218,11 @@ public final class Boolean implements Serializable, Comparable<Boolean> { * If it is not necessary to get a new {@code Boolean} instance, it is * recommended to use this method instead of the constructor, since it * returns its static instances, which results in better performance. - * </p> - * + * * @param b * the boolean to convert to a {@code Boolean}. * @return {@code Boolean.TRUE} if {@code b} is equal to {@code true}, * {@code Boolean.FALSE} otherwise. - * @since Android 1.0 */ public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; diff --git a/luni/src/main/java/java/lang/Byte.java b/luni/src/main/java/java/lang/Byte.java index a74b539..7e20493 100644 --- a/luni/src/main/java/java/lang/Byte.java +++ b/luni/src/main/java/java/lang/Byte.java @@ -19,10 +19,11 @@ package java.lang; /** * The wrapper for the primitive type {@code byte}. - * - * @since Android 1.0 + * + * @since 1.1 */ -public final class Byte extends Number implements Comparable<Byte> { +public final class Byte extends Number implements Comparable<Byte> { + private static final long serialVersionUID = -7183698231559129828L; /** @@ -32,30 +33,24 @@ public final class Byte extends Number implements Comparable<Byte> { /** * The maximum {@code Byte} value, 2<sup>7</sup>-1. - * - * @since Android 1.0 */ public static final byte MAX_VALUE = (byte) 0x7F; /** * The minimum {@code Byte} value, -2<sup>7</sup>. - * - * @since Android 1.0 */ public static final byte MIN_VALUE = (byte) 0x80; - + /** * The number of bits needed to represent a {@code Byte} value in two's * complement form. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int SIZE = 8; /** * The {@link Class} object that represents the primitive type {@code byte}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final Class<Byte> TYPE = (Class<Byte>) new byte[0].getClass() @@ -63,7 +58,7 @@ public final class Byte extends Number implements Comparable<Byte> { // Note: This can't be set to "byte.class", since *that* is // defined to be "java.lang.Byte.TYPE"; - + /** * A cache of instances used by {@link #valueOf(byte)} and auto-boxing. */ @@ -71,10 +66,9 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Constructs a new {@code Byte} with the specified primitive byte value. - * + * * @param value * the primitive byte value to store in the new instance. - * @since Android 1.0 */ public Byte(byte value) { this.value = value; @@ -82,13 +76,12 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Constructs a new {@code Byte} from the specified string. - * + * * @param string * the string representation of a single byte value. * @throws NumberFormatException * if {@code string} can not be decoded into a byte value. * @see #parseByte(String) - * @since Android 1.0 */ public Byte(String string) throws NumberFormatException { this(parseByte(string)); @@ -96,9 +89,8 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Gets the primitive value of this byte. - * + * * @return this object's primitive value. - * @since Android 1.0 */ @Override public byte byteValue() { @@ -108,7 +100,7 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Compares this object to the specified byte object to determine their * relative order. - * + * * @param object * the byte object to compare this object to. * @return a negative value if the value of this byte is less than the value @@ -116,7 +108,7 @@ public final class Byte extends Number implements Comparable<Byte> { * {@code object} are equal; a positive value if the value of this * byte is greater than the value of {@code object}. * @see java.lang.Comparable - * @since Android 1.0 + * @since 1.2 */ public int compareTo(Byte object) { return value > object.value ? 1 : (value < object.value ? -1 : 0); @@ -127,13 +119,12 @@ public final class Byte extends Number implements Comparable<Byte> { * string can be decoded into a single byte value. The string may be an * optional minus sign "-" followed by a hexadecimal ("0x..." or "#..."), * octal ("0..."), or decimal ("...") representation of a byte. - * + * * @param string * a string representation of a single byte value. * @return a {@code Byte} containing the value represented by {@code string}. * @throws NumberFormatException * if {@code string} can not be parsed as a byte value. - * @since Android 1.0 */ public static Byte decode(String string) throws NumberFormatException { int intValue = Integer.decode(string).intValue(); @@ -153,12 +144,11 @@ public final class Byte extends Number implements Comparable<Byte> { * Compares this object with the specified object and indicates if they are * equal. In order to be equal, {@code object} must be an instance of * {@code Byte} and have the same byte value as this object. - * + * * @param object * the object to compare this byte with. * @return {@code true} if the specified object is equal to this * {@code Byte}; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -189,14 +179,13 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Parses the specified string as a signed decimal byte value. The ASCII * character \u002d ('-') is recognized as the minus sign. - * + * * @param string * the string representation of a single byte value. * @return the primitive byte value represented by {@code string}. * @throws NumberFormatException * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a byte value. - * @since Android 1.0 */ public static byte parseByte(String string) throws NumberFormatException { int intValue = Integer.parseInt(string); @@ -210,7 +199,7 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Parses the specified string as a signed byte value using the specified * radix. The ASCII character \u002d ('-') is recognized as the minus sign. - * + * * @param string * the string representation of a single byte value. * @param radix @@ -222,7 +211,6 @@ public final class Byte extends Number implements Comparable<Byte> { * {@code radix < Character.MIN_RADIX}, * {@code radix > Character.MAX_RADIX}, or if {@code string} * can not be parsed as a byte value. - * @since Android 1.0 */ public static byte parseByte(String string, int radix) throws NumberFormatException { @@ -247,11 +235,10 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Returns a string containing a concise, human-readable description of the * specified byte value. - * + * * @param value * the byte to convert to a string. * @return a printable representation of {@code value}. - * @since Android 1.0 */ public static String toString(byte value) { return Integer.toString(value); @@ -259,7 +246,7 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Parses the specified string as a signed decimal byte value. - * + * * @param string * the string representation of a single byte value. * @return a {@code Byte} instance containing the byte value represented by @@ -268,7 +255,6 @@ public final class Byte extends Number implements Comparable<Byte> { * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a byte value. * @see #parseByte(String) - * @since Android 1.0 */ public static Byte valueOf(String string) throws NumberFormatException { return valueOf(parseByte(string)); @@ -277,7 +263,7 @@ public final class Byte extends Number implements Comparable<Byte> { /** * Parses the specified string as a signed byte value using the specified * radix. - * + * * @param string * the string representation of a single byte value. * @param radix @@ -290,25 +276,23 @@ public final class Byte extends Number implements Comparable<Byte> { * {@code radix > Character.MAX_RADIX}, or if {@code string} * can not be parsed as a byte value. * @see #parseByte(String, int) - * @since Android 1.0 */ public static Byte valueOf(String string, int radix) throws NumberFormatException { return valueOf(parseByte(string, radix)); } - + /** * Returns a {@code Byte} instance for the specified byte value. * <p> * If it is not necessary to get a new {@code Byte} instance, it is * recommended to use this method instead of the constructor, since it * maintains a cache of instances which may result in better performance. - * </p> - * + * * @param b * the byte value to store in the instance. * @return a {@code Byte} instance containing {@code b}. - * @since Android 1.0 + * @since 1.5 */ public static Byte valueOf(byte b) { synchronized (CACHE) { diff --git a/luni/src/main/java/java/lang/CharSequence.java b/luni/src/main/java/java/lang/CharSequence.java index 1901192..fc1ecd3 100644 --- a/luni/src/main/java/java/lang/CharSequence.java +++ b/luni/src/main/java/java/lang/CharSequence.java @@ -21,37 +21,33 @@ package java.lang; /** * This interface represents an ordered set of characters and defines the * methods to probe them. - * - * @since Android 1.0 */ public interface CharSequence { /** * Returns the number of characters in this sequence. - * + * * @return the number of characters. - * @since Android 1.0 */ public int length(); /** * Returns the character at the specified index, with the first character * having index zero. - * + * * @param index * the index of the character to return. * @return the requested character. * @throws IndexOutOfBoundsException * if {@code index < 0} or {@code index} is greater than the * length of this sequence. - * @since Android 1.0 */ public char charAt(int index); /** * Returns a {@code CharSequence} from the {@code start} index (inclusive) * to the {@code end} index (exclusive) of this sequence. - * + * * @param start * the start offset of the sub-sequence. It is inclusive, that * is, the index of the first character that is included in the @@ -65,16 +61,14 @@ public interface CharSequence { * if {@code start < 0}, {@code end < 0}, {@code start > end}, * or if {@code start} or {@code end} are greater than the * length of this sequence. - * @since Android 1.0 */ public CharSequence subSequence(int start, int end); /** * Returns a string with the same characters in the same order as in this * sequence. - * + * * @return a string based on this sequence. - * @since Android 1.0 */ public String toString(); } diff --git a/luni/src/main/java/java/lang/Character.java b/luni/src/main/java/java/lang/Character.java index 564e37a..8e83b48 100644 --- a/luni/src/main/java/java/lang/Character.java +++ b/luni/src/main/java/java/lang/Character.java @@ -21,7 +21,7 @@ import java.io.Serializable; // BEGIN android-removed // import java.util.SortedMap; // import java.util.TreeMap; -// +// // import org.apache.harmony.luni.util.BinarySearch; // END android-removed @@ -36,7 +36,6 @@ import com.ibm.icu4jni.lang.UCharacter; * Character data is based upon the Unicode Standard, 4.0. The Unicode * specification, character tables and other information are available at <a * href="http://www.unicode.org/">http://www.unicode.org/</a>. - * </p> * <p> * Unicode characters are referred to as <i>code points</i>. The range of valid * code points is U+0000 to U+10FFFF. The <i>Basic Multilingual Plane (BMP)</i> @@ -47,14 +46,12 @@ import com.ibm.icu4jni.lang.UCharacter; * supplementary character are made up of a <i>high surrogate</i> with a value * range of 0xD800 to 0xDBFF and a <i>low surrogate</i> with a value range of * 0xDC00 to 0xDFFF. - * </p> * <p> * On the Java platform a {@code char} value represents either a single BMP code * point or a UTF-16 unit that's part of a surrogate pair. The {@code int} type * is used to represent all Unicode code points. - * </p> - * - * @since Android 1.0 + * + * @since 1.0 */ public final class Character implements Serializable, Comparable<Character> { private static final long serialVersionUID = 3786198910865385080L; @@ -63,36 +60,26 @@ public final class Character implements Serializable, Comparable<Character> { /** * The minimum {@code Character} value. - * - * @since Android 1.0 */ public static final char MIN_VALUE = '\u0000'; /** * The maximum {@code Character} value. - * - * @since Android 1.0 */ public static final char MAX_VALUE = '\uffff'; /** * The minimum radix used for conversions between characters and integers. - * - * @since Android 1.0 */ public static final int MIN_RADIX = 2; /** * The maximum radix used for conversions between characters and integers. - * - * @since Android 1.0 */ public static final int MAX_RADIX = 36; /** * The {@link Class} object that represents the primitive type {@code char}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final Class<Character> TYPE = (Class<Character>) new char[0] @@ -103,437 +90,415 @@ public final class Character implements Serializable, Comparable<Character> { /** * Unicode category constant Cn. - * - * @since Android 1.0 */ public static final byte UNASSIGNED = 0; /** * Unicode category constant Lu. - * - * @since Android 1.0 */ public static final byte UPPERCASE_LETTER = 1; /** * Unicode category constant Ll. - * - * @since Android 1.0 */ public static final byte LOWERCASE_LETTER = 2; /** * Unicode category constant Lt. - * - * @since Android 1.0 */ public static final byte TITLECASE_LETTER = 3; /** * Unicode category constant Lm. - * - * @since Android 1.0 */ public static final byte MODIFIER_LETTER = 4; /** * Unicode category constant Lo. - * - * @since Android 1.0 */ public static final byte OTHER_LETTER = 5; /** * Unicode category constant Mn. - * - * @since Android 1.0 */ public static final byte NON_SPACING_MARK = 6; /** * Unicode category constant Me. - * - * @since Android 1.0 */ public static final byte ENCLOSING_MARK = 7; /** * Unicode category constant Mc. - * - * @since Android 1.0 */ public static final byte COMBINING_SPACING_MARK = 8; /** * Unicode category constant Nd. - * - * @since Android 1.0 */ public static final byte DECIMAL_DIGIT_NUMBER = 9; /** * Unicode category constant Nl. - * - * @since Android 1.0 */ public static final byte LETTER_NUMBER = 10; /** * Unicode category constant No. - * - * @since Android 1.0 */ public static final byte OTHER_NUMBER = 11; /** * Unicode category constant Zs. - * - * @since Android 1.0 */ public static final byte SPACE_SEPARATOR = 12; /** * Unicode category constant Zl. - * - * @since Android 1.0 */ public static final byte LINE_SEPARATOR = 13; /** * Unicode category constant Zp. - * - * @since Android 1.0 */ public static final byte PARAGRAPH_SEPARATOR = 14; /** * Unicode category constant Cc. - * - * @since Android 1.0 */ public static final byte CONTROL = 15; /** * Unicode category constant Cf. - * - * @since Android 1.0 */ public static final byte FORMAT = 16; /** * Unicode category constant Co. - * - * @since Android 1.0 */ public static final byte PRIVATE_USE = 18; /** * Unicode category constant Cs. - * - * @since Android 1.0 */ public static final byte SURROGATE = 19; /** * Unicode category constant Pd. - * - * @since Android 1.0 */ public static final byte DASH_PUNCTUATION = 20; /** * Unicode category constant Ps. - * - * @since Android 1.0 */ public static final byte START_PUNCTUATION = 21; /** * Unicode category constant Pe. - * - * @since Android 1.0 */ public static final byte END_PUNCTUATION = 22; /** * Unicode category constant Pc. - * - * @since Android 1.0 */ public static final byte CONNECTOR_PUNCTUATION = 23; /** * Unicode category constant Po. - * - * @since Android 1.0 */ public static final byte OTHER_PUNCTUATION = 24; /** * Unicode category constant Sm. - * - * @since Android 1.0 */ public static final byte MATH_SYMBOL = 25; /** * Unicode category constant Sc. - * - * @since Android 1.0 */ public static final byte CURRENCY_SYMBOL = 26; /** * Unicode category constant Sk. - * - * @since Android 1.0 */ public static final byte MODIFIER_SYMBOL = 27; /** * Unicode category constant So. - * - * @since Android 1.0 */ public static final byte OTHER_SYMBOL = 28; /** * Unicode category constant Pi. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte INITIAL_QUOTE_PUNCTUATION = 29; /** * Unicode category constant Pf. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte FINAL_QUOTE_PUNCTUATION = 30; /** * Unicode bidirectional constant. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_UNDEFINED = -1; /** * Unicode bidirectional constant L. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0; /** * Unicode bidirectional constant R. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1; /** * Unicode bidirectional constant AL. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 2; /** * Unicode bidirectional constant EN. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 3; /** * Unicode bidirectional constant ES. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 4; /** * Unicode bidirectional constant ET. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 5; /** * Unicode bidirectional constant AN. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_ARABIC_NUMBER = 6; /** * Unicode bidirectional constant CS. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 7; /** * Unicode bidirectional constant NSM. * - * @since Android 1.0 + * @since 1.4 */ public static final byte DIRECTIONALITY_NONSPACING_MARK = 8; /** * Unicode bidirectional constant BN. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 9; /** * Unicode bidirectional constant B. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 10; /** * Unicode bidirectional constant S. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 11; /** * Unicode bidirectional constant WS. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_WHITESPACE = 12; /** * Unicode bidirectional constant ON. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 13; /** * Unicode bidirectional constant LRE. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 14; /** * Unicode bidirectional constant LRO. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 15; /** * Unicode bidirectional constant RLE. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 16; /** * Unicode bidirectional constant RLO. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 17; /** * Unicode bidirectional constant PDF. - * - * @since Android 1.0 + * + * @since 1.4 */ public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 18; - + /** * The minimum value of a high surrogate or leading surrogate unit in UTF-16 * encoding, {@code '\uD800'}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final char MIN_HIGH_SURROGATE = '\uD800'; /** * The maximum value of a high surrogate or leading surrogate unit in UTF-16 * encoding, {@code '\uDBFF'}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final char MAX_HIGH_SURROGATE = '\uDBFF'; /** * The minimum value of a low surrogate or trailing surrogate unit in UTF-16 * encoding, {@code '\uDC00'}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final char MIN_LOW_SURROGATE = '\uDC00'; /** * The maximum value of a low surrogate or trailing surrogate unit in UTF-16 * encoding, {@code '\uDFFF'}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final char MAX_LOW_SURROGATE = '\uDFFF'; /** * The minimum value of a surrogate unit in UTF-16 encoding, {@code '\uD800'}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final char MIN_SURROGATE = '\uD800'; /** * The maximum value of a surrogate unit in UTF-16 encoding, {@code '\uDFFF'}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final char MAX_SURROGATE = '\uDFFF'; /** * The minimum value of a supplementary code point, {@code U+010000}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x10000; /** * The minimum code point value, {@code U+0000}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int MIN_CODE_POINT = 0x000000; /** * The maximum code point value, {@code U+10FFFF}. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int MAX_CODE_POINT = 0x10FFFF; /** - * The number of bits required to represent a {@code Character} value in - * two's compliment form. - * - * @since Android 1.0 + * The number of bits required to represent a {@code Character} value + * unsigned form. + * + * @since 1.5 */ public static final int SIZE = 16; // BEGIN android-removed - // removed strings containing information about chars that now are read from - // icu data. + // Unicode 3.0.1 (same as Unicode 3.0.0) + // private static final String bidiKeys = ... + + // private static final char[] bidiValues = ... + + // private static final char[] mirrored = ... + + // Unicode 3.0.1 (same as Unicode 3.0.0) + // private static final String typeKeys = ... + + // private static final char[] typeValues = ... + + // private static final int[] typeValuesCache = ... + + // Unicode 3.0.1 (same as Unicode 3.0.0) + // private static final String uppercaseKeys = ... + + // private static final char[] uppercaseValues = ... + + // private static final int[] uppercaseValuesCache = ... + + // private static final String lowercaseKeys = ... + + // private static final char[] lowercaseValues = ... + + // private static final int[] lowercaseValuesCache = ... + + // private static final String digitKeys = ... + + // private static final char[] digitValues = ... // END android-removed - + + // BEGIN android-note + // put this in a helper class so that it's only initialized on demand? + // END android-note private static final char[] typeTags = "\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0000\u0000\u0000\u0000\u0003\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0000\u0000\u0000\u0000\u0002" .getValue(); - + + // BEGIN android-note + // put this in a helper class so that it's only initialized on demand? + // END android-note private static final byte[] DIRECTIONALITY = new byte[] { DIRECTIONALITY_LEFT_TO_RIGHT, DIRECTIONALITY_RIGHT_TO_LEFT, DIRECTIONALITY_EUROPEAN_NUMBER, @@ -557,24 +522,28 @@ public final class Character implements Serializable, Comparable<Character> { private static final int ISJAVAPART = 2; // BEGIN android-removed - // removed strings containing information about chars that now are read from - // icu data. + // Unicode 3.0.1 (same as Unicode 3.0.0) + // private static final String titlecaseKeys = ... + + // private static final char[] titlecaseValues = ... + + // Unicode 3.0.0 (NOT the same as Unicode 3.0.1) + // private static final String numericKeys = ... + + // private static final char[] numericValues = ... // END android-removed - - /** + + /* * Represents a subset of the Unicode character set. - * - * @since Android 1.0 */ public static class Subset { String name; /** * Constructs a new {@code Subset}. - * + * * @param string * this subset's name. - * @since Android 1.0 */ protected Subset(String string) { if (string == null) { @@ -586,12 +555,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Compares this character subset with the specified object. Uses * {@link java.lang.Object#equals(Object)} to do the comparison. - * + * * @param object * the object to compare this character subset with. * @return {@code true} if {@code object} is this subset, that is, if * {@code object == this}; {@code false} otherwise. - * @since Android 1.0 */ @Override public final boolean equals(Object object) { @@ -600,10 +568,9 @@ public final class Character implements Serializable, Comparable<Character> { /** * Returns the integer hash code for this character subset. - * + * * @return this subset's hash code, which is the hash code computed by * {@link java.lang.Object#hashCode()}. - * @since Android 1.0 */ @Override public final int hashCode() { @@ -612,9 +579,8 @@ public final class Character implements Serializable, Comparable<Character> { /** * Returns the string representation of this subset. - * + * * @return this subset's name. - * @since Android 1.0 */ @Override public final String toString() { @@ -622,799 +588,796 @@ public final class Character implements Serializable, Comparable<Character> { } } - // BEGIN android-changed - /** * Represents a block of Unicode characters, as defined by the Unicode 4.0.1 * specification. - * - * @since Android 1.0 + * + * @since 1.2 */ public static final class UnicodeBlock extends Subset { /** * The "Surrogates Area" Unicode Block. - * + * * @deprecated As of Java 5, this block has been replaced by * {@link #HIGH_SURROGATES}, * {@link #HIGH_PRIVATE_USE_SURROGATES} and * {@link #LOW_SURROGATES}. - * @since Android 1.0 */ @Deprecated - public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA"); + public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA", 0x0, 0x0); /** - * The "Basic Latin" Unicode Block. + * The "Basic Latin" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN"); + public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN", 0x0, 0x7f); /** - * The "Latin-1 Supplement" Unicode Block. + * The "Latin-1 Supplement" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT"); + public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT", 0x80, 0xff); /** - * The "Latin Extended-A" Unicode Block. + * The "Latin Extended-A" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A"); + public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A", 0x100, 0x17f); /** - * The "Latin Extended-B" Unicode Block. + * The "Latin Extended-B" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B"); + public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B", 0x180, 0x24f); /** - * The "IPA Extensions" Unicode Block. + * The "IPA Extensions" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS"); + public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS", 0x250, 0x2af); /** - * The "Spacing Modifier Letters" Unicode Block. + * The "Spacing Modifier Letters" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS"); + public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS", 0x2b0, 0x2ff); /** - * The "Combining Diacritical Marks" Unicode Block. + * The "Combining Diacritical Marks" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS"); + public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", 0x300, 0x36f); /** * The "Greek and Coptic" Unicode Block. Previously referred * to as "Greek". - * - * @since Android 1.0 + * + * @since 1.2 */ - public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK"); + public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK", 0x370, 0x3ff); /** - * The "Cyrillic" Unicode Block. + * The "Cyrillic" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC"); + public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC", 0x400, 0x4ff); /** * The "Cyrillic Supplement" Unicode Block. Previously * referred to as "Cyrillic Supplementary". - * - * @since Android 1.0 + * + * @since 1.5 */ - public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY"); + public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY", 0x500, 0x52f); /** - * The "Armenian" Unicode Block. + * The "Armenian" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN"); + public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN", 0x530, 0x58f); /** - * The "Hebrew" Unicode Block. + * The "Hebrew" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW"); + public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW", 0x590, 0x5ff); /** - * The "Arabic" Unicode Block. + * The "Arabic" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC"); + public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC", 0x600, 0x6ff); /** - * The "Syriac" Unicode Block. + * The "Syriac" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC"); + public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC", 0x700, 0x74f); /** - * The "Thaana" Unicode Block. + * The "Thaana" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA"); + public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA", 0x780, 0x7bf); /** - * The "Devanagari" Unicode Block. + * The "Devanagari" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI"); + public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI", 0x900, 0x97f); /** - * The "Bengali" Unicode Block. + * The "Bengali" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI"); + public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI", 0x980, 0x9ff); /** - * The "Gurmukhi" Unicode Block. + * The "Gurmukhi" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI"); + public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI", 0xa00, 0xa7f); /** - * The "Gujarati" Unicode Block. + * The "Gujarati" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI"); + public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI", 0xa80, 0xaff); /** - * The "Oriya" Unicode Block. + * The "Oriya" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA"); + public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA", 0xb00, 0xb7f); /** - * The "Tamil" Unicode Block. + * The "Tamil" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL"); + public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL", 0xb80, 0xbff); /** - * The "Telugu" Unicode Block. + * The "Telugu" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU"); + public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU", 0xc00, 0xc7f); /** - * The "Kannada" Unicode Block. + * The "Kannada" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA"); + public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA", 0xc80, 0xcff); /** - * The "Malayalam" Unicode Block. + * The "Malayalam" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM"); + public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM", 0xd00, 0xd7f); /** - * The "Sinhala" Unicode Block. + * The "Sinhala" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA"); + public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA", 0xd80, 0xdff); /** - * The "Thai" Unicode Block. + * The "Thai" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock THAI = new UnicodeBlock("THAI"); + public static final UnicodeBlock THAI = new UnicodeBlock("THAI", 0xe00, 0xe7f); /** - * The "Lao" Unicode Block. + * The "Lao" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock LAO = new UnicodeBlock("LAO"); + public static final UnicodeBlock LAO = new UnicodeBlock("LAO", 0xe80, 0xeff); /** - * The "Tibetan" Unicode Block. + * The "Tibetan" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN"); + public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN", 0xf00, 0xfff); /** - * The "Myanmar" Unicode Block. + * The "Myanmar" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR"); + public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR", 0x1000, 0x109f); /** - * The "Georgian" Unicode Block. + * The "Georgian" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN"); + public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN", 0x10a0, 0x10ff); /** - * The "Hangul Jamo" Unicode Block. + * The "Hangul Jamo" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO"); + public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO", 0x1100, 0x11ff); /** - * The "Ethiopic" Unicode Block. + * The "Ethiopic" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC"); + public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC", 0x1200, 0x137f); /** - * The "Cherokee" Unicode Block. + * The "Cherokee" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE"); + public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE", 0x13a0, 0x13ff); /** - * The "Unified Canadian Aboriginal Syllabics" Unicode Block. + * The "Unified Canadian Aboriginal Syllabics" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS"); + public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS", 0x1400, 0x167f); /** - * The "Ogham" Unicode Block. + * The "Ogham" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM"); + public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM", 0x1680, 0x169f); /** - * The "Runic" Unicode Block. + * The "Runic" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC"); + public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC", 0x16a0, 0x16ff); /** - * The "Tagalog" Unicode Block. + * The "Tagalog" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG"); + public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG", 0x1700, 0x171f); /** - * The "Hanunoo" Unicode Block. + * The "Hanunoo" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO"); + public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO", 0x1720, 0x173f); /** - * The "Buhid" Unicode Block. + * The "Buhid" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID"); + public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID", 0x1740, 0x175f); /** - * The "Tagbanwa" Unicode Block. + * The "Tagbanwa" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA"); + public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA", 0x1760, 0x177f); /** - * The "Khmer" Unicode Block. + * The "Khmer" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER"); + public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER", 0x1780, 0x17ff); /** - * The "Mongolian" Unicode Block. + * The "Mongolian" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN"); + public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN", 0x1800, 0x18af); /** - * The "Limbu" Unicode Block. + * The "Limbu" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU"); + public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU", 0x1900, 0x194f); /** - * The "Tai Le" Unicode Block. + * The "Tai Le" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE"); + public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE", 0x1950, 0x197f); /** - * The "Khmer Symbols" Unicode Block. + * The "Khmer Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS"); + public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS", 0x19e0, 0x19ff); /** - * The "Phonetic Extensions" Unicode Block. + * The "Phonetic Extensions" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS"); + public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS", 0x1d00, 0x1d7f); /** - * The "Latin Extended Additional" Unicode Block. + * The "Latin Extended Additional" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL"); + public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", 0x1e00, 0x1eff); /** - * The "Greek Extended" Unicode Block. + * The "Greek Extended" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED"); + public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED", 0x1f00, 0x1fff); /** - * The "General Punctuation" Unicode Block. + * The "General Punctuation" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION"); + public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION", 0x2000, 0x206f); /** - * The "Superscripts and Subscripts" Unicode Block. + * The "Superscripts and Subscripts" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS"); + public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", 0x2070, 0x209f); /** - * The "Currency Symbols" Unicode Block. + * The "Currency Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS"); + public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS", 0x20a0, 0x20cf); /** * The "Combining Diacritical Marks for Symbols" Unicode * Block. Previously referred to as "Combining Marks for * Symbols". - * - * @since Android 1.0 + * + * @since 1.2 */ - public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS"); + public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", 0x20d0, 0x20ff); /** - * The "Letterlike Symbols" Unicode Block. + * The "Letterlike Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS"); + public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS", 0x2100, 0x214f); /** - * The "Number Forms" Unicode Block. + * The "Number Forms" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS"); + public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS", 0x2150, 0x218f); /** - * The "Arrows" Unicode Block. + * The "Arrows" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS"); + public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS", 0x2190, 0x21ff); /** - * The "Mathematical Operators" Unicode Block. + * The "Mathematical Operators" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS"); + public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS", 0x2200, 0x22ff); /** - * The "Miscellaneous Technical" Unicode Block. + * The "Miscellaneous Technical" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL"); + public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL", 0x2300, 0x23ff); /** - * The "Control Pictures" Unicode Block. + * The "Control Pictures" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES"); + public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES", 0x2400, 0x243f); /** - * The "Optical Character Recognition" Unicode Block. + * The "Optical Character Recognition" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION"); + public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", 0x2440, 0x245f); /** - * The "Enclosed Alphanumerics" Unicode Block. + * The "Enclosed Alphanumerics" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS"); + public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS", 0x2460, 0x24ff); /** - * The "Box Drawing" Unicode Block. + * The "Box Drawing" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING"); + public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING", 0x2500, 0x257f); /** - * The "Block Elements" Unicode Block. + * The "Block Elements" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS"); + public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS", 0x2580, 0x259f); /** - * The "Geometric Shapes" Unicode Block. + * The "Geometric Shapes" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES"); + public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES", 0x25a0, 0x25ff); /** - * The "Miscellaneous Symbols" Unicode Block. + * The "Miscellaneous Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS"); + public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS", 0x2600, 0x26ff); /** - * The "Dingbats" Unicode Block. + * The "Dingbats" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS"); + public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS", 0x2700, 0x27bf); /** - * The "Miscellaneous Mathematical Symbols-A" Unicode Block. + * The "Miscellaneous Mathematical Symbols-A" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A"); + public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A", 0x27c0, 0x27ef); /** - * The "Supplemental Arrows-A" Unicode Block. + * The "Supplemental Arrows-A" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A"); + public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", 0x27f0, 0x27ff); /** - * The "Braille Patterns" Unicode Block. + * The "Braille Patterns" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS"); + public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS", 0x2800, 0x28ff); /** - * The "Supplemental Arrows-B" Unicode Block. + * The "Supplemental Arrows-B" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B"); + public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", 0x2900, 0x297f); /** - * The "Miscellaneous Mathematical Symbols-B" Unicode Block. + * The "Miscellaneous Mathematical Symbols-B" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B"); + public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", 0x2980, 0x29ff); /** - * The "Supplemental Mathematical Operators" Unicode Block. + * The "Supplemental Mathematical Operators" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS"); + public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS", 0x2a00, 0x2aff); /** - * The "Miscellaneous Symbols and Arrows" Unicode Block. + * The "Miscellaneous Symbols and Arrows" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS"); + public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", 0x2b00, 0x2bff); /** - * The "CJK Radicals Supplement" Unicode Block. + * The "CJK Radicals Supplement" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT"); + public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", 0x2e80, 0x2eff); /** - * The "Kangxi Radicals" Unicode Block. + * The "Kangxi Radicals" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS"); + public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS", 0x2f00, 0x2fdf); /** - * The "Ideographic Description Characters" Unicode Block. + * The "Ideographic Description Characters" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS"); + public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", 0x2ff0, 0x2fff); /** - * The "CJK Symbols and Punctuation" Unicode Block. + * The "CJK Symbols and Punctuation" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION"); + public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", 0x3000, 0x303f); /** - * The "Hiragana" Unicode Block. + * The "Hiragana" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA"); + public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA", 0x3040, 0x309f); /** - * The "Katakana" Unicode Block. + * The "Katakana" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA"); + public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA", 0x30a0, 0x30ff); /** - * The "Bopomofo" Unicode Block. + * The "Bopomofo" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO"); + public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO", 0x3100, 0x312f); /** - * The "Hangul Compatibility Jamo" Unicode Block. + * The "Hangul Compatibility Jamo" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO"); + public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", 0x3130, 0x318f); /** - * The "Kanbun" Unicode Block. + * The "Kanbun" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN"); + public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN", 0x3190, 0x319f); /** - * The "Bopomofo Extended" Unicode Block. + * The "Bopomofo Extended" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED"); + public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED", 0x31a0, 0x31bf); /** - * The "Katakana Phonetic Extensions" Unicode Block. + * The "Katakana Phonetic Extensions" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS"); + public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", 0x31f0, 0x31ff); /** - * The "Enclosed CJK Letters and Months" Unicode Block. + * The "Enclosed CJK Letters and Months" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS"); + public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", 0x3200, 0x32ff); /** - * The "CJK Compatibility" Unicode Block. + * The "CJK Compatibility" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY"); + public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY", 0x3300, 0x33ff); /** - * The "CJK Unified Ideographs Extension A" Unicode Block. + * The "CJK Unified Ideographs Extension A" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A"); + public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", 0x3400, 0x4dbf); /** - * The "Yijing Hexagram Symbols" Unicode Block. + * The "Yijing Hexagram Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS"); + public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", 0x4dc0, 0x4dff); /** - * The "CJK Unified Ideographs" Unicode Block. + * The "CJK Unified Ideographs" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS"); + public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", 0x4e00, 0x9fff); /** - * The "Yi Syllables" Unicode Block. + * The "Yi Syllables" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES"); + public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES", 0xa000, 0xa48f); /** - * The "Yi Radicals" Unicode Block. + * The "Yi Radicals" Unicode Block. * - * @since Android 1.0 + * @since 1.4 */ - public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS"); + public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS", 0xa490, 0xa4cf); /** - * The "Hangul Syllables" Unicode Block. + * The "Hangul Syllables" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES"); + public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES", 0xac00, 0xd7af); /** * The "High Surrogates" Unicode Block. This block represents * code point values in the high surrogate range 0xD800 to 0xDB7F - * - * @since Android 1.0 */ - public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES"); + public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES", 0xd800, 0xdb7f); /** * The "High Private Use Surrogates" Unicode Block. This block * represents code point values in the high surrogate range 0xDB80 to * 0xDBFF - * - * @since Android 1.0 */ - public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES"); + public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", 0xdb80, 0xdbff); /** * The "Low Surrogates" Unicode Block. This block represents * code point values in the low surrogate range 0xDC00 to 0xDFFF - * - * @since Android 1.0 */ - public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES"); + public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES", 0xdc00, 0xdfff); /** - * The "Private Use Area" Unicode Block. + * The "Private Use Area" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA"); + public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA", 0xe000, 0xf8ff); /** - * The "CJK Compatibility Ideographs" Unicode Block. + * The "CJK Compatibility Ideographs" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS"); + public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS", 0xf900, 0xfaff); /** - * The "Alphabetic Presentation Forms" Unicode Block. + * The "Alphabetic Presentation Forms" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS"); + public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", 0xfb00, 0xfb4f); /** - * The "Arabic Presentation Forms-A" Unicode Block. + * The "Arabic Presentation Forms-A" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A"); + public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", 0xfb50, 0xfdff); /** - * The "Variation Selectors" Unicode Block. + * The "Variation Selectors" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS"); + public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS", 0xfe00, 0xfe0f); /** - * The "Combining Half Marks" Unicode Block. + * The "Combining Half Marks" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS"); + public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS", 0xfe20, 0xfe2f); /** - * The "CJK Compatibility Forms" Unicode Block. + * The "CJK Compatibility Forms" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS"); + public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS", 0xfe30, 0xfe4f); /** - * The "Small Form Variants" Unicode Block. + * The "Small Form Variants" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS"); + public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS", 0xfe50, 0xfe6f); /** - * The "Arabic Presentation Forms-B" Unicode Block. + * The "Arabic Presentation Forms-B" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B"); + public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", 0xfe70, 0xfeff); /** - * The "Halfwidth and Fullwidth Forms" Unicode Block. + * The "Halfwidth and Fullwidth Forms" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS"); + public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS", 0xff00, 0xffef); /** - * The "Specials" Unicode Block. + * The "Specials" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS"); + public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS", 0xfff0, 0xffff); /** - * The "Linear B Syllabary" Unicode Block. + * The "Linear B Syllabary" Unicode Block. * - * @since Android 1.0 + * @since 1.2 */ - public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY"); + public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY", 0x10000, 0x1007f); /** - * The "Linear B Ideograms" Unicode Block. + * The "Linear B Ideograms" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS"); + public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS", 0x10080, 0x100ff); /** - * The "Aegean Numbers" Unicode Block. + * The "Aegean Numbers" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS"); + public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS", 0x10100, 0x1013f); /** - * The "Old Italic" Unicode Block. + * The "Old Italic" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC"); + public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC", 0x10300, 0x1032f); /** - * The "Gothic" Unicode Block. + * The "Gothic" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC"); + public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC", 0x10330, 0x1034f); /** - * The "Ugaritic" Unicode Block. + * The "Ugaritic" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC"); + public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC", 0x10380, 0x1039f); /** - * The "Deseret" Unicode Block. + * The "Deseret" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET"); + public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET", 0x10400, 0x1044f); /** - * The "Shavian" Unicode Block. + * The "Shavian" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN"); + public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN", 0x10450, 0x1047f); /** - * The "Osmanya" Unicode Block. + * The "Osmanya" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA"); + public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA", 0x10480, 0x104af); /** - * The "Cypriot Syllabary" Unicode Block. + * The "Cypriot Syllabary" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY"); + public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY", 0x10800, 0x1083f); /** - * The "Byzantine Musical Symbols" Unicode Block. + * The "Byzantine Musical Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS"); + public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", 0x1d000, 0x1d0ff); /** - * The "Musical Symbols" Unicode Block. + * The "Musical Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS"); + public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS", 0x1d100, 0x1d1ff); /** - * The "Tai Xuan Jing Symbols" Unicode Block. + * The "Tai Xuan Jing Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS"); + public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", 0x1d300, 0x1d35f); /** - * The "Mathematical Alphanumeric Symbols" Unicode Block. + * The "Mathematical Alphanumeric Symbols" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS"); + public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS", 0x1d400, 0x1d7ff); /** - * The "CJK Unified Ideographs Extension B" Unicode Block. + * The "CJK Unified Ideographs Extension B" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B"); + public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B", 0x20000, 0x2a6df); /** - * The "CJK Compatibility Ideographs Supplement" Unicode Block. + * The "CJK Compatibility Ideographs Supplement" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT"); + public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT", 0x2f800, 0x2fa1f); /** - * The "Tags" Unicode Block. + * The "Tags" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS"); + public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS", 0xe0000, 0xe007f); /** - * The "Variation Selectors Supplement" Unicode Block. + * The "Variation Selectors Supplement" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT"); + public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", 0xe0100, 0xe01ef); /** - * The "Supplementary Private Use Area-A" Unicode Block. + * The "Supplementary Private Use Area-A" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A"); + public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A", 0xf0000, 0xfffff); /** - * The "Supplementary Private Use Area-B" Unicode Block. + * The "Supplementary Private Use Area-B" Unicode Block. * - * @since Android 1.0 + * @since 1.5 */ - public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B"); + public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B", 0x100000, 0x10ffff); /* * All of the UnicodeBlocks with valid ranges in ascending order. */ private static UnicodeBlock[] BLOCKS; + // BEGIN android-changed + // /* + // * A SortedMap (String.CASE_INSENSITIVE_ORDER) with keys that represents + // * valid block names and values of the UnicodeBlock constant they map + // * to. + // */ + // private static final SortedMap<String, UnicodeBlock> BLOCKS_BY_NAME = ...; // END android-changed - + /** * Retrieves the constant that corresponds to the specified block name. * The block names are defined by the Unicode 4.0.1 specification in the * {@code Blocks-4.0.1.txt} file. * <p> * Block names may be one of the following: - * </p> * <ul> * <li>Canonical block name, as defined by the Unicode specification; * case-insensitive.</li> @@ -1424,13 +1387,15 @@ public final class Character implements Serializable, Comparable<Character> { * uppercasing the canonical name and replacing all spaces and hyphens * with underscores.</li> * </ul> - * + * * @param blockName * the name of the block to retrieve. * @return the UnicodeBlock constant corresponding to {@code blockName}. + * @throws NullPointerException + * if {@code blockName} is {@code null}. * @throws IllegalArgumentException * if {@code blockName} is not a valid block name. - * @since Android 1.0 + * @since 1.5 */ public static final UnicodeBlock forName(String blockName) { // BEGIN android-note @@ -1449,7 +1414,7 @@ public final class Character implements Serializable, Comparable<Character> { return SURROGATES_AREA; } else if(blockName.equalsIgnoreCase("greek")) { return GREEK; - } else if(blockName.equals("COMBINING_MARKS_FOR_SYMBOLS") || + } else if(blockName.equals("COMBINING_MARKS_FOR_SYMBOLS") || blockName.equals("Combining Marks for Symbols") || blockName.equals("CombiningMarksforSymbols")) { return COMBINING_MARKS_FOR_SYMBOLS; @@ -1459,27 +1424,26 @@ public final class Character implements Serializable, Comparable<Character> { return BLOCKS[block]; // END android-changed } - + /** * Gets the constant for the Unicode block that contains the specified * character. - * + * * @param c * the character for which to get the {@code UnicodeBlock} * constant. * @return the {@code UnicodeBlock} constant for the block that contains * {@code c}, or {@code null} if {@code c} does not belong to * any defined block. - * @since Android 1.0 */ public static UnicodeBlock of(char c) { return of((int) c); } - + /** * Gets the constant for the Unicode block that contains the specified * Unicode code point. - * + * * @param codePoint * the Unicode code point for which to get the * {@code UnicodeBlock} constant. @@ -1488,7 +1452,7 @@ public final class Character implements Serializable, Comparable<Character> { * not belong to any defined block. * @throws IllegalArgumentException * if {@code codePoint} is not a valid Unicode code point. - * @since Android 1.0 + * @since 1.5 */ public static UnicodeBlock of(int codePoint) { if (!isValidCodePoint(codePoint)) { @@ -1505,9 +1469,9 @@ public final class Character implements Serializable, Comparable<Character> { return BLOCKS[block]; // END android-changed } - + // BEGIN android-changed - private UnicodeBlock(String blockName) { + private UnicodeBlock(String blockName, int start, int end) { super(blockName); } // END android-changed @@ -1516,10 +1480,9 @@ public final class Character implements Serializable, Comparable<Character> { /** * Constructs a new {@code Character} with the specified primitive char * value. - * + * * @param value * the primitive char value to store in the new instance. - * @since Android 1.0 */ public Character(char value) { this.value = value; @@ -1527,9 +1490,8 @@ public final class Character implements Serializable, Comparable<Character> { /** * Gets the primitive value of this character. - * + * * @return this object's primitive value. - * @since Android 1.0 */ public char charValue() { return value; @@ -1538,7 +1500,7 @@ public final class Character implements Serializable, Comparable<Character> { /** * Compares this object to the specified character object to determine their * relative order. - * + * * @param c * the character object to compare this object to. * @return {@code 0} if the value of this character and the value of @@ -1547,22 +1509,22 @@ public final class Character implements Serializable, Comparable<Character> { * value if the value of this character is less than the value of * {@code c}. * @see java.lang.Comparable - * @since Android 1.0 + * @since 1.2 */ public int compareTo(Character c) { return value - c.value; } - + /** * Returns a {@code Character} instance for the {@code char} value passed. * For ASCII/Latin-1 characters (and generally all characters with a Unicode * value up to 512), this method should be used instead of the constructor, * as it maintains a cache of corresponding {@code Character} instances. - * + * * @param c * the char value for which to get a {@code Character} instance. * @return the {@code Character} instance for {@code c}. - * @since Android 1.0 + * @since 1.5 */ public static Character valueOf(char c) { if (c >= CACHE_LEN ) { @@ -1589,12 +1551,12 @@ public final class Character implements Serializable, Comparable<Character> { } /** * Indicates whether {@code codePoint} is a valid Unicode code point. - * + * * @param codePoint * the code point to test. * @return {@code true} if {@code codePoint} is a valid Unicode code point; * {@code false} otherwise. - * @since Android 1.0 + * @since 1.5 */ public static boolean isValidCodePoint(int codePoint) { return (MIN_CODE_POINT <= codePoint && MAX_CODE_POINT >= codePoint); @@ -1603,12 +1565,12 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether {@code codePoint} is within the supplementary code * point range. - * + * * @param codePoint * the code point to test. * @return {@code true} if {@code codePoint} is within the supplementary * code point range; {@code false} otherwise. - * @since Android 1.0 + * @since 1.5 */ public static boolean isSupplementaryCodePoint(int codePoint) { return (MIN_SUPPLEMENTARY_CODE_POINT <= codePoint && MAX_CODE_POINT >= codePoint); @@ -1618,13 +1580,13 @@ public final class Character implements Serializable, Comparable<Character> { * Indicates whether {@code ch} is a high- (or leading-) surrogate code unit * that is used for representing supplementary characters in UTF-16 * encoding. - * + * * @param ch * the character to test. * @return {@code true} if {@code ch} is a high-surrogate code unit; * {@code false} otherwise. * @see #isLowSurrogate(char) - * @since Android 1.0 + * @since 1.5 */ public static boolean isHighSurrogate(char ch) { return (MIN_HIGH_SURROGATE <= ch && MAX_HIGH_SURROGATE >= ch); @@ -1634,21 +1596,21 @@ public final class Character implements Serializable, Comparable<Character> { * Indicates whether {@code ch} is a low- (or trailing-) surrogate code unit * that is used for representing supplementary characters in UTF-16 * encoding. - * + * * @param ch * the character to test. * @return {@code true} if {@code ch} is a low-surrogate code unit; * {@code false} otherwise. * @see #isHighSurrogate(char) - * @since Android 1.0 - */ + * @since 1.5 + */ public static boolean isLowSurrogate(char ch) { return (MIN_LOW_SURROGATE <= ch && MAX_LOW_SURROGATE >= ch); } /** * Indicates whether the specified character pair is a valid surrogate pair. - * + * * @param high * the high surrogate unit to test. * @param low @@ -1658,7 +1620,7 @@ public final class Character implements Serializable, Comparable<Character> { * otherwise. * @see #isHighSurrogate(char) * @see #isLowSurrogate(char) - * @since Android 1.0 + * @since 1.5 */ public static boolean isSurrogatePair(char high, char low) { return (isHighSurrogate(high) && isLowSurrogate(low)); @@ -1670,12 +1632,14 @@ public final class Character implements Serializable, Comparable<Character> { * is greater than or equal to {@code 0x10000}, in which case {@code 2} is * returned, otherwise {@code 1}. To test if the code point is valid, use * the {@link #isValidCodePoint(int)} method. - * + * * @param codePoint * the code point for which to calculate the number of required * chars. * @return {@code 2} if {@code codePoint >= 0x10000}; {@code 1} otherwise. - * @since Android 1.0 + * @see #isValidCodePoint(int) + * @see #isSupplementaryCodePoint(int) + * @since 1.5 */ public static int charCount(int codePoint) { return (codePoint >= 0x10000 ? 2 : 1); @@ -1687,14 +1651,14 @@ public final class Character implements Serializable, Comparable<Character> { * surrogates, then the result is indeterminate. The * {@link #isSurrogatePair(char, char)} method should be used prior to this * method to validate the pair. - * + * * @param high * the high surrogate unit. * @param low * the low surrogate unit. * @return the Unicode code point corresponding to the surrogate unit pair. * @see #isSurrogatePair(char, char) - * @since Android 1.0 + * @since 1.5 */ public static int toCodePoint(char high, char low) { // See RFC 2781, Section 2.2 @@ -1711,7 +1675,7 @@ public final class Character implements Serializable, Comparable<Character> { * {@code index + 1} is a low-surrogate unit, then the supplementary code * point represented by the pair is returned; otherwise the {@code char} * value at {@code index} is returned. - * + * * @param seq * the source sequence of {@code char} units. * @param index @@ -1719,10 +1683,12 @@ public final class Character implements Serializable, Comparable<Character> { * point. * @return the Unicode code point or {@code char} value at {@code index} in * {@code seq}. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if the {@code index} is negative or greater than or equal to * the length of {@code seq}. - * @since Android 1.0 + * @since 1.5 */ public static int codePointAt(CharSequence seq, int index) { if (seq == null) { @@ -1751,7 +1717,7 @@ public final class Character implements Serializable, Comparable<Character> { * {@code index + 1} is a low-surrogate unit, then the supplementary code * point represented by the pair is returned; otherwise the {@code char} * value at {@code index} is returned. - * + * * @param seq * the source array of {@code char} units. * @param index @@ -1759,10 +1725,12 @@ public final class Character implements Serializable, Comparable<Character> { * point. * @return the Unicode code point or {@code char} value at {@code index} in * {@code seq}. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if the {@code index} is negative or greater than or equal to * the length of {@code seq}. - * @since Android 1.0 + * @since 1.5 */ public static int codePointAt(char[] seq, int index) { if (seq == null) { @@ -1792,7 +1760,7 @@ public final class Character implements Serializable, Comparable<Character> { * low-surrogate unit, then the supplementary code point represented by the * pair is returned; otherwise the {@code char} value at {@code index} is * returned. - * + * * @param seq * the source array of {@code char} units. * @param index @@ -1801,16 +1769,18 @@ public final class Character implements Serializable, Comparable<Character> { * the index after the last unit in {@code seq} that can be used. * @return the Unicode code point or {@code char} value at {@code index} in * {@code seq}. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if {@code index < 0}, {@code index >= limit}, * {@code limit < 0} or if {@code limit} is greater than the * length of {@code seq}. - * @since Android 1.0 + * @since 1.5 */ public static int codePointAt(char[] seq, int index, int limit) { if (index < 0 || index >= limit || limit < 0 || limit > seq.length) { throw new IndexOutOfBoundsException(); - } + } char high = seq[index++]; if (index >= limit) { @@ -1830,7 +1800,7 @@ public final class Character implements Serializable, Comparable<Character> { * {@code index - 2} is a high-surrogate unit, then the supplementary code * point represented by the pair is returned; otherwise the {@code char} * value at {@code index - 1} is returned. - * + * * @param seq * the source sequence of {@code char} units. * @param index @@ -1838,10 +1808,12 @@ public final class Character implements Serializable, Comparable<Character> { * point that should be returned. * @return the Unicode code point or {@code char} value before {@code index} * in {@code seq}. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if the {@code index} is less than 1 or greater than the * length of {@code seq}. - * @since Android 1.0 + * @since 1.5 */ public static int codePointBefore(CharSequence seq, int index) { if (seq == null) { @@ -1870,7 +1842,7 @@ public final class Character implements Serializable, Comparable<Character> { * {@code index - 2} is a high-surrogate unit, then the supplementary code * point represented by the pair is returned; otherwise the {@code char} * value at {@code index - 1} is returned. - * + * * @param seq * the source array of {@code char} units. * @param index @@ -1878,10 +1850,12 @@ public final class Character implements Serializable, Comparable<Character> { * point that should be returned. * @return the Unicode code point or {@code char} value before {@code index} * in {@code seq}. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if the {@code index} is less than 1 or greater than the * length of {@code seq}. - * @since Android 1.0 + * @since 1.5 */ public static int codePointBefore(char[] seq, int index) { if (seq == null) { @@ -1911,7 +1885,7 @@ public final class Character implements Serializable, Comparable<Character> { * high-surrogate unit, then the supplementary code point represented by the * pair is returned; otherwise the {@code char} value at {@code index - 1} * is returned. - * + * * @param seq * the source array of {@code char} units. * @param index @@ -1921,12 +1895,14 @@ public final class Character implements Serializable, Comparable<Character> { * the index of the first element in {@code seq}. * @return the Unicode code point or {@code char} value before {@code index} * in {@code seq}. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if the {@code index <= start}, {@code start < 0}, * {@code index} is greater than the length of {@code seq}, or * if {@code start} is equal or greater than the length of * {@code seq}. - * @since Android 1.0 + * @since 1.5 */ public static int codePointBefore(char[] seq, int index, int start) { if (seq == null) { @@ -1952,7 +1928,7 @@ public final class Character implements Serializable, Comparable<Character> { * Converts the specified Unicode code point into a UTF-16 encoded sequence * and copies the value(s) into the char array {@code dst}, starting at * index {@code dstIndex}. - * + * * @param codePoint * the Unicode code point to encode. * @param dst @@ -1962,12 +1938,14 @@ public final class Character implements Serializable, Comparable<Character> { * @return the number of {@code char} value units copied into {@code dst}. * @throws IllegalArgumentException * if {@code codePoint} is not a valid Unicode code point. + * @throws NullPointerException + * if {@code dst} is {@code null}. * @throws IndexOutOfBoundsException * if {@code dstIndex} is negative, greater than or equal to * {@code dst.length} or equals {@code dst.length - 1} when * {@code codePoint} is a * {@link #isSupplementaryCodePoint(int) supplementary code point}. - * @since Android 1.0 + * @since 1.5 */ public static int toChars(int codePoint, char[] dst, int dstIndex) { if (!isValidCodePoint(codePoint)) { @@ -2001,7 +1979,7 @@ public final class Character implements Serializable, Comparable<Character> { /** * Converts the specified Unicode code point into a UTF-16 encoded sequence * and returns it as a char array. - * + * * @param codePoint * the Unicode code point to encode. * @return the UTF-16 encoded char sequence. If {@code codePoint} is a @@ -2010,7 +1988,7 @@ public final class Character implements Serializable, Comparable<Character> { * contains just one character. * @throws IllegalArgumentException * if {@code codePoint} is not a valid Unicode code point. - * @since Android 1.0 + * @since 1.5 */ public static char[] toChars(int codePoint) { if (!isValidCodePoint(codePoint)) { @@ -2031,7 +2009,7 @@ public final class Character implements Serializable, Comparable<Character> { * specified character sequence, as delineated by {@code beginIndex} and * {@code endIndex}. Any surrogate values with missing pair values will be * counted as one code point. - * + * * @param seq * the {@code CharSequence} to look through. * @param beginIndex @@ -2039,10 +2017,12 @@ public final class Character implements Serializable, Comparable<Character> { * @param endIndex * the exclusive index to stop counting at. * @return the number of Unicode code points. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if {@code beginIndex < 0}, {@code beginIndex > endIndex} or * if {@code endIndex} is greater than the length of {@code seq}. - * @since Android 1.0 + * @since 1.5 */ public static int codePointCount(CharSequence seq, int beginIndex, int endIndex) { @@ -2075,7 +2055,7 @@ public final class Character implements Serializable, Comparable<Character> { * specified char array, as delineated by {@code offset} and {@code count}. * Any surrogate values with missing pair values will be counted as one code * point. - * + * * @param seq * the char array to look through * @param offset @@ -2084,11 +2064,13 @@ public final class Character implements Serializable, Comparable<Character> { * the number of {@code char} values to look through in * {@code seq}. * @return the number of Unicode code points. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if {@code offset < 0}, {@code count < 0} or if * {@code offset + count} is greater than the length of * {@code seq}. - * @since Android 1.0 + * @since 1.5 */ public static int codePointCount(char[] seq, int offset, int count) { if (seq == null) { @@ -2119,7 +2101,7 @@ public final class Character implements Serializable, Comparable<Character> { /** * Determines the index in the specified character sequence that is offset * {@code codePointOffset} code points from {@code index}. - * + * * @param seq * the character sequence to find the index in. * @param index @@ -2129,13 +2111,15 @@ public final class Character implements Serializable, Comparable<Character> { * be a negative or positive value. * @return the index in {@code seq} that is {@code codePointOffset} code * points away from {@code index}. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if {@code index < 0}, {@code index} is greater than the * length of {@code seq}, or if there are not enough values in * {@code seq} to skip {@code codePointOffset} code points * forwards or backwards (if {@code codePointOffset} is * negative) from {@code index}. - * @since Android 1.0 + * @since 1.5 */ public static int offsetByCodePoints(CharSequence seq, int index, int codePointOffset) { @@ -2193,7 +2177,7 @@ public final class Character implements Serializable, Comparable<Character> { * Determines the index in a subsequence of the specified character array * that is offset {@code codePointOffset} code points from {@code index}. * The subsequence is delineated by {@code start} and {@code count}. - * + * * @param seq * the character array to find the index in. * @param start @@ -2209,6 +2193,8 @@ public final class Character implements Serializable, Comparable<Character> { * be a negative or positive value. * @return the index in {@code seq} that is {@code codePointOffset} code * points away from {@code index}. + * @throws NullPointerException + * if {@code seq} is {@code null}. * @throws IndexOutOfBoundsException * if {@code start < 0}, {@code count < 0}, * {@code index < start}, {@code index > start + count}, @@ -2217,7 +2203,7 @@ public final class Character implements Serializable, Comparable<Character> { * {@code seq} to skip {@code codePointOffset} code points * forward or backward (if {@code codePointOffset} is * negative) from {@code index}. - * @since Android 1.0 + * @since 1.5 */ public static int offsetByCodePoints(char[] seq, int start, int count, int index, int codePointOffset) { @@ -2276,14 +2262,13 @@ public final class Character implements Serializable, Comparable<Character> { * Convenience method to determine the value of the specified character * {@code c} in the supplied radix. The value of {@code radix} must be * between MIN_RADIX and MAX_RADIX. - * + * * @param c * the character to determine the value of. * @param radix * the radix. * @return the value of {@code c} in {@code radix} if {@code radix} lies * between {@link #MIN_RADIX} and {@link #MAX_RADIX}; -1 otherwise. - * @since Android 1.0 */ public static int digit(char c, int radix) { // BEGIN android-changed @@ -2313,12 +2298,12 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.digit(c, radix); // ENd android-changed } - + /** * Convenience method to determine the value of the character * {@code codePoint} in the supplied radix. The value of {@code radix} must * be between MIN_RADIX and MAX_RADIX. - * + * * @param codePoint * the character, including supplementary characters. * @param radix @@ -2326,7 +2311,6 @@ public final class Character implements Serializable, Comparable<Character> { * @return if {@code radix} lies between {@link #MIN_RADIX} and * {@link #MAX_RADIX} then the value of the character in the radix; * -1 otherwise. - * @since Android 1.0 */ public static int digit(int codePoint, int radix) { return UCharacter.digit(codePoint, radix); @@ -2336,12 +2320,11 @@ public final class Character implements Serializable, Comparable<Character> { * Compares this object with the specified object and indicates if they are * equal. In order to be equal, {@code object} must be an instance of * {@code Character} and have the same char value as this object. - * + * * @param object * the object to compare this double with. * @return {@code true} if the specified object is equal to this * {@code Character}; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -2355,14 +2338,13 @@ public final class Character implements Serializable, Comparable<Character> { * {@code MAX_RADIX} inclusive; {@code digit} must not be negative and * smaller than {@code radix}. If any of these conditions does not hold, 0 * is returned. - * + * * @param digit * the integer value. * @param radix * the radix. * @return the character which represents the {@code digit} in the * {@code radix}. - * @since Android 1.0 */ public static char forDigit(int digit, int radix) { if (MIN_RADIX <= radix && radix <= MAX_RADIX) { @@ -2375,13 +2357,12 @@ public final class Character implements Serializable, Comparable<Character> { /** * Gets the numeric value of the specified Unicode character. - * + * * @param c * the Unicode character to get the numeric value of. * @return a non-negative numeric integer value if a numeric value for * {@code c} exists, -1 if there is no numeric value for {@code c}, * -2 if the numeric value can not be represented with an integer. - * @since Android 1.0 */ public static int getNumericValue(char c) { // BEGIN android-changed @@ -2414,19 +2395,18 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.getNumericValue(c); // END android-changed } - + /** * Gets the numeric value of the specified Unicode code point. For example, * the code point '\u216B' stands for the Roman number XII, which has the * numeric value 12. - * + * * @param codePoint * the Unicode code point to get the numeric value of. * @return a non-negative numeric integer value if a numeric value for * {@code codePoint} exists, -1 if there is no numeric value for * {@code codePoint}, -2 if the numeric value can not be * represented with an integer. - * @since Android 1.0 */ public static int getNumericValue(int codePoint) { return UCharacter.getNumericValue(codePoint); @@ -2434,14 +2414,16 @@ public final class Character implements Serializable, Comparable<Character> { /** * Gets the general Unicode category of the specified character. - * + * * @param c * the character to get the category of. * @return the Unicode category of {@code c}. - * @since Android 1.0 */ public static int getType(char c) { // BEGIN android-changed + // if(c < 1000) { + // return typeValuesCache[(int)c]; + // } // int result = BinarySearch.binarySearchRange(typeKeys, c); // int high = typeValues[result * 2]; // if (c <= high) { @@ -2452,19 +2434,23 @@ public final class Character implements Serializable, Comparable<Character> { // return (c & 1) == 1 ? code >> 8 : code & 0xff; // } // return UNASSIGNED; - return getType((int)c); + return getType((int) c); // END android-changed } - + /** * Gets the general Unicode category of the specified code point. - * + * * @param codePoint * the Unicode code point to get the category of. * @return the Unicode category of {@code codePoint}. - * @since Android 1.0 */ public static int getType(int codePoint) { + // BEGIN android-changed + // if (codePoint < 1000 && codePoint > 0) { + // return typeValuesCache[codePoint]; + // } + // END android-changed int type = UCharacter.getType(codePoint); // the type values returned by UCharacter are not compatible with what @@ -2477,11 +2463,10 @@ public final class Character implements Serializable, Comparable<Character> { /** * Gets the Unicode directionality of the specified character. - * + * * @param c * the character to get the directionality of. * @return the Unicode directionality of {@code c}. - * @since Android 1.0 */ public static byte getDirectionality(char c) { // BEGIN android-changed @@ -2498,21 +2483,20 @@ public final class Character implements Serializable, Comparable<Character> { return getDirectionality((int)c); // END android-changed } - + /** * Gets the Unicode directionality of the specified character. - * + * * @param codePoint * the Unicode code point to get the directionality of. * @return the Unicode directionality of {@code codePoint}. - * @since Android 1.0 */ public static byte getDirectionality(int codePoint) { if (getType(codePoint) == Character.UNASSIGNED) { return Character.DIRECTIONALITY_UNDEFINED; } - - byte UCDirectionality = UCharacter.getDirectionality(codePoint); + + byte UCDirectionality = UCharacter.getDirectionality(codePoint); if (UCDirectionality == -1) { return -1; } @@ -2521,12 +2505,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is mirrored. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is mirrored; {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isMirrored(char c) { // BEGIN android-changed @@ -2539,15 +2522,14 @@ public final class Character implements Serializable, Comparable<Character> { return isMirrored((int)c); // ENd android-changed } - + /** * Indicates whether the specified code point is mirrored. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is mirrored, {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isMirrored(int codePoint) { return UCharacter.isMirrored(codePoint); @@ -2561,12 +2543,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is defined in the Unicode * specification. - * + * * @param c * the character to check. * @return {@code true} if the general Unicode category of the character is * not {@code UNASSIGNED}; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isDefined(char c) { // BEGIN android-changed @@ -2574,16 +2555,15 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isDefined(c); // END android-changed } - + /** * Indicates whether the specified code point is defined in the Unicode * specification. - * + * * @param codePoint * the code point to check. * @return {@code true} if the general Unicode category of the code point is * not {@code UNASSIGNED}; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isDefined(int codePoint) { return UCharacter.isDefined(codePoint); @@ -2591,12 +2571,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a digit. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a digit; {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isDigit(char c) { // BEGIN android-changed @@ -2611,15 +2590,14 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isDigit(c); // END android-changed } - + /** * Indicates whether the specified code point is a digit. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a digit; {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isDigit(int codePoint) { return UCharacter.isDigit(codePoint); @@ -2628,11 +2606,10 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is ignorable in a Java or * Unicode identifier. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is ignorable; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isIdentifierIgnorable(char c) { // BEGIN android-changed @@ -2641,16 +2618,15 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isIdentifierIgnorable(c); // END android-changed } - + /** * Indicates whether the specified code point is ignorable in a Java or * Unicode identifier. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is ignorable; {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isIdentifierIgnorable(int codePoint) { return UCharacter.isIdentifierIgnorable(codePoint); @@ -2658,12 +2634,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is an ISO control character. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is an ISO control character; * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isISOControl(char c) { return isISOControl((int)c); @@ -2671,12 +2646,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified code point is an ISO control character. - * + * * @param c * the code point to check. * @return {@code true} if {@code c} is an ISO control character; * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isISOControl(int c) { return (c >= 0 && c <= 0x1f) || (c >= 0x7f && c <= 0x9f); @@ -2685,12 +2659,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a valid part of a Java * identifier other than the first character. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is valid as part of a Java identifier; * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isJavaIdentifierPart(char c) { // Optimized case for ASCII @@ -2709,31 +2682,29 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified code point is a valid part of a Java * identifier other than the first character. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code c} is valid as part of a Java identifier; * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isJavaIdentifierPart(int codePoint) { int type = getType(codePoint); return (type >= UPPERCASE_LETTER && type <= OTHER_LETTER) || type == CURRENCY_SYMBOL || type == CONNECTOR_PUNCTUATION || (type >= DECIMAL_DIGIT_NUMBER && type <= LETTER_NUMBER) - || type == COMBINING_SPACING_MARK || type == NON_SPACING_MARK + || type == COMBINING_SPACING_MARK || type == NON_SPACING_MARK || isIdentifierIgnorable(codePoint); } /** * Indicates whether the specified character is a valid first character for * a Java identifier. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a valid first character of a Java * identifier; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isJavaIdentifierStart(char c) { // Optimized case for ASCII @@ -2746,16 +2717,15 @@ public final class Character implements Serializable, Comparable<Character> { || type == CURRENCY_SYMBOL || type == CONNECTOR_PUNCTUATION || type == LETTER_NUMBER; } - + /** * Indicates whether the specified code point is a valid start for a Java * identifier. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a valid start of a Java * identifier; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isJavaIdentifierStart(int codePoint) { int type = getType(codePoint); @@ -2765,13 +2735,12 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a Java letter. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a Java letter; {@code false} * otherwise. * @deprecated Use {@link #isJavaIdentifierStart(char)} - * @since Android 1.0 */ @Deprecated public static boolean isJavaLetter(char c) { @@ -2781,13 +2750,12 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a Java letter or digit * character. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a Java letter or digit; * {@code false} otherwise. * @deprecated Use {@link #isJavaIdentifierPart(char)} - * @since Android 1.0 */ @Deprecated public static boolean isJavaLetterOrDigit(char c) { @@ -2796,11 +2764,10 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a letter. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a letter; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isLetter(char c) { // BEGIN android-changed @@ -2815,15 +2782,14 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isLetter(c); // END android-changed } - + /** * Indicates whether the specified code point is a letter. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a letter; {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isLetter(int codePoint) { return UCharacter.isLetter(codePoint); @@ -2831,12 +2797,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a letter or a digit. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a letter or a digit; {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isLetterOrDigit(char c) { // BEGIN android-changed @@ -2846,15 +2811,14 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isLetterOrDigit(c); // END andorid-changed } - + /** * Indicates whether the specified code point is a letter or a digit. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a letter or a digit; * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isLetterOrDigit(int codePoint) { return UCharacter.isLetterOrDigit(codePoint); @@ -2862,12 +2826,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a lower case letter. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a lower case letter; {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isLowerCase(char c) { // BEGIN android-changed @@ -2878,20 +2841,19 @@ public final class Character implements Serializable, Comparable<Character> { // if (c < 128) { // return false; // } - // + // // return getType(c) == LOWERCASE_LETTER; return UCharacter.isLowerCase(c); // END android-changed } - + /** * Indicates whether the specified code point is a lower case letter. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a lower case letter; * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isLowerCase(int codePoint) { return UCharacter.isLowerCase(codePoint); @@ -2899,13 +2861,12 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a Java space. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a Java space; {@code false} * otherwise. * @deprecated Use {@link #isWhitespace(char)} - * @since Android 1.0 */ @Deprecated public static boolean isSpace(char c) { @@ -2916,12 +2877,11 @@ public final class Character implements Serializable, Comparable<Character> { * Indicates whether the specified character is a Unicode space character. * That is, if it is a member of one of the Unicode categories Space * Separator, Line Separator, or Paragraph Separator. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a Unicode space character, * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isSpaceChar(char c) { // BEGIN android-changed @@ -2936,17 +2896,16 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isSpaceChar(c); // END android-changed } - + /** * Indicates whether the specified code point is a Unicode space character. * That is, if it is a member of one of the Unicode categories Space * Separator, Line Separator, or Paragraph Separator. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a Unicode space character, * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isSpaceChar(int codePoint) { return UCharacter.isSpaceChar(codePoint); @@ -2954,12 +2913,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a titlecase character. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a titlecase character, {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isTitleCase(char c) { // BEGIN android-changed @@ -2978,15 +2936,14 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isTitleCase(c); // END android-changed } - + /** * Indicates whether the specified code point is a titlecase character. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a titlecase character, * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isTitleCase(int codePoint) { return UCharacter.isTitleCase(codePoint); @@ -2995,12 +2952,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is valid as part of a Unicode * identifier other than the first character. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is valid as part of a Unicode * identifier; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isUnicodeIdentifierPart(char c) { // BEGIN android-changed @@ -3013,16 +2969,15 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isUnicodeIdentifierPart(c); // END android-changed } - + /** * Indicates whether the specified code point is valid as part of a Unicode * identifier other than the first character. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is valid as part of a Unicode * identifier; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isUnicodeIdentifierPart(int codePoint) { return UCharacter.isUnicodeIdentifierPart(codePoint); @@ -3031,12 +2986,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a valid initial character * for a Unicode identifier. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a valid first character for a * Unicode identifier; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isUnicodeIdentifierStart(char c) { // BEGIN android-changed @@ -3046,16 +3000,15 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isUnicodeIdentifierStart(c); // END android-changed } - + /** * Indicates whether the specified code point is a valid initial character * for a Unicode identifier. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a valid first character for * a Unicode identifier; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isUnicodeIdentifierStart(int codePoint) { return UCharacter.isUnicodeIdentifierStart(codePoint); @@ -3063,12 +3016,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is an upper case letter. - * + * * @param c * the character to check. * @return {@code true} if {@code c} is a upper case letter; {@code false} * otherwise. - * @since Android 1.0 */ public static boolean isUpperCase(char c) { // BEGIN android-changed @@ -3079,20 +3031,19 @@ public final class Character implements Serializable, Comparable<Character> { // if (c < 128) { // return false; // } - // + // // return getType(c) == UPPERCASE_LETTER; return UCharacter.isUpperCase(c); // END android-changed } - + /** * Indicates whether the specified code point is an upper case letter. - * + * * @param codePoint * the code point to check. * @return {@code true} if {@code codePoint} is a upper case letter; * {@code false} otherwise. - * @since Android 1.0 */ public static boolean isUpperCase(int codePoint) { return UCharacter.isUpperCase(codePoint); @@ -3101,12 +3052,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Indicates whether the specified character is a whitespace character in * Java. - * + * * @param c * the character to check. * @return {@code true} if the supplied {@code c} is a whitespace character * in Java; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isWhitespace(char c) { // BEGIN android-changed @@ -3124,30 +3074,29 @@ public final class Character implements Serializable, Comparable<Character> { return UCharacter.isWhitespace(c); // END android-changed } - + /** * Indicates whether the specified code point is a whitespace character in * Java. - * + * * @param codePoint * the code point to check. * @return {@code true} if the supplied {@code c} is a whitespace character * in Java; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isWhitespace(int codePoint) { //FIXME depends on ICU when the codePoint is '\u2007' return UCharacter.isWhitespace(codePoint); + } /** * Reverses the order of the first and second byte in the specified * character. - * + * * @param c * the character to reverse. * @return the character with reordered bytes. - * @since Android 1.0 */ public static char reverseBytes(char c) { return (char)((c<<8) | (c>>8)); @@ -3157,12 +3106,11 @@ public final class Character implements Serializable, Comparable<Character> { * Returns the lower case equivalent for the specified character if the * character is an upper case letter. Otherwise, the specified character is * returned unchanged. - * + * * @param c * the character * @return if {@code c} is an upper case character then its lower case * counterpart, otherwise just {@code c}. - * @since Android 1.0 */ public static char toLowerCase(char c) { // BEGIN android-changed @@ -3170,10 +3118,13 @@ public final class Character implements Serializable, Comparable<Character> { // if ('A' <= c && c <= 'Z') { // return (char) (c + ('a' - 'A')); // } - // if (c < 128) { + // if (c < 192) {// || c == 215 || (c > 222 && c < 256)) { // return c; // } - // + // if (c<1000) { + // return (char)lowercaseValuesCache[c-192]; + // } + // // int result = BinarySearch.binarySearchRange(lowercaseKeys, c); // if (result >= 0) { // boolean by2 = false; @@ -3195,17 +3146,16 @@ public final class Character implements Serializable, Comparable<Character> { return (char)UCharacter.toLowerCase(c); // END android-changed } - + /** * Returns the lower case equivalent for the specified code point if it is * an upper case letter. Otherwise, the specified code point is returned * unchanged. - * + * * @param codePoint * the code point to check. * @return if {@code codePoint} is an upper case character then its lower * case counterpart, otherwise just {@code codePoint}. - * @since Android 1.0 */ public static int toLowerCase(int codePoint) { return UCharacter.toLowerCase(codePoint); @@ -3218,11 +3168,10 @@ public final class Character implements Serializable, Comparable<Character> { /** * Converts the specified character to its string representation. - * + * * @param value * the character to convert. * @return the character converted to a string. - * @since Android 1.0 */ public static String toString(char value) { return String.valueOf(value); @@ -3231,12 +3180,11 @@ public final class Character implements Serializable, Comparable<Character> { /** * Returns the title case equivalent for the specified character if it * exists. Otherwise, the specified character is returned unchanged. - * + * * @param c * the character to convert. * @return the title case equivalent of {@code c} if it exists, otherwise * {@code c}. - * @since Android 1.0 */ public static char toTitleCase(char c) { // BEGIN android-changed @@ -3251,16 +3199,15 @@ public final class Character implements Serializable, Comparable<Character> { return (char)UCharacter.toTitleCase(c); // ENd android-changed } - + /** * Returns the title case equivalent for the specified code point if it * exists. Otherwise, the specified code point is returned unchanged. - * + * * @param codePoint * the code point to convert. * @return the title case equivalent of {@code codePoint} if it exists, * otherwise {@code codePoint}. - * @since Android 1.0 */ public static int toTitleCase(int codePoint) { return UCharacter.toTitleCase(codePoint); @@ -3270,12 +3217,11 @@ public final class Character implements Serializable, Comparable<Character> { * Returns the upper case equivalent for the specified character if the * character is a lower case letter. Otherwise, the specified character is * returned unchanged. - * + * * @param c * the character to convert. * @return if {@code c} is a lower case character then its upper case * counterpart, otherwise just {@code c}. - * @since Android 1.0 */ public static char toUpperCase(char c) { // BEGIN android-changed @@ -3283,10 +3229,12 @@ public final class Character implements Serializable, Comparable<Character> { // if ('a' <= c && c <= 'z') { // return (char) (c - ('a' - 'A')); // } - // if (c < 128) { + // if (c < 181) { // return c; // } - // + // if (c<1000) { + // return (char)uppercaseValuesCache[(int)c-181]; + // } // int result = BinarySearch.binarySearchRange(uppercaseKeys, c); // if (result >= 0) { // boolean by2 = false; @@ -3308,17 +3256,16 @@ public final class Character implements Serializable, Comparable<Character> { return (char)UCharacter.toUpperCase(c); // END android-changed } - + /** * Returns the upper case equivalent for the specified code point if the * code point is a lower case letter. Otherwise, the specified code point is * returned unchanged. - * + * * @param codePoint * the code point to convert. * @return if {@code codePoint} is a lower case character then its upper * case counterpart, otherwise just {@code codePoint}. - * @since Android 1.0 */ public static int toUpperCase(int codePoint) { return UCharacter.toUpperCase(codePoint); diff --git a/luni/src/main/java/java/lang/ClassCastException.java b/luni/src/main/java/java/lang/ClassCastException.java index 1482b21..b33efcf 100644 --- a/luni/src/main/java/java/lang/ClassCastException.java +++ b/luni/src/main/java/java/lang/ClassCastException.java @@ -22,8 +22,6 @@ import org.apache.harmony.luni.util.Msg; /** * Thrown when a program attempts to cast a an object to a type with which it is * not compatible. - * - * @since Android 1.0 */ public class ClassCastException extends RuntimeException { private static final long serialVersionUID = -9223365651070458532L; @@ -31,8 +29,6 @@ public class ClassCastException extends RuntimeException { /** * Constructs a new {@code ClassCastException} that includes the current * stack trace. - * - * @since Android 1.0 */ public ClassCastException() { super(); @@ -41,10 +37,9 @@ public class ClassCastException extends RuntimeException { /** * Constructs a new {@code ClassCastException} with the current stack trace * and the specified detail message. - * + * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public ClassCastException(String detailMessage) { super(detailMessage); @@ -53,12 +48,11 @@ public class ClassCastException extends RuntimeException { /** * Constructs a new {@code ClassCastException} with the current stack trace * and a detail message based on the source and target class. - * + * * @param instanceClass * the class being cast from. * @param castClass * the class being cast to. - * @since Android 1.0 */ ClassCastException(Class<?> instanceClass, Class<?> castClass) { super(Msg.getString("K0340", instanceClass.getName(), castClass //$NON-NLS-1$ diff --git a/luni/src/main/java/java/lang/ClassCircularityError.java b/luni/src/main/java/java/lang/ClassCircularityError.java index 6dd1c8e..07bf339 100644 --- a/luni/src/main/java/java/lang/ClassCircularityError.java +++ b/luni/src/main/java/java/lang/ClassCircularityError.java @@ -24,9 +24,6 @@ package java.lang; * <p> * Note that this error can only occur when inconsistent class files are loaded, * since it would normally be detected at compile time. - * </p> - * - * @since Android 1.0 */ public class ClassCircularityError extends LinkageError { @@ -35,8 +32,6 @@ public class ClassCircularityError extends LinkageError { /** * Constructs a new {@code ClassCircularityError} that include the current * stack trace. - * - * @since Android 1.0 */ public ClassCircularityError() { super(); @@ -45,10 +40,9 @@ public class ClassCircularityError extends LinkageError { /** * Constructs a new {@code ClassCircularityError} with the current stack * trace and the specified detail message. - * + * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public ClassCircularityError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/ClassFormatError.java b/luni/src/main/java/java/lang/ClassFormatError.java index 282ed70..009f44a 100644 --- a/luni/src/main/java/java/lang/ClassFormatError.java +++ b/luni/src/main/java/java/lang/ClassFormatError.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown by a class loader when a class file has an illegal format or if the * data that it contains can not be interpreted as a class. - * - * @since Android 1.0 */ public class ClassFormatError extends LinkageError { @@ -30,8 +28,6 @@ public class ClassFormatError extends LinkageError { /** * Constructs a new {@code ClassFormatError} that includes the current stack * trace. - * - * @since Android 1.0 */ public ClassFormatError() { super(); @@ -40,10 +36,9 @@ public class ClassFormatError extends LinkageError { /** * Constructs a new {@code ClassFormatError} with the current stack trace * and the specified detail message. - * + * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public ClassFormatError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/ClassNotFoundException.java b/luni/src/main/java/java/lang/ClassNotFoundException.java index 26bdbf7..2ac3b49 100644 --- a/luni/src/main/java/java/lang/ClassNotFoundException.java +++ b/luni/src/main/java/java/lang/ClassNotFoundException.java @@ -19,8 +19,6 @@ package java.lang; /** * Thrown when a class loader is unable to find a class. - * - * @since Android 1.0 */ public class ClassNotFoundException extends Exception { @@ -31,8 +29,6 @@ public class ClassNotFoundException extends Exception { /** * Constructs a new {@code ClassNotFoundException} that includes the current * stack trace. - * - * @since Android 1.0 */ public ClassNotFoundException() { super((Throwable) null); @@ -41,10 +37,9 @@ public class ClassNotFoundException extends Exception { /** * Constructs a new {@code ClassNotFoundException} with the current stack * trace and the specified detail message. - * + * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public ClassNotFoundException(String detailMessage) { super(detailMessage, null); @@ -54,12 +49,11 @@ public class ClassNotFoundException extends Exception { * Constructs a new {@code ClassNotFoundException} with the current stack * trace, the specified detail message and the exception that occurred when * loading the class. - * + * * @param detailMessage * the detail message for this exception. * @param exception * the exception which occurred while loading the class. - * @since Android 1.0 */ public ClassNotFoundException(String detailMessage, Throwable exception) { super(detailMessage); @@ -68,7 +62,7 @@ public class ClassNotFoundException extends Exception { /** * Returns the exception which occurred when loading the class. - * + * * @return Throwable the exception which occurred while loading the class. */ public Throwable getException() { @@ -78,7 +72,7 @@ public class ClassNotFoundException extends Exception { /** * Returns the cause of this Throwable, or {@code null} if there is no * cause. - * + * * @return Throwable the receiver's cause. */ @Override diff --git a/luni/src/main/java/java/lang/CloneNotSupportedException.java b/luni/src/main/java/java/lang/CloneNotSupportedException.java index b484e08..2f4f11c 100644 --- a/luni/src/main/java/java/lang/CloneNotSupportedException.java +++ b/luni/src/main/java/java/lang/CloneNotSupportedException.java @@ -20,9 +20,8 @@ package java.lang; /** * Thrown when a program attempts to clone an object which does not support the * {@link Cloneable} interface. - * + * * @see Cloneable - * @since Android 1.0 */ public class CloneNotSupportedException extends Exception { @@ -31,8 +30,6 @@ public class CloneNotSupportedException extends Exception { /** * Constructs a new {@code CloneNotSupportedException} that includes the * current stack trace. - * - * @since Android 1.0 */ public CloneNotSupportedException() { super(); @@ -41,10 +38,9 @@ public class CloneNotSupportedException extends Exception { /** * Constructs a new {@code CloneNotSupportedException} with the current * stack trace and the specified detail message. - * + * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public CloneNotSupportedException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/Comparable.java b/luni/src/main/java/java/lang/Comparable.java index c50f112..df10416 100644 --- a/luni/src/main/java/java/lang/Comparable.java +++ b/luni/src/main/java/java/lang/Comparable.java @@ -28,21 +28,17 @@ package java.lang; * invertible (the sign of the result of x.compareTo(y) must be equal to the * negation of the sign of the result of y.compareTo(x) for all combinations of * x and y). - * </p> * <p> * In addition, it is recommended (but not required) that if and only if the * result of x.compareTo(y) is zero, then the result of x.equals(y) should be * {@code true}. - * </p> - * - * @since Android 1.0 */ public interface Comparable<T> { - + /** * Compares this object to the specified object to determine their relative * order. - * + * * @param another * the object to compare to this instance. * @return a negative integer if this instance is less than {@code another}; @@ -52,7 +48,6 @@ public interface Comparable<T> { * @throws ClassCastException * if {@code another} cannot be converted into something * comparable to {@code this} instance. - * @since Android 1.0 */ int compareTo(T another); } diff --git a/luni/src/main/java/java/lang/Deprecated.java b/luni/src/main/java/java/lang/Deprecated.java index eb356c2..047a6be 100644 --- a/luni/src/main/java/java/lang/Deprecated.java +++ b/luni/src/main/java/java/lang/Deprecated.java @@ -1,11 +1,11 @@ -/* - * Copyright (C) 2007 The Android Open Source Project +/* 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 * - * Licensed 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 + * 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, @@ -18,17 +18,16 @@ package java.lang; import java.lang.annotation.Documented; import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Annotation type used to mark program elements that should no longer be used * by programmers. Compilers produce a warning if a deprecated program element * is used. - * - * @since Android 1.0 + * + * @since 1.5 */ @Documented -@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME) -public @interface Deprecated -{ - +@Retention(RetentionPolicy.RUNTIME) +public @interface Deprecated { } diff --git a/luni/src/main/java/java/lang/Double.java b/luni/src/main/java/java/lang/Double.java index c50b27d..bc0c380 100644 --- a/luni/src/main/java/java/lang/Double.java +++ b/luni/src/main/java/java/lang/Double.java @@ -19,9 +19,9 @@ package java.lang; /** * The wrapper for the primitive type {@code double}. - * + * * @see java.lang.Number - * @since Android 1.0 + * @since 1.0 */ public final class Double extends Number implements Comparable<Double> { @@ -35,15 +35,11 @@ public final class Double extends Number implements Comparable<Double> { /** * Constant for the maximum {@code double} value, (2 - 2<sup>-52</sup>) * * 2<sup>1023</sup>. - * - * @since Android 1.0 */ public static final double MAX_VALUE = 1.79769313486231570e+308; /** * Constant for the minimum {@code double} value, 2<sup>-1074</sup>. - * - * @since Android 1.0 */ public static final double MIN_VALUE = 5e-324; @@ -51,30 +47,24 @@ public final class Double extends Number implements Comparable<Double> { /** * Constant for the Not-a-Number (NaN) value of the {@code double} type. - * - * @since Android 1.0 */ public static final double NaN = 0.0 / 0.0; /** * Constant for the Positive Infinity value of the {@code double} type. - * - * @since Android 1.0 */ public static final double POSITIVE_INFINITY = 1.0 / 0.0; /** * Constant for the Negative Infinity value of the {@code double} type. - * - * @since Android 1.0 */ public static final double NEGATIVE_INFINITY = -1.0 / 0.0; /** * The {@link Class} object that represents the primitive type {@code * double}. - * - * @since Android 1.0 + * + * @since 1.1 */ @SuppressWarnings("unchecked") public static final Class<Double> TYPE = (Class<Double>) new double[0] @@ -86,18 +76,17 @@ public final class Double extends Number implements Comparable<Double> { /** * Constant for the number of bits needed to represent a {@code double} in * two's complement form. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int SIZE = 64; /** * Constructs a new {@code Double} with the specified primitive double * value. - * + * * @param value * the primitive double value to store in the new instance. - * @since Android 1.0 */ public Double(double value) { this.value = value; @@ -105,13 +94,12 @@ public final class Double extends Number implements Comparable<Double> { /** * Constructs a new {@code Double} from the specified string. - * + * * @param string * the string representation of a double value. * @throws NumberFormatException * if {@code string} can not be decoded into a double value. * @see #parseDouble(String) - * @since Android 1.0 */ public Double(String string) throws NumberFormatException { this(parseDouble(string)); @@ -125,36 +113,20 @@ public final class Double extends Number implements Comparable<Double> { * than any other double value, including {@code Double.POSITIVE_INFINITY};</li> * <li>+0.0d is greater than -0.0d</li> * </ul> - * + * * @param object * the double object to compare this object to. * @return a negative value if the value of this double is less than the * value of {@code object}; 0 if the value of this double and the * value of {@code object} are equal; a positive value if the value * of this double is greater than the value of {@code object}. + * @throws NullPointerException + * if {@code object} is {@code null}. * @see java.lang.Comparable - * @since Android 1.0 + * @since 1.2 */ public int compareTo(Double object) { - long d1, d2; - long NaNbits = Double.doubleToLongBits(Double.NaN); - if ((d1 = Double.doubleToLongBits(value)) == NaNbits) { - if (Double.doubleToLongBits(object.value) == NaNbits) { - return 0; - } - return 1; - } - if ((d2 = Double.doubleToLongBits(object.value)) == NaNbits) { - return -1; - } - if (value == object.value) { - if (d1 == d2) { - return 0; - } - // check for -0 - return d1 > d2 ? 1 : -1; - } - return value > object.value ? 1 : -1; + return compare(value, object.value); } @Override @@ -167,14 +139,13 @@ public final class Double extends Number implements Comparable<Double> { * to the IEEE 754 floating-point double precision bit layout. All * <em>Not-a-Number (NaN)</em> values are converted to a single NaN * representation ({@code 0x7ff8000000000000L}). - * + * * @param value * the double value to convert. * @return the IEEE 754 floating-point double precision representation of * {@code value}. * @see #doubleToRawLongBits(double) * @see #longBitsToDouble(long) - * @since Android 1.0 */ public static native long doubleToLongBits(double value); @@ -182,22 +153,20 @@ public final class Double extends Number implements Comparable<Double> { * Converts the specified double value to a binary representation conforming * to the IEEE 754 floating-point double precision bit layout. * <em>Not-a-Number (NaN)</em> values are preserved. - * + * * @param value * the double value to convert. * @return the IEEE 754 floating-point double precision representation of * {@code value}. * @see #doubleToLongBits(double) * @see #longBitsToDouble(long) - * @since Android 1.0 */ public static native long doubleToRawLongBits(double value); /** * Gets the primitive value of this double. - * + * * @return this object's primitive value. - * @since Android 1.0 */ @Override public double doubleValue() { @@ -209,12 +178,11 @@ public final class Double extends Number implements Comparable<Double> { * equal. In order to be equal, {@code object} must be an instance of * {@code Double} and the bit pattern of its double value is the same as * this object's. - * + * * @param object * the object to compare this double with. * @return {@code true} if the specified object is equal to this * {@code Double}; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -241,10 +209,9 @@ public final class Double extends Number implements Comparable<Double> { /** * Indicates whether this object represents an infinite value. - * + * * @return {@code true} if the value of this double is positive or negative * infinity; {@code false} otherwise. - * @since Android 1.0 */ public boolean isInfinite() { return isInfinite(value); @@ -252,12 +219,11 @@ public final class Double extends Number implements Comparable<Double> { /** * Indicates whether the specified double represents an infinite value. - * + * * @param d * the double to check. * @return {@code true} if the value of {@code d} is positive or negative * infinity; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isInfinite(double d) { return (d == POSITIVE_INFINITY) || (d == NEGATIVE_INFINITY); @@ -265,10 +231,9 @@ public final class Double extends Number implements Comparable<Double> { /** * Indicates whether this object is a <em>Not-a-Number (NaN)</em> value. - * + * * @return {@code true} if this double is <em>Not-a-Number</em>; * {@code false} if it is a (potentially infinite) double number. - * @since Android 1.0 */ public boolean isNaN() { return isNaN(value); @@ -277,12 +242,11 @@ public final class Double extends Number implements Comparable<Double> { /** * Indicates whether the specified double is a <em>Not-a-Number (NaN)</em> * value. - * + * * @param d * the double value to check. * @return {@code true} if {@code d} is <em>Not-a-Number</em>; * {@code false} if it is a (potentially infinite) double number. - * @since Android 1.0 */ public static boolean isNaN(double d) { return d != d; @@ -291,14 +255,13 @@ public final class Double extends Number implements Comparable<Double> { /** * Converts the specified IEEE 754 floating-point double precision bit * pattern to a Java double value. - * + * * @param bits * the IEEE 754 floating-point double precision representation of * a double value. * @return the double value converted from {@code bits}. * @see #doubleToLongBits(double) * @see #doubleToRawLongBits(double) - * @since Android 1.0 */ public static native double longBitsToDouble(long bits); @@ -309,14 +272,13 @@ public final class Double extends Number implements Comparable<Double> { /** * Parses the specified string as a double value. - * + * * @param string * the string representation of a double value. * @return the primitive double value represented by {@code string}. * @throws NumberFormatException * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a double value. - * @since Android 1.0 */ public static double parseDouble(String string) throws NumberFormatException { @@ -337,11 +299,10 @@ public final class Double extends Number implements Comparable<Double> { /** * Returns a string containing a concise, human-readable description of the * specified double value. - * + * * @param d * the double to convert to a string. * @return a printable representation of {@code d}. - * @since Android 1.0 */ public static String toString(double d) { return org.apache.harmony.luni.util.NumberConverter.convert(d); @@ -349,7 +310,7 @@ public final class Double extends Number implements Comparable<Double> { /** * Parses the specified string as a double value. - * + * * @param string * the string representation of a double value. * @return a {@code Double} instance containing the double value represented @@ -358,7 +319,6 @@ public final class Double extends Number implements Comparable<Double> { * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a double value. * @see #parseDouble(String) - * @since Android 1.0 */ public static Double valueOf(String string) throws NumberFormatException { return new Double(parseDouble(string)); @@ -371,7 +331,7 @@ public final class Double extends Number implements Comparable<Double> { * than any other double value, including {@code Double.POSITIVE_INFINITY};</li> * <li>+0.0d is greater than -0.0d</li> * </ul> - * + * * @param double1 * the first value to compare. * @param double2 @@ -379,37 +339,44 @@ public final class Double extends Number implements Comparable<Double> { * @return a negative value if {@code double1} is less than {@code double2}; * 0 if {@code double1} and {@code double2} are equal; a positive * value if {@code double1} is greater than {@code double2}. - * @since Android 1.0 */ public static int compare(double double1, double double2) { - long d1, d2; - long NaNbits = Double.doubleToLongBits(Double.NaN); - if ((d1 = Double.doubleToLongBits(double1)) == NaNbits) { - if (Double.doubleToLongBits(double2) == NaNbits) { - return 0; - } + // Non-zero, non-NaN checking. + if (double1 > double2) { return 1; } - if ((d2 = Double.doubleToLongBits(double2)) == NaNbits) { + if (double2 > double1) { return -1; } - if (double1 == double2) { - if (d1 == d2) { + if (double1 == double2 && 0.0d != double1) { + return 0; + } + + // NaNs are equal to other NaNs and larger than any other double + if (isNaN(double1)) { + if (isNaN(double2)) { return 0; } - // check for -0 - return d1 > d2 ? 1 : -1; + return 1; + } else if (isNaN(double2)) { + return -1; } - return double1 > double2 ? 1 : -1; + + // Deal with +0.0 and -0.0 + long d1 = doubleToRawLongBits(double1); + long d2 = doubleToRawLongBits(double2); + // The below expression is equivalent to: + // (d1 == d2) ? 0 : (d1 < d2) ? -1 : 1 + return (int) ((d1 >> 63) - (d2 >> 63)); } /** * Returns a {@code Double} instance for the specified double value. - * + * * @param d * the double value to store in the instance. * @return a {@code Double} instance containing {@code d}. - * @since Android 1.0 + * @since 1.5 */ public static Double valueOf(double d) { return new Double(d); @@ -417,11 +384,11 @@ public final class Double extends Number implements Comparable<Double> { /** * Converts the specified double into its hexadecimal string representation. - * + * * @param d * the double to convert. * @return the hexadecimal string representation of {@code d}. - * @since Android 1.0 + * @since 1.5 */ public static String toHexString(double d) { /* diff --git a/luni/src/main/java/java/lang/Enum.java b/luni/src/main/java/java/lang/Enum.java index 0aa15dd..395c825 100644 --- a/luni/src/main/java/java/lang/Enum.java +++ b/luni/src/main/java/java/lang/Enum.java @@ -27,8 +27,6 @@ import org.apache.harmony.luni.util.Msg; * The superclass of all enumerated types. Actual enumeration types inherit from * this class, but extending this class does not make a class an enumration * type, since the compiler needs to generate special information for it. - * - * @since Android 1.0 */ public abstract class Enum<E extends Enum<E>> implements Serializable, Comparable<E> { @@ -41,13 +39,12 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, /** * Constructor for constants of enum subtypes. - * + * * @param name * the enum constant's declared name. * @param ordinal * the enum constant's ordinal, which corresponds to its position * in the enum declaration, starting at zero. - * @since Android 1.0 */ protected Enum(String name, int ordinal) { this.name = name; @@ -57,10 +54,9 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, /** * Returns the name of this enum constant. The name is the field as it * appears in the {@code enum} declaration. - * + * * @return the name of this enum constant. * @see #toString() - * @since Android 1.0 */ public final String name() { return name; @@ -69,9 +65,8 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, /** * Returns the position of the enum constant in the declaration. The first * constant has an ordinal value of zero. - * + * * @return the ordinal value of this enum constant. - * @since Android 1.0 */ public final int ordinal() { return ordinal; @@ -80,9 +75,8 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, /** * Returns a string containing a concise, human-readable description of this * object. In this case, the enum constant's name is returned. - * + * * @return a printable representation of this object. - * @since Android 1.0 */ @Override public String toString() { @@ -93,12 +87,11 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, * Compares this object with the specified object and indicates if they are * equal. In order to be equal, {@code object} must be identical to this * enum constant. - * + * * @param other * the object to compare this enum constant with. * @return {@code true} if the specified object is equal to this * {@code Enum}; {@code false} otherwise. - * @since Android 1.0 */ @Override public final boolean equals(Object other) { @@ -113,11 +106,10 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, /** * {@code Enum} objects are singletons, they may not be cloned. This method * always throws a {@code CloneNotSupportedException}. - * + * * @return does not return. * @throws CloneNotSupportedException * is always thrown. - * @since Android 1.0 */ @Override protected final Object clone() throws CloneNotSupportedException { @@ -129,7 +121,7 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, * Compares this object to the specified enum object to determine their * relative order. This method compares the object's ordinal values, that * is, their position in the enum declaration. - * + * * @param o * the enum object to compare this object to. * @return a negative value if the ordinal value of this enum constant is @@ -138,7 +130,6 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, * value if the ordinal value of this enum constant is greater than * the ordinal value of {@code o}. * @see java.lang.Comparable - * @since Android 1.0 */ public final int compareTo(E o) { return ordinal - o.ordinal; @@ -146,9 +137,8 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, /** * Returns the enum constant's declaring class. - * + * * @return the class object representing the constant's enum type. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public final Class<E> getDeclaringClass() { @@ -162,7 +152,7 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, /** * Returns the constant with the specified name of the specified enum type. - * + * * @param enumType * the class of the enumerated type to search for the constant * value. @@ -174,7 +164,6 @@ public abstract class Enum<E extends Enum<E>> implements Serializable, * @throws IllegalArgumentException * if {@code enumType} is not an enumerated type or does not * have a constant value called {@code name}. - * @since Android 1.0 */ public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { if ((enumType == null) || (name == null)) { diff --git a/luni/src/main/java/java/lang/EnumConstantNotPresentException.java b/luni/src/main/java/java/lang/EnumConstantNotPresentException.java index 0416703..aec32d0 100644 --- a/luni/src/main/java/java/lang/EnumConstantNotPresentException.java +++ b/luni/src/main/java/java/lang/EnumConstantNotPresentException.java @@ -20,8 +20,8 @@ import org.apache.harmony.luni.util.Msg; /** * Thrown if an {@code enum} constant does not exist for a particular name. - * - * @since Android 1.0 + * + * @since 1.5 */ public class EnumConstantNotPresentException extends RuntimeException { @@ -36,12 +36,11 @@ public class EnumConstantNotPresentException extends RuntimeException { * Constructs a new {@code EnumConstantNotPresentException} with the current * stack trace and a detail message based on the specified enum type and * missing constant name. - * + * * @param enumType * the enum type. * @param constantName * the missing constant name. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public EnumConstantNotPresentException(Class<? extends Enum> enumType, @@ -54,9 +53,8 @@ public class EnumConstantNotPresentException extends RuntimeException { /** * Gets the enum type for which the constant name is missing. - * + * * @return the enum type for which a constant name has not been found. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public Class<? extends Enum> enumType() { @@ -68,7 +66,6 @@ public class EnumConstantNotPresentException extends RuntimeException { * * @return the name of the constant that has not been found in the enum * type. - * @since Android 1.0 */ public String constantName() { return constantName; diff --git a/luni/src/main/java/java/lang/Error.java b/luni/src/main/java/java/lang/Error.java index 3bce72c..dd284ae 100644 --- a/luni/src/main/java/java/lang/Error.java +++ b/luni/src/main/java/java/lang/Error.java @@ -26,7 +26,6 @@ package java.lang; * @see Throwable * @see Exception * @see RuntimeException - * @since Android 1.0 */ public class Error extends Throwable { @@ -34,8 +33,6 @@ public class Error extends Throwable { /** * Constructs a new {@code Error} that includes the current stack trace. - * - * @since Android 1.0 */ public Error() { super(); @@ -47,7 +44,6 @@ public class Error extends Throwable { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public Error(String detailMessage) { super(detailMessage); @@ -61,7 +57,6 @@ public class Error extends Throwable { * the detail message for this error. * @param throwable * the cause of this error. - * @since Android 1.0 */ public Error(String detailMessage, Throwable throwable) { super(detailMessage, throwable); @@ -73,7 +68,6 @@ public class Error extends Throwable { * * @param throwable * the cause of this error. - * @since Android 1.0 */ public Error(Throwable throwable) { super(throwable); diff --git a/luni/src/main/java/java/lang/Exception.java b/luni/src/main/java/java/lang/Exception.java index 010cea4..7921edd 100644 --- a/luni/src/main/java/java/lang/Exception.java +++ b/luni/src/main/java/java/lang/Exception.java @@ -26,15 +26,12 @@ package java.lang; * @see Throwable * @see Error * @see RuntimeException - * @since Android 1.0 */ public class Exception extends Throwable { private static final long serialVersionUID = -3387516993124229948L; /** * Constructs a new {@code Exception} that includes the current stack trace. - * - * @since Android 1.0 */ public Exception() { super(); @@ -46,7 +43,6 @@ public class Exception extends Throwable { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public Exception(String detailMessage) { super(detailMessage); @@ -60,7 +56,6 @@ public class Exception extends Throwable { * the detail message for this exception. * @param throwable * the cause of this exception. - * @since Android 1.0 */ public Exception(String detailMessage, Throwable throwable) { super(detailMessage, throwable); @@ -72,7 +67,6 @@ public class Exception extends Throwable { * * @param throwable * the cause of this exception. - * @since Android 1.0 */ public Exception(Throwable throwable) { super(throwable); diff --git a/luni/src/main/java/java/lang/ExceptionInInitializerError.java b/luni/src/main/java/java/lang/ExceptionInInitializerError.java index 6096f08..3767488 100644 --- a/luni/src/main/java/java/lang/ExceptionInInitializerError.java +++ b/luni/src/main/java/java/lang/ExceptionInInitializerError.java @@ -19,8 +19,6 @@ package java.lang; /** * Thrown when an exception occurs during class initialization. - * - * @since Android 1.0 */ public class ExceptionInInitializerError extends LinkageError { @@ -31,8 +29,6 @@ public class ExceptionInInitializerError extends LinkageError { /** * Constructs a new {@code ExceptionInInitializerError} that includes the * current stack trace. - * - * @since Android 1.0 */ public ExceptionInInitializerError() { super(); @@ -45,7 +41,6 @@ public class ExceptionInInitializerError extends LinkageError { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public ExceptionInInitializerError(String detailMessage) { super(detailMessage); @@ -70,7 +65,6 @@ public class ExceptionInInitializerError extends LinkageError { * Returns the exception that is the cause of this error. * * @return the exception that caused this error. - * @since Android 1.0 */ public Throwable getException() { return exception; @@ -80,7 +74,6 @@ public class ExceptionInInitializerError extends LinkageError { * Returns the cause of this error, or {@code null} if there is no cause. * * @return the exception that caused this error. - * @since Android 1.0 */ @Override public Throwable getCause() { diff --git a/luni/src/main/java/java/lang/Float.java b/luni/src/main/java/java/lang/Float.java index 69f91c5..067149d 100644 --- a/luni/src/main/java/java/lang/Float.java +++ b/luni/src/main/java/java/lang/Float.java @@ -19,9 +19,9 @@ package java.lang; /** * The wrapper for the primitive type {@code float}. - * + * * @see java.lang.Number - * @since Android 1.0 + * @since 1.0 */ public final class Float extends Number implements Comparable<Float> { @@ -34,44 +34,34 @@ public final class Float extends Number implements Comparable<Float> { /** * Constant for the maximum {@code float} value, (2 - 2<sup>-23</sup>) * 2<sup>127</sup>. - * - * @since Android 1.0 */ public static final float MAX_VALUE = 3.40282346638528860e+38f; /** * Constant for the minimum {@code float} value, 2<sup>-149</sup>. - * - * @since Android 1.0 */ public static final float MIN_VALUE = 1.40129846432481707e-45f; /** * Constant for the Not-a-Number (NaN) value of the {@code float} type. - * - * @since Android 1.0 */ public static final float NaN = 0.0f / 0.0f; /** * Constant for the Positive Infinity value of the {@code float} type. - * - * @since Android 1.0 */ public static final float POSITIVE_INFINITY = 1.0f / 0.0f; /** * Constant for the Negative Infinity value of the {@code float} type. - * - * @since Android 1.0 */ public static final float NEGATIVE_INFINITY = -1.0f / 0.0f; /** - * The {@link Class} object that represents the primitive type {@code + * The {@link Class} object that represents the primitive type {@code * float}. - * - * @since Android 1.0 + * + * @since 1.1 */ @SuppressWarnings("unchecked") public static final Class<Float> TYPE = (Class<Float>) new float[0] @@ -83,17 +73,16 @@ public final class Float extends Number implements Comparable<Float> { /** * Constant for the number of bits needed to represent a {@code float} in * two's complement form. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int SIZE = 32; /** * Constructs a new {@code Float} with the specified primitive float value. - * + * * @param value * the primitive float value to store in the new instance. - * @since Android 1.0 */ public Float(float value) { this.value = value; @@ -101,10 +90,9 @@ public final class Float extends Number implements Comparable<Float> { /** * Constructs a new {@code Float} with the specified primitive double value. - * + * * @param value * the primitive double value to store in the new instance. - * @since Android 1.0 */ public Float(double value) { this.value = (float) value; @@ -112,13 +100,12 @@ public final class Float extends Number implements Comparable<Float> { /** * Constructs a new {@code Float} from the specified string. - * + * * @param string * the string representation of a float value. * @throws NumberFormatException * if {@code string} can not be decoded into a float value. * @see #parseFloat(String) - * @since Android 1.0 */ public Float(String string) throws NumberFormatException { this(parseFloat(string)); @@ -132,7 +119,7 @@ public final class Float extends Number implements Comparable<Float> { * than any other float value, including {@code Float.POSITIVE_INFINITY};</li> * <li>+0.0f is greater than -0.0f</li> * </ul> - * + * * @param object * the float object to compare this object to. * @return a negative value if the value of this float is less than the @@ -140,28 +127,10 @@ public final class Float extends Number implements Comparable<Float> { * value of {@code object} are equal; a positive value if the value * of this float is greater than the value of {@code object}. * @see java.lang.Comparable - * @since Android 1.0 + * @since 1.2 */ public int compareTo(Float object) { - int f1, f2; - int NaNbits = Float.floatToIntBits(Float.NaN); - if ((f1 = Float.floatToIntBits(value)) == NaNbits) { - if (Float.floatToIntBits(object.value) == NaNbits) { - return 0; - } - return 1; - } - if ((f2 = Float.floatToIntBits(object.value)) == NaNbits) { - return -1; - } - if (value == object.value) { - if (f1 == f2) { - return 0; - } - // check for -0 - return f1 > f2 ? 1 : -1; - } - return value > object.value ? 1 : -1; + return compare(value, object.value); } @Override @@ -178,12 +147,11 @@ public final class Float extends Number implements Comparable<Float> { * Compares this instance with the specified object and indicates if they * are equal. In order to be equal, {@code object} must be an instance of * {@code Float} and have the same float value as this object. - * + * * @param object * the object to compare this float with. * @return {@code true} if the specified object is equal to this * {@code Float}; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -197,14 +165,13 @@ public final class Float extends Number implements Comparable<Float> { * to the IEEE 754 floating-point single precision bit layout. All * <em>Not-a-Number (NaN)</em> values are converted to a single NaN * representation ({@code 0x7ff8000000000000L}). - * + * * @param value * the float value to convert. * @return the IEEE 754 floating-point single precision representation of * {@code value}. * @see #floatToRawIntBits(float) * @see #intBitsToFloat(int) - * @since Android 1.0 */ public static native int floatToIntBits(float value); @@ -212,22 +179,20 @@ public final class Float extends Number implements Comparable<Float> { * Converts the specified float value to a binary representation conforming * to the IEEE 754 floating-point single precision bit layout. * <em>Not-a-Number (NaN)</em> values are preserved. - * + * * @param value * the float value to convert. * @return the IEEE 754 floating-point single precision representation of * {@code value}. * @see #floatToIntBits(float) * @see #intBitsToFloat(int) - * @since Android 1.0 */ public static native int floatToRawIntBits(float value); /** * Gets the primitive value of this float. - * + * * @return this object's primitive value. - * @since Android 1.0 */ @Override public float floatValue() { @@ -242,14 +207,13 @@ public final class Float extends Number implements Comparable<Float> { /** * Converts the specified IEEE 754 floating-point single precision bit * pattern to a Java float value. - * + * * @param bits * the IEEE 754 floating-point single precision representation of * a float value. * @return the float value converted from {@code bits}. * @see #floatToIntBits(float) * @see #floatToRawIntBits(float) - * @since Android 1.0 */ public static native float intBitsToFloat(int bits); @@ -260,10 +224,9 @@ public final class Float extends Number implements Comparable<Float> { /** * Indicates whether this object represents an infinite value. - * + * * @return {@code true} if the value of this float is positive or negative * infinity; {@code false} otherwise. - * @since Android 1.0 */ public boolean isInfinite() { return isInfinite(value); @@ -271,12 +234,11 @@ public final class Float extends Number implements Comparable<Float> { /** * Indicates whether the specified float represents an infinite value. - * + * * @param f * the float to check. * @return {@code true} if the value of {@code f} is positive or negative * infinity; {@code false} otherwise. - * @since Android 1.0 */ public static boolean isInfinite(float f) { return (f == POSITIVE_INFINITY) || (f == NEGATIVE_INFINITY); @@ -284,10 +246,9 @@ public final class Float extends Number implements Comparable<Float> { /** * Indicates whether this object is a <em>Not-a-Number (NaN)</em> value. - * + * * @return {@code true} if this float is <em>Not-a-Number</em>; * {@code false} if it is a (potentially infinite) float number. - * @since Android 1.0 */ public boolean isNaN() { return isNaN(value); @@ -296,12 +257,11 @@ public final class Float extends Number implements Comparable<Float> { /** * Indicates whether the specified float is a <em>Not-a-Number (NaN)</em> * value. - * + * * @param f * the float value to check. * @return {@code true} if {@code f} is <em>Not-a-Number</em>; * {@code false} if it is a (potentially infinite) float number. - * @since Android 1.0 */ public static boolean isNaN(float f) { return f != f; @@ -314,14 +274,15 @@ public final class Float extends Number implements Comparable<Float> { /** * Parses the specified string as a float value. - * + * * @param string * the string representation of a float value. * @return the primitive float value represented by {@code string}. * @throws NumberFormatException * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a float value. - * @since Android 1.0 + * @see #valueOf(String) + * @since 1.2 */ public static float parseFloat(String string) throws NumberFormatException { return org.apache.harmony.luni.util.FloatingPointParser @@ -341,11 +302,10 @@ public final class Float extends Number implements Comparable<Float> { /** * Returns a string containing a concise, human-readable description of the * specified float value. - * + * * @param f * the float to convert to a string. * @return a printable representation of {@code f}. - * @since Android 1.0 */ public static String toString(float f) { return org.apache.harmony.luni.util.NumberConverter.convert(f); @@ -353,7 +313,7 @@ public final class Float extends Number implements Comparable<Float> { /** * Parses the specified string as a float value. - * + * * @param string * the string representation of a float value. * @return a {@code Float} instance containing the float value represented @@ -362,7 +322,6 @@ public final class Float extends Number implements Comparable<Float> { * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a float value. * @see #parseFloat(String) - * @since Android 1.0 */ public static Float valueOf(String string) throws NumberFormatException { return valueOf(parseFloat(string)); @@ -375,7 +334,7 @@ public final class Float extends Number implements Comparable<Float> { * than any other float value, including {@code Float.POSITIVE_INFINITY};</li> * <li>+0.0f is greater than -0.0f</li> * </ul> - * + * * @param float1 * the first value to compare. * @param float2 @@ -383,37 +342,46 @@ public final class Float extends Number implements Comparable<Float> { * @return a negative value if {@code float1} is less than {@code float2}; * 0 if {@code float1} and {@code float2} are equal; a positive * value if {@code float1} is greater than {@code float2}. - * @since Android 1.0 + * @since 1.4 */ public static int compare(float float1, float float2) { - int f1, f2; - int NaNbits = Float.floatToIntBits(Float.NaN); - if ((f1 = Float.floatToIntBits(float1)) == NaNbits) { - if (Float.floatToIntBits(float2) == NaNbits) { - return 0; - } + // Non-zero, non-NaN checking. + if (float1 > float2) { return 1; } - if ((f2 = Float.floatToIntBits(float2)) == NaNbits) { + if (float2 > float1) { return -1; } - if (float1 == float2) { - if (f1 == f2) { + if (float1 == float2 && 0.0f != float1) { + return 0; + } + + // NaNs are equal to other NaNs and larger than any other float + if (isNaN(float1)) { + if (isNaN(float2)) { return 0; } - // check for -0 - return f1 > f2 ? 1 : -1; + return 1; + } else if (isNaN(float2)) { + return -1; } - return float1 > float2 ? 1 : -1; + + // Deal with +0.0 and -0.0 + int f1 = floatToRawIntBits(float1); + int f2 = floatToRawIntBits(float2); + // The below expression is equivalent to: + // (f1 == f2) ? 0 : (f1 < f2) ? -1 : 1 + // because f1 and f2 are either 0 or Integer.MIN_VALUE + return (f1 >> 31) - (f2 >> 31); } /** * Returns a {@code Float} instance for the specified float value. - * + * * @param f * the float value to store in the instance. * @return a {@code Float} instance containing {@code f}. - * @since Android 1.0 + * @since 1.5 */ public static Float valueOf(float f) { return new Float(f); @@ -421,11 +389,11 @@ public final class Float extends Number implements Comparable<Float> { /** * Converts the specified float into its hexadecimal string representation. - * + * * @param f * the float to convert. * @return the hexadecimal string representation of {@code f}. - * @since Android 1.0 + * @since 1.5 */ public static String toHexString(float f) { /* diff --git a/luni/src/main/java/java/lang/IllegalAccessError.java b/luni/src/main/java/java/lang/IllegalAccessError.java index 7f87afd..7fcef85 100644 --- a/luni/src/main/java/java/lang/IllegalAccessError.java +++ b/luni/src/main/java/java/lang/IllegalAccessError.java @@ -22,9 +22,6 @@ package java.lang; * which is not accessible from where it is referenced. * <p> * Note that this can only occur when inconsistent class files have been loaded. - * </p> - * - * @since Android 1.0 */ public class IllegalAccessError extends IncompatibleClassChangeError { @@ -33,8 +30,6 @@ public class IllegalAccessError extends IncompatibleClassChangeError { /** * Constructs a new {@code IllegalAccessError} that includes the current * stack trace. - * - * @since Android 1.0 */ public IllegalAccessError() { super(); @@ -46,7 +41,6 @@ public class IllegalAccessError extends IncompatibleClassChangeError { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public IllegalAccessError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/IllegalAccessException.java b/luni/src/main/java/java/lang/IllegalAccessException.java index b9d2d69..d96fd56 100644 --- a/luni/src/main/java/java/lang/IllegalAccessException.java +++ b/luni/src/main/java/java/lang/IllegalAccessException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when a program attempts to access a field or method which is not * accessible from the location where the reference is made. - * - * @since Android 1.0 */ public class IllegalAccessException extends Exception { @@ -30,8 +28,6 @@ public class IllegalAccessException extends Exception { /** * Constructs a new {@code IllegalAccessException} that includes the current * stack trace. - * - * @since Android 1.0 */ public IllegalAccessException() { super(); @@ -43,7 +39,6 @@ public class IllegalAccessException extends Exception { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public IllegalAccessException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/IllegalArgumentException.java b/luni/src/main/java/java/lang/IllegalArgumentException.java index 6f8dcf6..eb2ad91 100644 --- a/luni/src/main/java/java/lang/IllegalArgumentException.java +++ b/luni/src/main/java/java/lang/IllegalArgumentException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when a method is invoked with an argument which it can not reasonably * deal with. - * - * @since Android 1.0 */ public class IllegalArgumentException extends RuntimeException { @@ -30,8 +28,6 @@ public class IllegalArgumentException extends RuntimeException { /** * Constructs a new {@code IllegalArgumentException} that includes the * current stack trace. - * - * @since Android 1.0 */ public IllegalArgumentException() { super(); @@ -43,7 +39,6 @@ public class IllegalArgumentException extends RuntimeException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public IllegalArgumentException(String detailMessage) { super(detailMessage); @@ -57,7 +52,7 @@ public class IllegalArgumentException extends RuntimeException { * the detail message for this exception. * @param cause * the cause of this exception, may be {@code null}. - * @since Android 1.0 + * @since 1.5 */ public IllegalArgumentException(String message, Throwable cause) { super(message, cause); @@ -69,8 +64,8 @@ public class IllegalArgumentException extends RuntimeException { * * @param cause * the cause of this exception, may be {@code null}. - * @since Android 1.0 - */ + * @since 1.5 + */ public IllegalArgumentException(Throwable cause) { super((cause == null ? null : cause.toString()), cause); } diff --git a/luni/src/main/java/java/lang/IllegalMonitorStateException.java b/luni/src/main/java/java/lang/IllegalMonitorStateException.java index e570bfd..a0b8a75 100644 --- a/luni/src/main/java/java/lang/IllegalMonitorStateException.java +++ b/luni/src/main/java/java/lang/IllegalMonitorStateException.java @@ -21,8 +21,6 @@ package java.lang; * Thrown when a monitor operation is attempted when the monitor is not in the * correct state, for example when a thread attempts to exit a monitor which it * does not own. - * - * @since Android 1.0 */ public class IllegalMonitorStateException extends RuntimeException { @@ -31,8 +29,6 @@ public class IllegalMonitorStateException extends RuntimeException { /** * Constructs a new {@code IllegalMonitorStateException} that includes the * current stack trace. - * - * @since Android 1.0 */ public IllegalMonitorStateException() { super(); @@ -44,7 +40,6 @@ public class IllegalMonitorStateException extends RuntimeException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public IllegalMonitorStateException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/IllegalStateException.java b/luni/src/main/java/java/lang/IllegalStateException.java index 427aaf4..28db2de 100644 --- a/luni/src/main/java/java/lang/IllegalStateException.java +++ b/luni/src/main/java/java/lang/IllegalStateException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when an action is attempted at a time when the virtual machine is not * in the correct state. - * - * @since Android 1.0 */ public class IllegalStateException extends RuntimeException { @@ -30,8 +28,6 @@ public class IllegalStateException extends RuntimeException { /** * Constructs a new {@code IllegalStateException} that includes the current * stack trace. - * - * @since Android 1.0 */ public IllegalStateException() { super(); @@ -43,7 +39,6 @@ public class IllegalStateException extends RuntimeException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public IllegalStateException(String detailMessage) { super(detailMessage); @@ -57,7 +52,7 @@ public class IllegalStateException extends RuntimeException { * the detail message for this exception. * @param cause * the cause of this exception. - * @since Android 1.0 + * @since 1.5 */ public IllegalStateException(String message, Throwable cause) { super(message, cause); @@ -69,7 +64,7 @@ public class IllegalStateException extends RuntimeException { * * @param cause * the cause of this exception, may be {@code null}. - * @since Android 1.0 + * @since 1.5 */ public IllegalStateException(Throwable cause) { super((cause == null ? null : cause.toString()), cause); diff --git a/luni/src/main/java/java/lang/IllegalThreadStateException.java b/luni/src/main/java/java/lang/IllegalThreadStateException.java index 82eccbb..f1e99a8 100644 --- a/luni/src/main/java/java/lang/IllegalThreadStateException.java +++ b/luni/src/main/java/java/lang/IllegalThreadStateException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when an operation is attempted which is not possible given the state * that the executing thread is in. - * - * @since Android 1.0 */ public class IllegalThreadStateException extends IllegalArgumentException { @@ -30,8 +28,6 @@ public class IllegalThreadStateException extends IllegalArgumentException { /** * Constructs a new {@code IllegalThreadStateException} that includes the * current stack trace. - * - * @since Android 1.0 */ public IllegalThreadStateException() { super(); @@ -43,7 +39,6 @@ public class IllegalThreadStateException extends IllegalArgumentException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public IllegalThreadStateException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/IncompatibleClassChangeError.java b/luni/src/main/java/java/lang/IncompatibleClassChangeError.java index 83950fd..2155a28 100644 --- a/luni/src/main/java/java/lang/IncompatibleClassChangeError.java +++ b/luni/src/main/java/java/lang/IncompatibleClassChangeError.java @@ -24,7 +24,6 @@ package java.lang; * the same running image. * * @see Error - * @since Android 1.0 */ public class IncompatibleClassChangeError extends LinkageError { @@ -33,8 +32,6 @@ public class IncompatibleClassChangeError extends LinkageError { /** * Constructs a new {@code IncompatibleClassChangeError} that includes the * current stack trace. - * - * @since Android 1.0 */ public IncompatibleClassChangeError() { super(); @@ -46,7 +43,6 @@ public class IncompatibleClassChangeError extends LinkageError { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public IncompatibleClassChangeError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/IndexOutOfBoundsException.java b/luni/src/main/java/java/lang/IndexOutOfBoundsException.java index a4dc282..f26fcbf 100644 --- a/luni/src/main/java/java/lang/IndexOutOfBoundsException.java +++ b/luni/src/main/java/java/lang/IndexOutOfBoundsException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when a program attempts to access a value in an indexable collection * using a value which is outside of the range of valid indices. - * - * @since Android 1.0 */ public class IndexOutOfBoundsException extends RuntimeException { @@ -30,8 +28,6 @@ public class IndexOutOfBoundsException extends RuntimeException { /** * Constructs a new {@code IndexOutOfBoundsException} that includes the * current stack trace. - * - * @since Android 1.0 */ public IndexOutOfBoundsException() { super(); @@ -43,7 +39,6 @@ public class IndexOutOfBoundsException extends RuntimeException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public IndexOutOfBoundsException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/InheritableThreadLocal.java b/luni/src/main/java/java/lang/InheritableThreadLocal.java index 41e0d82..7e12ac2 100644 --- a/luni/src/main/java/java/lang/InheritableThreadLocal.java +++ b/luni/src/main/java/java/lang/InheritableThreadLocal.java @@ -1,17 +1,18 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * 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 * - * Licensed 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 * - * 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. + * 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 java.lang; @@ -24,36 +25,33 @@ package java.lang; * creation time. However, subclasses may override {code #childValue(Object)} * to provide an arbitrary function for passing the value of a parent's * thread-local variable to the child's thread-local variable. - * + * * @see java.lang.Thread * @see java.lang.ThreadLocal - * - * @since Android 1.0 */ public class InheritableThreadLocal<T> extends ThreadLocal<T> { /** * Creates a new inheritable thread-local variable. - * - * @since Android 1.0 */ - public InheritableThreadLocal() {} + public InheritableThreadLocal() { + super(); + } /** * Computes the initial value of this thread-local variable for the child - * thread given the parent thread's value. Called from the parent thread - * when creating a child thread. The default implementation returns the - * parent thread's value. - * - * @param parentValue - * the value of the variable in the parent thread. + * thread given the parent thread's value. Called from the parent thread when + * creating a child thread. The default implementation returns the parent + * thread's value. + * + * @param parentValue the value of the variable in the parent thread. * @return the initial value of the variable for the child thread. - * @since Android 1.0 */ protected T childValue(T parentValue) { return parentValue; } + // BEGIN android-added @Override Values values(Thread current) { return current.inheritableValues; @@ -63,4 +61,5 @@ public class InheritableThreadLocal<T> extends ThreadLocal<T> { Values initializeValues(Thread current) { return current.inheritableValues = new Values(); } + // END android-added } diff --git a/luni/src/main/java/java/lang/InstantiationError.java b/luni/src/main/java/java/lang/InstantiationError.java index 0d387c6..9ad1ed6 100644 --- a/luni/src/main/java/java/lang/InstantiationError.java +++ b/luni/src/main/java/java/lang/InstantiationError.java @@ -23,9 +23,6 @@ package java.lang; * {@code new} is invoked. * <p> * Note that this can only occur when inconsistent class files are being loaded. - * </p> - * - * @since Android 1.0 */ public class InstantiationError extends IncompatibleClassChangeError { private static final long serialVersionUID = -4885810657349421204L; @@ -33,8 +30,6 @@ public class InstantiationError extends IncompatibleClassChangeError { /** * Constructs a new {@code InstantiationError} that includes the current * stack trace. - * - * @since Android 1.0 */ public InstantiationError() { super(); @@ -46,7 +41,6 @@ public class InstantiationError extends IncompatibleClassChangeError { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public InstantiationError(String detailMessage) { super(detailMessage); @@ -58,7 +52,6 @@ public class InstantiationError extends IncompatibleClassChangeError { * * @param clazz * the class that can not be instantiated. - * @since Android 1.0 */ InstantiationError(Class<?> clazz) { super(clazz.getName()); diff --git a/luni/src/main/java/java/lang/InstantiationException.java b/luni/src/main/java/java/lang/InstantiationException.java index cc8b556..fe68345 100644 --- a/luni/src/main/java/java/lang/InstantiationException.java +++ b/luni/src/main/java/java/lang/InstantiationException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when a program attempts to access a constructor which is not * accessible from the location where the reference is made. - * - * @since Android 1.0 */ public class InstantiationException extends Exception { private static final long serialVersionUID = -8441929162975509110L; @@ -29,8 +27,6 @@ public class InstantiationException extends Exception { /** * Constructs a new {@code InstantiationException} that includes the current * stack trace. - * - * @since Android 1.0 */ public InstantiationException() { super(); @@ -42,7 +38,6 @@ public class InstantiationException extends Exception { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public InstantiationException(String detailMessage) { super(detailMessage); @@ -54,7 +49,6 @@ public class InstantiationException extends Exception { * * @param clazz * the class that can not be instantiated. - * @since Android 1.0 */ InstantiationException(Class<?> clazz) { super(clazz.getName()); diff --git a/luni/src/main/java/java/lang/Integer.java b/luni/src/main/java/java/lang/Integer.java index 3a98872..570120b 100644 --- a/luni/src/main/java/java/lang/Integer.java +++ b/luni/src/main/java/java/lang/Integer.java @@ -24,10 +24,9 @@ package java.lang; * href="http://www.hackersdelight.org/">Henry S. Warren, Jr.'s Hacker's * Delight, (Addison Wesley, 2002)</a> as well as <a * href="http://aggregate.org/MAGIC/">The Aggregate's Magic Algorithms</a>. - * </p> - * + * * @see java.lang.Number - * @since Android 1.0 + * @since 1.1 */ public final class Integer extends Number implements Comparable<Integer> { @@ -40,30 +39,32 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Constant for the maximum {@code int} value, 2<sup>31</sup>-1. - * - * @since Android 1.0 */ public static final int MAX_VALUE = 0x7FFFFFFF; /** * Constant for the minimum {@code int} value, -2<sup>31</sup>. - * - * @since Android 1.0 */ public static final int MIN_VALUE = 0x80000000; /** * Constant for the number of bits needed to represent an {@code int} in * two's complement form. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int SIZE = 32; + /* + * Progressively smaller decimal order of magnitude that can be represented + * by an instance of Integer. Used to help compute the String + * representation. + */ + private static final int[] decimalScale = new int[] { 1000000000, 100000000, + 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 }; + /** * The {@link Class} object that represents the primitive type {@code int}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final Class<Integer> TYPE = (Class<Integer>) new int[0] @@ -75,10 +76,9 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Constructs a new {@code Integer} with the specified primitive integer * value. - * + * * @param value * the primitive integer value to store in the new instance. - * @since Android 1.0 */ public Integer(int value) { this.value = value; @@ -86,13 +86,12 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Constructs a new {@code Integer} from the specified string. - * + * * @param string * the string representation of an integer value. * @throws NumberFormatException * if {@code string} can not be decoded into an integer value. * @see #parseInt(String) - * @since Android 1.0 */ public Integer(String string) throws NumberFormatException { this(parseInt(string)); @@ -106,7 +105,7 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Compares this object to the specified integer object to determine their * relative order. - * + * * @param object * the integer object to compare this object to. * @return a negative value if the value of this integer is less than the @@ -114,7 +113,7 @@ public final class Integer extends Number implements Comparable<Integer> { * value of {@code object} are equal; a positive value if the value * of this integer is greater than the value of {@code object}. * @see java.lang.Comparable - * @since Android 1.0 + * @since 1.2 */ public int compareTo(Integer object) { return value > object.value ? 1 : (value < object.value ? -1 : 0); @@ -125,14 +124,13 @@ public final class Integer extends Number implements Comparable<Integer> { * string can be decoded into an integer value. The string may be an * optional minus sign "-" followed by a hexadecimal ("0x..." or "#..."), * octal ("0..."), or decimal ("...") representation of an integer. - * + * * @param string * a string representation of an integer value. * @return an {@code Integer} containing the value represented by * {@code string}. * @throws NumberFormatException * if {@code string} can not be parsed as an integer value. - * @since Android 1.0 */ public static Integer decode(String string) throws NumberFormatException { int length = string.length(), i = 0; @@ -158,23 +156,21 @@ public final class Integer extends Number implements Comparable<Integer> { return valueOf(0); } if ((firstDigit = string.charAt(i)) == 'x' || firstDigit == 'X') { - if (i == length) { + if (++i == length) { // BEGIN android-changed throw new NumberFormatException("unable to parse '"+string+"' as integer"); // END android-changed } - i++; base = 16; } else { base = 8; } } else if (firstDigit == '#') { - if (i == length) { + if (++i == length) { // BEGIN android-changed throw new NumberFormatException("unable to parse '"+string+"' as integer"); // END android-changed } - i++; base = 16; } @@ -191,12 +187,11 @@ public final class Integer extends Number implements Comparable<Integer> { * Compares this instance with the specified object and indicates if they * are equal. In order to be equal, {@code o} must be an instance of * {@code Integer} and have the same integer value as this object. - * + * * @param o * the object to compare this integer with. * @return {@code true} if the specified object is equal to this * {@code Integer}; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object o) { @@ -214,12 +209,11 @@ public final class Integer extends Number implements Comparable<Integer> { * {@code string}. Returns {@code null} if {@code string} is {@code null} * or empty, if the property can not be found or if its value can not be * parsed as an integer. - * + * * @param string * the name of the requested system property. * @return the requested property's value as an {@code Integer} or * {@code null}. - * @since Android 1.0 */ public static Integer getInteger(String string) { if (string == null || string.length() == 0) { @@ -241,7 +235,7 @@ public final class Integer extends Number implements Comparable<Integer> { * {@code string}. Returns the specified default value if {@code string} is * {@code null} or empty, if the property can not be found or if its value * can not be parsed as an integer. - * + * * @param string * the name of the requested system property. * @param defaultValue @@ -249,7 +243,6 @@ public final class Integer extends Number implements Comparable<Integer> { * system property with the requested name. * @return the requested property's value as an {@code Integer} or the * default value. - * @since Android 1.0 */ public static Integer getInteger(String string, int defaultValue) { if (string == null || string.length() == 0) { @@ -271,7 +264,7 @@ public final class Integer extends Number implements Comparable<Integer> { * {@code string}. Returns the specified default value if {@code string} is * {@code null} or empty, if the property can not be found or if its value * can not be parsed as an integer. - * + * * @param string * the name of the requested system property. * @param defaultValue @@ -279,7 +272,6 @@ public final class Integer extends Number implements Comparable<Integer> { * system property with the requested name. * @return the requested property's value as an {@code Integer} or the * default value. - * @since Android 1.0 */ public static Integer getInteger(String string, Integer defaultValue) { if (string == null || string.length() == 0) { @@ -303,9 +295,8 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Gets the primitive value of this int. - * + * * @return this object's primitive value. - * @since Android 1.0 */ @Override public int intValue() { @@ -320,14 +311,13 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Parses the specified string as a signed decimal integer value. The ASCII * character \u002d ('-') is recognized as the minus sign. - * + * * @param string * the string representation of an integer value. * @return the primitive integer value represented by {@code string}. * @throws NumberFormatException * if {@code string} is {@code null}, has a length of zero or * can not be parsed as an integer value. - * @since Android 1.0 */ public static int parseInt(String string) throws NumberFormatException { return parseInt(string, 10); @@ -336,7 +326,7 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Parses the specified string as a signed integer value using the specified * radix. The ASCII character \u002d ('-') is recognized as the minus sign. - * + * * @param string * the string representation of an integer value. * @param radix @@ -348,7 +338,6 @@ public final class Integer extends Number implements Comparable<Integer> { * {@code radix < Character.MIN_RADIX}, * {@code radix > Character.MAX_RADIX}, or if {@code string} * can not be parsed as an integer value. - * @since Android 1.0 */ public static int parseInt(String string, int radix) throws NumberFormatException { @@ -417,11 +406,10 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Converts the specified integer into its binary string representation. The * returned string is a concatenation of '0' and '1' characters. - * + * * @param i * the integer to convert. * @return the binary string representation of {@code i}. - * @since Android 1.0 */ public static String toBinaryString(int i) { int count = 1, j = i; @@ -446,12 +434,11 @@ public final class Integer extends Number implements Comparable<Integer> { * Converts the specified integer into its hexadecimal string * representation. The returned string is a concatenation of characters from * '0' to '9' and 'a' to 'f'. - * + * * @param i * the integer to convert. * @return the hexadecimal string representation of {@code i}. - * @since Android 1.0 - */ + */ public static String toHexString(int i) { int count = 1, j = i; @@ -480,12 +467,11 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Converts the specified integer into its octal string representation. The * returned string is a concatenation of characters from '0' to '7'. - * + * * @param i * the integer to convert. * @return the octal string representation of {@code i}. - * @since Android 1.0 - */ + */ public static String toOctalString(int i) { int count = 1, j = i; @@ -514,14 +500,102 @@ public final class Integer extends Number implements Comparable<Integer> { * Converts the specified integer into its decimal string representation. * The returned string is a concatenation of a minus sign if the number is * negative and characters from '0' to '9'. - * - * @param i + * + * @param value * the integer to convert. - * @return the decimal string representation of {@code i}. - * @since Android 1.0 - */ - public static String toString(int i) { - return toString(i, 10); + * @return the decimal string representation of {@code value}. + */ + public static String toString(int value) { + // BEGIN android-note + // cache the strings in the range 0..99 to save allocations? + // END android-note + if (value == 0) { + return "0"; //$NON-NLS-1$ + } + + // Faster algorithm for smaller Integers + if (value < 1000 && value > -1000) { + char[] buffer = new char[4]; + int positive_value = value < 0 ? -value : value; + int first_digit = 0; + if (value < 0) { + buffer[0] = '-'; + first_digit++; + } + int last_digit = first_digit; + int quot = positive_value; + do { + int res = quot / 10; + int digit_value = quot - (res * 10); + digit_value += '0'; + buffer[last_digit++] = (char) digit_value; + quot = res; + } while (quot != 0); + + int count = last_digit--; + do { + char tmp = buffer[last_digit]; + buffer[last_digit--] = buffer[first_digit]; + buffer[first_digit++] = tmp; + } while (first_digit < last_digit); + return new String(0, count, buffer); + } + if (value == MIN_VALUE) { + return "-2147483648";//$NON-NLS-1$ + } + + char[] buffer = new char[11]; + int positive_value = value < 0 ? -value : value; + byte first_digit = 0; + if (value < 0) { + buffer[0] = '-'; + first_digit++; + } + byte last_digit = first_digit; + byte count; + int number; + boolean start = false; + for (int i = 0; i < 9; i++) { + count = 0; + if (positive_value < (number = decimalScale[i])) { + if (start) { + buffer[last_digit++] = '0'; + } + continue; + } + + if (i > 0) { + number = (decimalScale[i] << 3); + if (positive_value >= number) { + positive_value -= number; + count += 8; + } + number = (decimalScale[i] << 2); + if (positive_value >= number) { + positive_value -= number; + count += 4; + } + } + number = (decimalScale[i] << 1); + if (positive_value >= number) { + positive_value -= number; + count += 2; + } + if (positive_value >= decimalScale[i]) { + positive_value -= decimalScale[i]; + count++; + } + if (count > 0 && !start) { + start = true; + } + if (start) { + buffer[last_digit++] = (char) (count + '0'); + } + } + + buffer[last_digit++] = (char) (positive_value + '0'); + count = last_digit--; + return new String(0, count, buffer); } /** @@ -531,15 +605,18 @@ public final class Integer extends Number implements Comparable<Integer> { * depending on the radix. If {@code radix} is not in the interval defined * by {@code Character.MIN_RADIX} and {@code Character.MAX_RADIX} then 10 is * used as the base for the conversion. - * + * * @param i * the integer to convert. * @param radix * the base to use for the conversion. * @return the string representation of {@code i}. - * @since Android 1.0 - */ + */ public static String toString(int i, int radix) { + // BEGIN android-note + // if radix==10, call thru to faster Integer.toString(int) ? + // only worthwhile if 10 is a popular parameter + // END android-note if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { radix = 10; } @@ -575,7 +652,7 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Parses the specified string as a signed decimal integer value. - * + * * @param string * the string representation of an integer value. * @return an {@code Integer} instance containing the integer value @@ -584,7 +661,6 @@ public final class Integer extends Number implements Comparable<Integer> { * if {@code string} is {@code null}, has a length of zero or * can not be parsed as an integer value. * @see #parseInt(String) - * @since Android 1.0 */ public static Integer valueOf(String string) throws NumberFormatException { return valueOf(parseInt(string)); @@ -593,7 +669,7 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Parses the specified string as a signed integer value using the specified * radix. - * + * * @param string * the string representation of an integer value. * @param radix @@ -606,7 +682,6 @@ public final class Integer extends Number implements Comparable<Integer> { * {@code radix > Character.MAX_RADIX}, or if {@code string} * can not be parsed as an integer value. * @see #parseInt(String, int) - * @since Android 1.0 */ public static Integer valueOf(String string, int radix) throws NumberFormatException { @@ -618,11 +693,11 @@ public final class Integer extends Number implements Comparable<Integer> { * and returns the bit mask value for that bit. This is also referred to as * the Most Significant 1 Bit. Returns zero if the specified integer is * zero. - * + * * @param i * the integer to examine. * @return the bit mask indicating the highest 1 bit in {@code i}. - * @since Android 1.0 + * @since 1.5 */ public static int highestOneBit(int i) { i |= (i >> 1); @@ -638,11 +713,11 @@ public final class Integer extends Number implements Comparable<Integer> { * and returns the bit mask value for that bit. This is also referred * to as the Least Significant 1 Bit. Returns zero if the specified integer * is zero. - * + * * @param i * the integer to examine. * @return the bit mask indicating the lowest 1 bit in {@code i}. - * @since Android 1.0 + * @since 1.5 */ public static int lowestOneBit(int i) { return (i & (-i)); @@ -651,11 +726,11 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Determines the number of leading zeros in the specified integer prior to * the {@link #highestOneBit(int) highest one bit}. - * + * * @param i * the integer to examine. * @return the number of leading zeros in {@code i}. - * @since Android 1.0 + * @since 1.5 */ public static int numberOfLeadingZeros(int i) { i |= i >> 1; @@ -669,11 +744,11 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Determines the number of trailing zeros in the specified integer after * the {@link #lowestOneBit(int) lowest one bit}. - * + * * @param i * the integer to examine. * @return the number of trailing zeros in {@code i}. - * @since Android 1.0 + * @since 1.5 */ public static int numberOfTrailingZeros(int i) { return bitCount((i & -i) - 1); @@ -682,11 +757,11 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Counts the number of 1 bits in the specified integer; this is also * referred to as population count. - * + * * @param i * the integer to examine. * @return the number of 1 bits in {@code i}. - * @since Android 1.0 + * @since 1.5 */ public static int bitCount(int i) { i -= ((i >> 1) & 0x55555555); @@ -700,13 +775,13 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Rotates the bits of the specified integer to the left by the specified * number of bits. - * + * * @param i * the integer value to rotate left. * @param distance * the number of bits to rotate. * @return the rotated value. - * @since Android 1.0 + * @since 1.5 */ public static int rotateLeft(int i, int distance) { if (distance == 0) { @@ -723,13 +798,13 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Rotates the bits of the specified integer to the right by the specified * number of bits. - * + * * @param i * the integer value to rotate right. * @param distance * the number of bits to rotate. * @return the rotated value. - * @since Android 1.0 + * @since 1.5 */ public static int rotateRight(int i, int distance) { if (distance == 0) { @@ -745,11 +820,11 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Reverses the order of the bytes of the specified integer. - * + * * @param i * the integer value for which to reverse the byte order. * @return the reversed value. - * @since Android 1.0 + * @since 1.5 */ public static int reverseBytes(int i) { int b3 = i >>> 24; @@ -761,11 +836,11 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Reverses the order of the bits of the specified integer. - * + * * @param i * the integer value for which to reverse the bit order. * @return the reversed value. - * @since Android 1.0 + * @since 1.5 */ public static int reverse(int i) { // From Hacker's Delight, 7-1, Figure 7-1 @@ -778,12 +853,12 @@ public final class Integer extends Number implements Comparable<Integer> { /** * Returns the value of the {@code signum} function for the specified * integer. - * + * * @param i * the integer value to check. * @return -1 if {@code i} is negative, 1 if {@code i} is positive, 0 if * {@code i} is zero. - * @since Android 1.0 + * @since 1.5 */ public static int signum(int i) { return (i == 0 ? 0 : (i < 0 ? -1 : 1)); @@ -795,12 +870,11 @@ public final class Integer extends Number implements Comparable<Integer> { * If it is not necessary to get a new {@code Integer} instance, it is * recommended to use this method instead of the constructor, since it * maintains a cache of instances which may result in better performance. - * </p> - * + * * @param i * the integer value to store in the instance. * @return a {@code Integer} instance containing {@code i}. - * @since Android 1.0 + * @since 1.5 */ public static Integer valueOf(int i) { if (i < -128 || i > 127) { @@ -814,7 +888,6 @@ public final class Integer extends Number implements Comparable<Integer> { /** * <p> * A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing. - * </p> */ static final Integer[] CACHE = new Integer[256]; diff --git a/luni/src/main/java/java/lang/InternalError.java b/luni/src/main/java/java/lang/InternalError.java index 9082cd8..d4748af 100644 --- a/luni/src/main/java/java/lang/InternalError.java +++ b/luni/src/main/java/java/lang/InternalError.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when the virtual machine notices that it has gotten into an undefined * state. - * - * @since Android 1.0 */ public class InternalError extends VirtualMachineError { @@ -30,8 +28,6 @@ public class InternalError extends VirtualMachineError { /** * Constructs a new {@code InternalError} that includes the current stack * trace. - * - * @since Android 1.0 */ public InternalError() { super(); @@ -43,7 +39,6 @@ public class InternalError extends VirtualMachineError { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public InternalError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/InterruptedException.java b/luni/src/main/java/java/lang/InterruptedException.java index b014559..0e099c3 100644 --- a/luni/src/main/java/java/lang/InterruptedException.java +++ b/luni/src/main/java/java/lang/InterruptedException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when a waiting thread is activated before the condition it was waiting * for has been satisfied. - * - * @since Android 1.0 */ public class InterruptedException extends Exception { @@ -30,8 +28,6 @@ public class InterruptedException extends Exception { /** * Constructs a new {@code InterruptedException} that includes the current * stack trace. - * - * @since Android 1.0 */ public InterruptedException() { super(); @@ -43,7 +39,6 @@ public class InterruptedException extends Exception { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public InterruptedException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/Iterable.java b/luni/src/main/java/java/lang/Iterable.java index d12f0a6..31883fb 100644 --- a/luni/src/main/java/java/lang/Iterable.java +++ b/luni/src/main/java/java/lang/Iterable.java @@ -21,8 +21,8 @@ import java.util.Iterator; /** * Objects of classes that implement this interface can be used within a * {@code foreach} statement. - * - * @since Android 1.0 + * + * @since 1.5 */ public interface Iterable<T> { @@ -30,7 +30,6 @@ public interface Iterable<T> { * Returns an {@link Iterator} for the elements in this object. * * @return An {@code Iterator} instance. - * @since Android 1.0 */ Iterator<T> iterator(); } diff --git a/luni/src/main/java/java/lang/LinkageError.java b/luni/src/main/java/java/lang/LinkageError.java index 9bba54b..061f3dc 100644 --- a/luni/src/main/java/java/lang/LinkageError.java +++ b/luni/src/main/java/java/lang/LinkageError.java @@ -23,7 +23,6 @@ package java.lang; * loading and linking class files. * * @see Error - * @since Android 1.0 */ public class LinkageError extends Error { @@ -32,8 +31,6 @@ public class LinkageError extends Error { /** * Constructs a new {@code LinkageError} that includes the current stack * trace. - * - * @since Android 1.0 */ public LinkageError() { super(); @@ -45,7 +42,6 @@ public class LinkageError extends Error { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public LinkageError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/Long.java b/luni/src/main/java/java/lang/Long.java index 00b56ae..2746424 100644 --- a/luni/src/main/java/java/lang/Long.java +++ b/luni/src/main/java/java/lang/Long.java @@ -24,10 +24,9 @@ package java.lang; * href="http://www.hackersdelight.org/">Henry S. Warren, Jr.'s Hacker's * Delight, (Addison Wesley, 2002)</a> as well as <a * href="http://aggregate.org/MAGIC/">The Aggregate's Magic Algorithms</a>. - * </p> - * + * * @see java.lang.Number - * @since Android 1.0 + * @since 1.0 */ public final class Long extends Number implements Comparable<Long> { @@ -40,22 +39,16 @@ public final class Long extends Number implements Comparable<Long> { /** * Constant for the maximum {@code long} value, 2<sup>63</sup>-1. - * - * @since Android 1.0 */ public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL; /** * Constant for the minimum {@code long} value, -2<sup>63</sup>. - * - * @since Android 1.0 */ public static final long MIN_VALUE = 0x8000000000000000L; /** * The {@link Class} object that represents the primitive type {@code long}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final Class<Long> TYPE = (Class<Long>) new long[0].getClass() @@ -67,8 +60,8 @@ public final class Long extends Number implements Comparable<Long> { /** * Constant for the number of bits needed to represent a {@code long} in * two's complement form. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int SIZE = 64; @@ -78,7 +71,6 @@ public final class Long extends Number implements Comparable<Long> { * * @param value * the primitive long value to store in the new instance. - * @since Android 1.0 */ public Long(long value) { this.value = value; @@ -92,7 +84,6 @@ public final class Long extends Number implements Comparable<Long> { * @throws NumberFormatException * if {@code string} can not be decoded into a long value. * @see #parseLong(String) - * @since Android 1.0 */ public Long(String string) throws NumberFormatException { this(parseLong(string)); @@ -114,7 +105,7 @@ public final class Long extends Number implements Comparable<Long> { * {@code object} are equal; a positive value if the value of this * long is greater than the value of {@code object}. * @see java.lang.Comparable - * @since Android 1.0 + * @since 1.2 */ public int compareTo(Long object) { return value > object.value ? 1 : (value < object.value ? -1 : 0); @@ -131,7 +122,6 @@ public final class Long extends Number implements Comparable<Long> { * @return a {@code Long} containing the value represented by {@code string}. * @throws NumberFormatException * if {@code string} can not be parsed as a long value. - * @since Android 1.0 */ public static Long decode(String string) throws NumberFormatException { int length = string.length(), i = 0; @@ -187,7 +177,6 @@ public final class Long extends Number implements Comparable<Long> { * the object to compare this long with. * @return {@code true} if the specified object is equal to this * {@code Long}; {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object o) { @@ -209,7 +198,6 @@ public final class Long extends Number implements Comparable<Long> { * @param string * the name of the requested system property. * @return the requested property's value as a {@code Long} or {@code null}. - * @since Android 1.0 */ public static Long getLong(String string) { if (string == null || string.length() == 0) { @@ -239,7 +227,6 @@ public final class Long extends Number implements Comparable<Long> { * property with the requested name. * @return the requested property's value as a {@code Long} or the default * value. - * @since Android 1.0 */ public static Long getLong(String string, long defaultValue) { if (string == null || string.length() == 0) { @@ -269,7 +256,6 @@ public final class Long extends Number implements Comparable<Long> { * property with the requested name. * @return the requested property's value as a {@code Long} or the default * value. - * @since Android 1.0 */ public static Long getLong(String string, Long defaultValue) { if (string == null || string.length() == 0) { @@ -300,7 +286,6 @@ public final class Long extends Number implements Comparable<Long> { * Gets the primitive value of this long. * * @return this object's primitive value. - * @since Android 1.0 */ @Override public long longValue() { @@ -317,7 +302,6 @@ public final class Long extends Number implements Comparable<Long> { * @throws NumberFormatException * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a long value. - * @since Android 1.0 */ public static long parseLong(String string) throws NumberFormatException { return parseLong(string, 10); @@ -338,7 +322,6 @@ public final class Long extends Number implements Comparable<Long> { * {@code radix < Character.MIN_RADIX}, * {@code radix > Character.MAX_RADIX}, or if {@code string} * can not be parsed as a long value. - * @since Android 1.0 */ public static long parseLong(String string, int radix) throws NumberFormatException { @@ -397,7 +380,6 @@ public final class Long extends Number implements Comparable<Long> { * @param l * the long value to convert. * @return the binary string representation of {@code l}. - * @since Android 1.0 */ public static String toBinaryString(long l) { int count = 1; @@ -427,7 +409,6 @@ public final class Long extends Number implements Comparable<Long> { * @param l * the long value to convert. * @return the hexadecimal string representation of {@code l}. - * @since Android 1.0 */ public static String toHexString(long l) { int count = 1; @@ -462,7 +443,6 @@ public final class Long extends Number implements Comparable<Long> { * @param l * the long value to convert. * @return the octal string representation of {@code l}. - * @since Android 1.0 */ public static String toOctalString(long l) { int count = 1; @@ -497,8 +477,7 @@ public final class Long extends Number implements Comparable<Long> { * @param l * the long to convert. * @return the decimal string representation of {@code l}. - * @since Android 1.0 - */ + */ public static String toString(long l) { return toString(l, 10); } @@ -516,7 +495,6 @@ public final class Long extends Number implements Comparable<Long> { * @param radix * the base to use for the conversion. * @return the string representation of {@code l}. - * @since Android 1.0 */ public static String toString(long l, int radix) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { @@ -564,7 +542,6 @@ public final class Long extends Number implements Comparable<Long> { * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a long value. * @see #parseLong(String) - * @since Android 1.0 */ public static Long valueOf(String string) throws NumberFormatException { return valueOf(parseLong(string)); @@ -586,7 +563,6 @@ public final class Long extends Number implements Comparable<Long> { * {@code radix > Character.MAX_RADIX}, or if {@code string} * can not be parsed as a long value. * @see #parseLong(String, int) - * @since Android 1.0 */ public static Long valueOf(String string, int radix) throws NumberFormatException { @@ -602,7 +578,7 @@ public final class Long extends Number implements Comparable<Long> { * @param lng * the long to examine. * @return the bit mask indicating the highest 1 bit in {@code lng}. - * @since Android 1.0 + * @since 1.5 */ public static long highestOneBit(long lng) { lng |= (lng >> 1); @@ -623,7 +599,7 @@ public final class Long extends Number implements Comparable<Long> { * @param lng * the long to examine. * @return the bit mask indicating the lowest 1 bit in {@code lng}. - * @since Android 1.0 + * @since 1.5 */ public static long lowestOneBit(long lng) { return (lng & (-lng)); @@ -632,11 +608,11 @@ public final class Long extends Number implements Comparable<Long> { /** * Determines the number of leading zeros in the specified long value prior * to the {@link #highestOneBit(long) highest one bit}. - * + * * @param lng * the long to examine. * @return the number of leading zeros in {@code lng}. - * @since Android 1.0 + * @since 1.5 */ public static int numberOfLeadingZeros(long lng) { lng |= lng >> 1; @@ -651,11 +627,11 @@ public final class Long extends Number implements Comparable<Long> { /** * Determines the number of trailing zeros in the specified long value after * the {@link #lowestOneBit(long) lowest one bit}. - * + * * @param lng * the long to examine. * @return the number of trailing zeros in {@code lng}. - * @since Android 1.0 + * @since 1.5 */ public static int numberOfTrailingZeros(long lng) { return bitCount((lng & -lng) - 1); @@ -664,11 +640,11 @@ public final class Long extends Number implements Comparable<Long> { /** * Counts the number of 1 bits in the specified long value; this is also * referred to as population count. - * + * * @param lng * the long to examine. * @return the number of 1 bits in {@code lng}. - * @since Android 1.0 + * @since 1.5 */ public static int bitCount(long lng) { lng = (lng & 0x5555555555555555L) + ((lng >> 1) & 0x5555555555555555L); @@ -684,13 +660,13 @@ public final class Long extends Number implements Comparable<Long> { /** * Rotates the bits of the specified long value to the left by the specified * number of bits. - * + * * @param lng * the long value to rotate left. * @param distance * the number of bits to rotate. * @return the rotated value. - * @since Android 1.0 + * @since 1.5 */ public static long rotateLeft(long lng, int distance) { if (distance == 0) { @@ -705,15 +681,16 @@ public final class Long extends Number implements Comparable<Long> { } /** + * <p> * Rotates the bits of the specified long value to the right by the * specified number of bits. - * + * * @param lng * the long value to rotate right. * @param distance * the number of bits to rotate. * @return the rotated value. - * @since Android 1.0 + * @since 1.5 */ public static long rotateRight(long lng, int distance) { if (distance == 0) { @@ -733,7 +710,7 @@ public final class Long extends Number implements Comparable<Long> { * @param lng * the long value for which to reverse the byte order. * @return the reversed value. - * @since Android 1.0 + * @since 1.5 */ public static long reverseBytes(long lng) { long b7 = lng >>> 56; @@ -753,7 +730,7 @@ public final class Long extends Number implements Comparable<Long> { * @param lng * the long value for which to reverse the bit order. * @return the reversed value. - * @since Android 1.0 + * @since 1.5 */ public static long reverse(long lng) { // From Hacker's Delight, 7-1, Figure 7-1 @@ -774,7 +751,7 @@ public final class Long extends Number implements Comparable<Long> { * the long value to check. * @return -1 if {@code lng} is negative, 1 if {@code lng} is positive, 0 if * {@code lng} is zero. - * @since Android 1.0 + * @since 1.5 */ public static int signum(long lng) { return (lng == 0 ? 0 : (lng < 0 ? -1 : 1)); @@ -786,12 +763,11 @@ public final class Long extends Number implements Comparable<Long> { * If it is not necessary to get a new {@code Long} instance, it is * recommended to use this method instead of the constructor, since it * maintains a cache of instances which may result in better performance. - * </p> - * + * * @param lng * the long value to store in the instance. * @return a {@code Long} instance containing {@code lng}. - * @since Android 1.0 + * @since 1.5 */ public static Long valueOf(long lng) { if (lng < -128 || lng > 127) { @@ -804,7 +780,6 @@ public final class Long extends Number implements Comparable<Long> { /** * <p> * A cache of instances used by {@link Long#valueOf(long)} and auto-boxing. - * </p> */ static final Long[] CACHE = new Long[256]; diff --git a/luni/src/main/java/java/lang/Math.java b/luni/src/main/java/java/lang/Math.java index f18f40f..998856a 100644 --- a/luni/src/main/java/java/lang/Math.java +++ b/luni/src/main/java/java/lang/Math.java @@ -17,26 +17,21 @@ package java.lang; + /** * Class Math provides basic math constants and operations such as trigonometric * functions, hyperbolic functions, exponential, logarithms, etc. - * - * @since Android 1.0 */ public final class Math { /** * The double value closest to e, the base of the natural logarithm. - * - * @since Android 1.0 */ public static final double E = 2.718281828459045; /** * The double value closest to pi, the ratio of a circle's circumference to * its diameter. - * - * @since Android 1.0 */ public static final double PI = 3.141592653589793; @@ -58,18 +53,16 @@ public final class Math { * <li>{@code abs(-infinity) = +infinity}</li> * <li>{@code abs(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose absolute value has to be computed. * @return the absolute value of the argument. - * @since Android 1.0 */ - 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. @@ -81,50 +74,45 @@ public final class Math { * <li>{@code abs(-infinity) = +infinity}</li> * <li>{@code abs(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param f * the value whose absolute value has to be computed. * @return the argument if it is positive, otherwise the negation of the * argument. - * @since Android 1.0 */ - 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. - * </p> - * + * * @param i * the value whose absolute value has to be computed. * @return the argument if it is positive, otherwise the negation of the * argument. - * @since Android 1.0 */ - 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. - * @since Android 1.0 */ - 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 @@ -137,14 +125,12 @@ public final class Math { * <li>{@code acos((anything < -1) = NaN}</li> * <li>{@code acos(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value to compute arc cosine of. * @return the arc cosine of the argument. - * @since Android 1.0 */ - 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 @@ -157,14 +143,12 @@ public final class Math { * <li>{@code asin((anything < -1)) = NaN}</li> * <li>{@code asin(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose arc sine has to be computed. * @return the arc sine of the argument. - * @since Android 1.0 */ - 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 @@ -179,12 +163,10 @@ public final class Math { * <li>{@code atan(-infinity) = -pi/2}</li> * <li>{@code atan(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose arc tangent has to be computed. * @return the arc tangent of the argument. - * @since Android 1.0 */ public static native double atan(double d); @@ -219,19 +201,14 @@ public final class Math { * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))} * {@code =} {@code -pi/2}</li> * </ul> - * </p> - * + * * @param y * the numerator of the value whose atan has to be computed. * @param x * the denominator of the value whose atan has to be computed. * @return the arc tangent of {@code y/x}. - * @since Android 1.0 */ - public static native double atan2(double y, double x); - // BEGIN android-note - // parameter names changed from d1 / d2 to x / y - // END android-note + public static native double atan2(double x, double y); /** * Returns the closest double approximation of the cube root of the @@ -245,12 +222,10 @@ public final class Math { * <li>{@code cbrt(-infinity) = -infinity}</li> * <li>{@code cbrt(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose cube root has to be computed. * @return the cube root of the argument. - * @since Android 1.0 */ public static native double cbrt(double d); @@ -267,16 +242,14 @@ public final class Math { * <li>{@code ceil(-infinity) = -infinity}</li> * <li>{@code ceil(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose closest integer value has to be computed. * @return the ceiling of the argument. - * @since Android 1.0 */ public static native double ceil(double d); - /** + /** * 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. @@ -287,15 +260,13 @@ public final class Math { * <li>{@code cos(-infinity) = NaN}</li> * <li>{@code cos(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the angle whose cosine has to be computed, in radians. * @return the cosine of the argument. - * @since Android 1.0 */ public static native double cos(double d); - + /** * Returns the closest double approximation of the hyperbolic cosine of the * argument. The returned result is within 2.5 ulps (units in the last @@ -307,12 +278,10 @@ public final class Math { * <li>{@code cosh(-infinity) = +infinity}</li> * <li>{@code cosh(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose hyperbolic cosine has to be computed. * @return the hyperbolic cosine of the argument. - * @since Android 1.0 */ public static native double cosh(double d); @@ -327,15 +296,13 @@ public final class Math { * <li>{@code exp(-infinity) = +0.0}</li> * <li>{@code exp(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose exponential has to be computed. * @return the exponential of the argument. - * @since Android 1.0 */ 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 @@ -354,14 +321,12 @@ public final class Math { * <li>{@code expm1(-infinity) = -1.0}</li> * <li>{@code expm1(NaN) = NaN}</li> * </ul> - * </p> - * + * * @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. - * @since Android 1.0 */ public static native double expm1(double d); @@ -377,20 +342,19 @@ public final class Math { * <li>{@code floor(-infinity) = -infinity}</li> * <li>{@code floor(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose closest integer value has to be computed. * @return the floor of the argument. - * @since Android 1.0 */ public static native double floor(double d); - + /** * 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. + * (unit in the last place) of the real result. If one parameter remains + * constant, the result should be semi-monotonic. * <p> * Special cases: * <ul> @@ -400,8 +364,7 @@ public final class Math { * <li>{@code hypot((anything including NaN), -infinity) = +infinity}</li> * <li>{@code hypot(NaN, NaN) = NaN}</li> * </ul> - * </p> - * + * * @param x * a double number. * @param y @@ -409,7 +372,6 @@ public final class Math { * @return the {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} * <i> {@code y}</i><sup>{@code 2}</sup>{@code )} value of the * arguments. - * @since Android 1.0 */ public static native double hypot(double x, double y); @@ -431,19 +393,14 @@ public final class Math { * <li>{@code IEEEremainder(x, -infinity) = x } where x is anything but * +/-infinity</li> * </ul> - * </p> - * + * * @param x * the numerator of the operation. * @param y * the denominator of the operation. * @return the IEEE754 floating point reminder of of {@code x/y}. - * @since Android 1.0 */ public static native double IEEEremainder(double x, double y); - // BEGIN android-note - // parameter names changed from d1 / d2 to x / y - // END android-note /** * Returns the closest double approximation of the natural logarithm of the @@ -459,12 +416,10 @@ public final class Math { * <li>{@code log(-infinity) = NaN}</li> * <li>{@code log(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose log has to be computed. * @return the natural logarithm of the argument. - * @since Android 1.0 */ public static native double log(double d); @@ -482,21 +437,19 @@ public final class Math { * <li>{@code log10(-infinity) = NaN}</li> * <li>{@code log10(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose base 10 log has to be computed. * @return the natural logarithm of the argument. - * @since Android 1.0 */ public static native double log10(double d); - + /** * Returns the closest double approximation of the natural logarithm of the * sum of the argument and 1. If the argument is very close to 0, it is much * more accurate to use {@code log1p(d)} than {@code log(1.0+d)} (due to * numerical cancellation). The returned result is within 1 ulp (unit in the - * last place) of the real result. + * last place) of the real result and is semi-monotonic. * <p> * Special cases: * <ul> @@ -508,12 +461,10 @@ public final class Math { * <li>{@code log1p(-infinity) = NaN}</li> * <li>{@code log1p(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value to compute the {@code ln(1+d)} of. * @return the natural logarithm of the sum of the argument and 1. - * @since Android 1.0 */ public static native double log1p(double d); @@ -528,29 +479,34 @@ 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> - * </p> - * + * * @param d1 * the first argument. * @param d2 * the second argument. * @return the larger of {@code d1} and {@code d2}. - * @since Android 1.0 */ - public static double max(double d1, double d2) { - if (d1 > d2) + public static double max(double d1, double d2) { + // BEGIN android-changed + // copied from a newer version of Harmony + if (d1 > d2) { return d1; - if (d1 < d2) + } + if (d1 < d2) { return d2; + } /* if either arg is NaN, return NaN */ - if (d1 != d2) + if (d1 != d2) { return Double.NaN; - /* max( +0.0,-0.0) == +0.0 */ - if (d1 == 0.0 - && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0) - return 0.0; - return d1; - } + } + /* max(+0.0,-0.0) == +0.0 */ + /* 0 == Double.doubleToRawLongBits(0.0d) */ + if (Double.doubleToRawLongBits(d1) != 0) { + return d2; + } + return 0.0d; + // END android-changed + } /** * Returns the most positive (closest to positive infinity) of the two @@ -563,59 +519,62 @@ 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> - * </p> - * + * * @param f1 * the first argument. * @param f2 * the second argument. * @return the larger of {@code f1} and {@code f2}. - * @since Android 1.0 */ - public static float max(float f1, float f2) { - if (f1 > f2) + public static float max(float f1, float f2) { + // BEGIN android-changed + // copied from a newer version of Harmony + if (f1 > f2) { return f1; - if (f1 < f2) + } + if (f1 < f2) { return f2; + } /* if either arg is NaN, return NaN */ - if (f1 != f2) + if (f1 != f2) { return Float.NaN; - /* max( +0.0,-0.0) == +0.0 */ - if (f1 == 0.0f - && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0) - return 0.0f; - return f1; - } + } + /* max(+0.0,-0.0) == +0.0 */ + /* 0 == Float.floatToRawIntBits(0.0f) */ + if (Float.floatToRawIntBits(f1) != 0) { + 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}. - * @since Android 1.0 */ - 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}. - * @since Android 1.0 */ - 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 @@ -628,29 +587,34 @@ 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> - * </p> - * + * * @param d1 * the first argument. * @param d2 * the second argument. * @return the smaller of {@code d1} and {@code d2}. - * @since Android 1.0 */ - public static double min(double d1, double d2) { - if (d1 > d2) + public static double min(double d1, double d2) { + // BEGIN android-changed + // copied from a newer version of Harmony + if (d1 > d2) { return d2; - if (d1 < d2) + } + if (d1 < d2) { return d1; + } /* if either arg is NaN, return NaN */ - if (d1 != d2) + if (d1 != d2) { return Double.NaN; - /* min( +0.0,-0.0) == -0.0 */ - if (d1 == 0.0 - && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0) - return 0.0 * (-1.0); - return d1; - } + } + /* min(+0.0,-0.0) == -0.0 */ + /* 0x8000000000000000L == Double.doubleToRawLongBits(-0.0d) */ + if (Double.doubleToRawLongBits(d1) == 0x8000000000000000L) { + return -0.0d; + } + return d2; + // END android-changed + } /** * Returns the most negative (closest to negative infinity) of the two @@ -663,59 +627,62 @@ 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> - * </p> - * + * * @param f1 * the first argument. * @param f2 * the second argument. * @return the smaller of {@code f1} and {@code f2}. - * @since Android 1.0 */ - public static float min(float f1, float f2) { - if (f1 > f2) + public static float min(float f1, float f2) { + // BEGIN android-changed + // copied from a newer version of Harmony + if (f1 > f2) { return f2; - if (f1 < f2) + } + if (f1 < f2) { return f1; + } /* if either arg is NaN, return NaN */ - if (f1 != f2) + if (f1 != f2) { return Float.NaN; - /* min( +0.0,-0.0) == -0.0 */ - if (f1 == 0.0f - && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0) - return 0.0f * (-1.0f); - return f1; - } + } + /* min(+0.0,-0.0) == -0.0 */ + /* 0x80000000 == Float.floatToRawIntBits(-0.0f) */ + if (Float.floatToRawIntBits(f1) == 0x80000000) { + 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}. - * @since Android 1.0 */ - 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}. - * @since Android 1.0 */ - 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 @@ -747,19 +714,14 @@ public final class Math { * {@code pow(-1,(integer))*pow(+anything,integer) }</li> * <li>{@code pow((-anything except 0 and inf), (non-integer)) = NAN}</li> * </ul> - * </p> - * + * * @param x * the base of the operation. * @param y * the exponent of the operation. * @return {@code x} to the power of {@code y}. - * @since Android 1.0 */ public static native double pow(double x, double y); - // BEGIN android-note - // parameter names changed from d1 / d2 to x / y - // END android-note /** * Returns the double conversion of the result of rounding the argument to @@ -773,16 +735,14 @@ public final class Math { * <li>{@code rint(-infinity) = -infinity}</li> * <li>{@code rint(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value to be rounded. * @return the closest integer to the argument (as a double). - * @since Android 1.0 */ public static native double rint(double d); - /** + /** * Returns the result of rounding the argument to an integer. The result is * equivalent to {@code (long) Math.floor(d+0.5)}. * <p> @@ -796,19 +756,17 @@ public final class Math { * <li>{@code round(-infintiy) = Long.MIN_VALUE}</li> * <li>{@code round(NaN) = +0.0}</li> * </ul> - * </p> - * + * * @param d * the value to be rounded. * @return the closest integer to the argument. - * @since Android 1.0 */ - 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 @@ -824,19 +782,17 @@ public final class Math { * <li>{@code round(-infintiy) = Integer.MIN_VALUE}</li> * <li>{@code round(NaN) = +0.0}</li> * </ul> - * </p> - * + * * @param f * the value to be rounded. * @return the closest integer to the argument. - * @since Android 1.0 */ - 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 @@ -852,17 +808,15 @@ public final class Math { * <li>{@code signum(-infinity) = -1.0}</li> * <li>{@code signum(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose signum has to be computed. * @return the value of the signum function. - * @since Android 1.0 */ public static double signum(double d) { return StrictMath.signum(d); } - + /** * Returns the signum function of the argument. If the argument is less than * zero, it returns -1.0. If the argument is greater than zero, 1.0 is @@ -877,12 +831,10 @@ public final class Math { * <li>{@code signum(-infinity) = -1.0}</li> * <li>{@code signum(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param f * the value whose signum has to be computed. * @return the value of the signum function. - * @since Android 1.0 */ public static float signum(float f) { return StrictMath.signum(f); @@ -901,15 +853,13 @@ public final class Math { * <li>{@code sin(-infinity) = NaN}</li> * <li>{@code sin(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the angle whose sin has to be computed, in radians. * @return the sine of the argument. - * @since Android 1.0 */ public static native double sin(double d); - + /** * Returns the closest double approximation of the hyperbolic sine of the * argument. The returned result is within 2.5 ulps (units in the last @@ -923,12 +873,10 @@ public final class Math { * <li>{@code sinh(-infinity) = -infinity}</li> * <li>{@code sinh(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose hyperbolic sine has to be computed. * @return the hyperbolic sine of the argument. - * @since Android 1.0 */ public static native double sinh(double d); @@ -944,12 +892,10 @@ public final class Math { * <li>{@code sqrt(+infinity) = +infinity}</li> * <li>{@code sqrt(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose square root has to be computed. * @return the square root of the argument. - * @since Android 1.0 */ public static native double sqrt(double d); @@ -966,15 +912,13 @@ public final class Math { * <li>{@code tan(-infinity) = NaN}</li> * <li>{@code tan(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the angle whose tangens has to be computed, in radians. * @return the tangent of the argument. - * @since Android 1.0 */ public static native double tan(double d); - + /** * Returns the closest double approximation of the hyperbolic tangent of the * argument. The absolute value is always less than 1. The returned result @@ -990,28 +934,25 @@ public final class Math { * <li>{@code tanh(-infinity) = -1.0}</li> * <li>{@code tanh(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose hyperbolic tangent has to be computed. * @return the hyperbolic tangent of the argument. - * @since Android 1.0 */ public static native double tanh(double d); /** * Returns a pseudo-random number between 0.0 (inclusive) and 1.0 * (exclusive). - * + * * @return a pseudo-random number. - * @since Android 1.0 */ - 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 @@ -1025,16 +966,14 @@ public final class Math { * <li>{@code toRadians(-infinity) = -infinity}</li> * <li>{@code toRadians(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param angdeg * an angle in degrees. * @return the radian measure of the angle. - * @since Android 1.0 */ - 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 @@ -1048,18 +987,16 @@ public final class Math { * <li>{@code toDegrees(-infinity) = -infinity}</li> * <li>{@code toDegrees(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param angrad * an angle in radians. * @return the degree measure of the angle. - * @since Android 1.0 */ - 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}, @@ -1073,12 +1010,10 @@ public final class Math { * <li>{@code ulp(-infintiy) = infinity}</li> * <li>{@code ulp(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the floating-point value to compute ulp of. * @return the size of a ulp of the argument. - * @since Android 1.0 */ public static double ulp(double d) { // special cases @@ -1105,12 +1040,10 @@ public final class Math { * <li>{@code ulp(-infintiy) = infinity}</li> * <li>{@code ulp(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param f * the floating-point value to compute ulp of. * @return the size of a ulp of the argument. - * @since Android 1.0 */ public static float ulp(float f) { // special cases diff --git a/luni/src/main/java/java/lang/NegativeArraySizeException.java b/luni/src/main/java/java/lang/NegativeArraySizeException.java index 1ca7855..50b6929 100644 --- a/luni/src/main/java/java/lang/NegativeArraySizeException.java +++ b/luni/src/main/java/java/lang/NegativeArraySizeException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when an attempt is made to create an array with a size of less than * zero. - * - * @since Android 1.0 */ public class NegativeArraySizeException extends RuntimeException { @@ -30,8 +28,6 @@ public class NegativeArraySizeException extends RuntimeException { /** * Constructs a new {@code NegativeArraySizeException} that includes the * current stack trace. - * - * @since Android 1.0 */ public NegativeArraySizeException() { super(); @@ -43,7 +39,6 @@ public class NegativeArraySizeException extends RuntimeException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NegativeArraySizeException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/NoClassDefFoundError.java b/luni/src/main/java/java/lang/NoClassDefFoundError.java index e23ecc6..9fae360 100644 --- a/luni/src/main/java/java/lang/NoClassDefFoundError.java +++ b/luni/src/main/java/java/lang/NoClassDefFoundError.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when the virtual machine is unable to locate a class which it has been * asked to load. - * - * @since Android 1.0 */ public class NoClassDefFoundError extends LinkageError { @@ -30,8 +28,6 @@ public class NoClassDefFoundError extends LinkageError { /** * Constructs a new {@code NoClassDefFoundError} that includes the current * stack trace. - * - * @since Android 1.0 */ public NoClassDefFoundError() { super(); @@ -43,7 +39,6 @@ public class NoClassDefFoundError extends LinkageError { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public NoClassDefFoundError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/NoSuchFieldError.java b/luni/src/main/java/java/lang/NoSuchFieldError.java index 667d6a5..9b479f6 100644 --- a/luni/src/main/java/java/lang/NoSuchFieldError.java +++ b/luni/src/main/java/java/lang/NoSuchFieldError.java @@ -22,9 +22,6 @@ package java.lang; * on a class or object, a field that does not exist. * <p> * Note that this can only occur when inconsistent class files are being loaded. - * </p> - * - * @since Android 1.0 */ public class NoSuchFieldError extends IncompatibleClassChangeError { @@ -33,8 +30,6 @@ public class NoSuchFieldError extends IncompatibleClassChangeError { /** * Constructs a new {@code NoSuchFieldError} that includes the current stack * trace. - * - * @since Android 1.0 */ public NoSuchFieldError() { super(); @@ -46,7 +41,6 @@ public class NoSuchFieldError extends IncompatibleClassChangeError { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public NoSuchFieldError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/NoSuchFieldException.java b/luni/src/main/java/java/lang/NoSuchFieldException.java index 31a566d..283bfab 100644 --- a/luni/src/main/java/java/lang/NoSuchFieldException.java +++ b/luni/src/main/java/java/lang/NoSuchFieldException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when the virtual machine notices that a program tries to reference, * on a class or object, a field that does not exist. - * - * @since Android 1.0 */ public class NoSuchFieldException extends java.lang.Exception { @@ -30,8 +28,6 @@ public class NoSuchFieldException extends java.lang.Exception { /** * Constructs a new {@code NoSuchFieldException} that includes the current * stack trace. - * - * @since Android 1.0 */ public NoSuchFieldException() { super(); @@ -43,7 +39,6 @@ public class NoSuchFieldException extends java.lang.Exception { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NoSuchFieldException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/NoSuchMethodError.java b/luni/src/main/java/java/lang/NoSuchMethodError.java index a72f76b..91ed06c 100644 --- a/luni/src/main/java/java/lang/NoSuchMethodError.java +++ b/luni/src/main/java/java/lang/NoSuchMethodError.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when the virtual machine notices that a program tries to reference, * on a class or object, a method that does not exist. - * - * @since Android 1.0 */ public class NoSuchMethodError extends IncompatibleClassChangeError { @@ -30,8 +28,6 @@ public class NoSuchMethodError extends IncompatibleClassChangeError { /** * Constructs a new {@code NoSuchMethodError} that includes the current * stack trace. - * - * @since Android 1.0 */ public NoSuchMethodError() { super(); @@ -43,7 +39,6 @@ public class NoSuchMethodError extends IncompatibleClassChangeError { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NoSuchMethodError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/NoSuchMethodException.java b/luni/src/main/java/java/lang/NoSuchMethodException.java index bd3cf01..cf4dbe0 100644 --- a/luni/src/main/java/java/lang/NoSuchMethodException.java +++ b/luni/src/main/java/java/lang/NoSuchMethodException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when the virtual machine notices that a program tries to reference, * on a class or object, a method that does not exist. - * - * @since Android 1.0 */ public class NoSuchMethodException extends java.lang.Exception { @@ -30,8 +28,6 @@ public class NoSuchMethodException extends java.lang.Exception { /** * Constructs a new {@code NoSuchMethodException} that includes the current * stack trace. - * - * @since Android 1.0 */ public NoSuchMethodException() { super(); @@ -43,7 +39,6 @@ public class NoSuchMethodException extends java.lang.Exception { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NoSuchMethodException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/NullPointerException.java b/luni/src/main/java/java/lang/NullPointerException.java index d11b282..90e9e50 100644 --- a/luni/src/main/java/java/lang/NullPointerException.java +++ b/luni/src/main/java/java/lang/NullPointerException.java @@ -23,8 +23,6 @@ package java.lang; * object or array points to {@code null}. It also occurs in some other, less * obvious circumstances, like a {@code throw e} statement where the {@link * Throwable} reference is {@code null}. - * - * @since Android 1.0 */ public class NullPointerException extends RuntimeException { @@ -33,8 +31,6 @@ public class NullPointerException extends RuntimeException { /** * Constructs a new {@code NullPointerException} that includes the current * stack trace. - * - * @since Android 1.0 */ public NullPointerException() { super(); @@ -46,7 +42,6 @@ public class NullPointerException extends RuntimeException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NullPointerException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/Number.java b/luni/src/main/java/java/lang/Number.java index dc868cb..4fb5596 100644 --- a/luni/src/main/java/java/lang/Number.java +++ b/luni/src/main/java/java/lang/Number.java @@ -22,8 +22,6 @@ package java.lang; * The abstract superclass of the classes which represent numeric base types * (that is {@link Byte}, {@link Short}, {@link Integer}, {@link Long}, * {@link Float}, and {@link Double}. - * - * @since Android 1.0 */ public abstract class Number implements java.io.Serializable { @@ -31,8 +29,6 @@ public abstract class Number implements java.io.Serializable { /** * Empty default constructor. - * - * @since Android 1.0 */ public Number() { } @@ -42,7 +38,6 @@ public abstract class Number implements java.io.Serializable { * truncating the value, so it fits into a byte. * * @return the primitive byte value of this object. - * @since Android 1.0 */ public byte byteValue() { return (byte) intValue(); @@ -52,7 +47,6 @@ public abstract class Number implements java.io.Serializable { * Returns this object's value as a double. Might involve rounding. * * @return the primitive double value of this object. - * @since Android 1.0 */ public abstract double doubleValue(); @@ -60,7 +54,6 @@ public abstract class Number implements java.io.Serializable { * Returns this object's value as a float. Might involve rounding. * * @return the primitive float value of this object. - * @since Android 1.0 */ public abstract float floatValue(); @@ -69,7 +62,6 @@ public abstract class Number implements java.io.Serializable { * truncating the value, so it fits into an int. * * @return the primitive int value of this object. - * @since Android 1.0 */ public abstract int intValue(); @@ -78,7 +70,6 @@ public abstract class Number implements java.io.Serializable { * truncating the value, so it fits into a long. * * @return the primitive long value of this object. - * @since Android 1.0 */ public abstract long longValue(); @@ -87,7 +78,6 @@ public abstract class Number implements java.io.Serializable { * truncating the value, so it fits into a short. * * @return the primitive short value of this object. - * @since Android 1.0 */ public short shortValue() { return (short) intValue(); diff --git a/luni/src/main/java/java/lang/NumberFormatException.java b/luni/src/main/java/java/lang/NumberFormatException.java index ed5433d..9d2f0c7 100644 --- a/luni/src/main/java/java/lang/NumberFormatException.java +++ b/luni/src/main/java/java/lang/NumberFormatException.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when an invalid value is passed to a string-to-number conversion * method. - * - * @since Android 1.0 */ public class NumberFormatException extends java.lang.IllegalArgumentException { @@ -30,8 +28,6 @@ public class NumberFormatException extends java.lang.IllegalArgumentException { /** * Constructs a new {@code NumberFormatException} that includes the current * stack trace. - * - * @since Android 1.0 */ public NumberFormatException() { super(); @@ -43,7 +39,6 @@ public class NumberFormatException extends java.lang.IllegalArgumentException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NumberFormatException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/OutOfMemoryError.java b/luni/src/main/java/java/lang/OutOfMemoryError.java index 2c54ad1..a8f8a2c 100644 --- a/luni/src/main/java/java/lang/OutOfMemoryError.java +++ b/luni/src/main/java/java/lang/OutOfMemoryError.java @@ -21,8 +21,6 @@ package java.lang; * Thrown when a request for memory is made that can not be satisfied using the * available platform resources. Such a request may be made by both the running * application or by an internal function of the virtual machine. - * - * @since Android 1.0 */ public class OutOfMemoryError extends java.lang.VirtualMachineError { @@ -31,8 +29,6 @@ public class OutOfMemoryError extends java.lang.VirtualMachineError { /** * Constructs a new {@code OutOfMemoryError} that includes the current stack * trace. - * - * @since Android 1.0 */ public OutOfMemoryError() { super(); @@ -44,7 +40,6 @@ public class OutOfMemoryError extends java.lang.VirtualMachineError { * * @param detailMessage * the detail message for this error. - * @since Android 1.0 */ public OutOfMemoryError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/Override.java b/luni/src/main/java/java/lang/Override.java index 864357d..c4049cb 100644 --- a/luni/src/main/java/java/lang/Override.java +++ b/luni/src/main/java/java/lang/Override.java @@ -1,12 +1,12 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed 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 - * +/* 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. @@ -16,19 +16,19 @@ package java.lang; -import java.lang.annotation.Target; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** - * Annotation type used to mark methods that override a method declaration in a superclass. - * Compilers produce an error if a method annotated with @Override does not actually override - * a method in a superclass. - * - * @since Android 1.0 + * Annotation type used to mark methods that override a method declaration in a + * superclass. Compilers produce an error if a method annotated with @Override + * does not actually override a method in a superclass. + * + * @since 1.5 */ -@Retention(value=java.lang.annotation.RetentionPolicy.SOURCE) -@Target(value=java.lang.annotation.ElementType.METHOD) -public @interface Override -{ - +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface Override { } diff --git a/luni/src/main/java/java/lang/Process.java b/luni/src/main/java/java/lang/Process.java index 5fe8be7..c030fcc 100644 --- a/luni/src/main/java/java/lang/Process.java +++ b/luni/src/main/java/java/lang/Process.java @@ -17,25 +17,20 @@ package java.lang; - import java.io.InputStream; import java.io.OutputStream; /** * Represents an external process. Enables writing to, reading from, destroying, * and waiting for the external process, as well as querying its exit value. - * + * * @see Runtime#exec * @see ProcessBuilder#start() - * - * @since Android 1.0 */ public abstract class Process { /** * Terminates this process and closes any associated streams. - * - * @since Android 1.0 */ abstract public void destroy(); @@ -46,7 +41,6 @@ public abstract class Process { * @return the exit value of this process. * @throws IllegalThreadStateException * if this process has not terminated. - * @since Android 1.0 */ abstract public int exitValue(); @@ -56,7 +50,6 @@ public abstract class Process { * * @return the input stream to read from the error stream associated with * the native process. - * @since Android 1.0 */ abstract public InputStream getErrorStream(); @@ -66,7 +59,6 @@ public abstract class Process { * * @return the input stream to read from the output stream associated with * the native process. - * @since Android 1.0 */ abstract public InputStream getInputStream(); @@ -76,7 +68,6 @@ public abstract class Process { * * @return the output stream to write to the input stream associated with * the native process. - * @since Android 1.0 */ abstract public OutputStream getOutputStream(); @@ -87,7 +78,6 @@ public abstract class Process { * @return the exit value of the native process being waited on. * @throws InterruptedException * if the calling thread is interrupted. - * @since Android 1.0 */ abstract public int waitFor() throws InterruptedException; } diff --git a/luni/src/main/java/java/lang/ProcessBuilder.java b/luni/src/main/java/java/lang/ProcessBuilder.java index 9d6b90b..f649fec 100644 --- a/luni/src/main/java/java/lang/ProcessBuilder.java +++ b/luni/src/main/java/java/lang/ProcessBuilder.java @@ -24,8 +24,8 @@ import java.util.Map; /** * Creates operating system processes. - * - * @since Android 1.0 + * + * @since 1.5 */ public final class ProcessBuilder { @@ -40,10 +40,9 @@ public final class ProcessBuilder { /** * Constructs a new {@code ProcessBuilder} instance with the specified * operating system program and its arguments. - * + * * @param command * the requested operating system program and its arguments. - * @since Android 1.0 */ public ProcessBuilder(String... command) { this(toList(command)); @@ -54,12 +53,11 @@ public final class ProcessBuilder { * operating system program and its arguments. Note that the list passed to * this constructor is not copied, so any subsequent updates to it are * reflected in this instance's state. - * + * * @param command * the requested operating system program and its arguments. * @throws NullPointerException * if {@code command} is {@code null}. - * @since Android 1.0 */ public ProcessBuilder(List<String> command) { super(); @@ -76,9 +74,8 @@ public final class ProcessBuilder { * Returns this process builder's current program and arguments. Note that * the returned list is not a copy and modifications to it will change the * state of this instance. - * + * * @return this process builder's program and arguments. - * @since Android 1.0 */ public List<String> command() { return command; @@ -86,11 +83,10 @@ public final class ProcessBuilder { /** * Changes the program and arguments of this process builder. - * + * * @param command * the new operating system program and its arguments. * @return this process builder instance. - * @since Android 1.0 */ public ProcessBuilder command(String... command) { return command(toList(command)); @@ -100,13 +96,12 @@ public final class ProcessBuilder { * Changes the program and arguments of this process builder. Note that the * list passed to this method is not copied, so any subsequent updates to it * are reflected in this instance's state. - * + * * @param command * the new operating system program and its arguments. * @return this process builder instance. * @throws NullPointerException * if {@code command} is {@code null}. - * @since Android 1.0 */ public ProcessBuilder command(List<String> command) { if (command == null) { @@ -120,9 +115,8 @@ public final class ProcessBuilder { * Returns the working directory of this process builder. If {@code null} is * returned, then the working directory of the Java process is used when a * process is started. - * + * * @return the current working directory, may be {@code null}. - * @since Android 1.0 */ public File directory() { return directory; @@ -132,11 +126,10 @@ public final class ProcessBuilder { * Changes the working directory of this process builder. If the specified * directory is {@code null}, then the working directory of the Java * process is used when a process is started. - * + * * @param directory * the new working directory for this process builder. * @return this process builder instance. - * @since Android 1.0 */ public ProcessBuilder directory(File directory) { this.directory = directory; @@ -149,9 +142,8 @@ public final class ProcessBuilder { * the environment, as returned by {@link System#getenv()}. Note that the * map returned by this method is not a copy and any changes made to it are * reflected in this instance's state. - * + * * @return the map containing this process builder's environment variables. - * @since Android 1.0 */ public Map<String, String> environment() { return environment; @@ -162,10 +154,9 @@ public final class ProcessBuilder { * output. If redirected, the {@link Process#getErrorStream()} will always * return end of stream and standard error is written to * {@link Process#getInputStream()}. - * + * * @return {@code true} if the standard error is redirected; {@code false} * otherwise. - * @since Android 1.0 */ public boolean redirectErrorStream() { return redirectErrorStream; @@ -174,12 +165,11 @@ public final class ProcessBuilder { /** * Changes the state of whether or not standard error is redirected to * standard output. - * + * * @param redirectErrorStream * {@code true} to redirect standard error, {@code false} * otherwise. * @return this process builder instance. - * @since Android 1.0 */ public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) { this.redirectErrorStream = redirectErrorStream; @@ -188,7 +178,7 @@ public final class ProcessBuilder { /** * Starts a new process based on the current state of this process builder. - * + * * @return the new {@code Process} instance. * @throws NullPointerException * if any of the elements of {@link #command()} is {@code null}. @@ -199,7 +189,6 @@ public final class ProcessBuilder { * process creation. * @throws IOException * if an I/O error happens. - * @since Android 1.0 */ public Process start() throws IOException { if (command.isEmpty()) { diff --git a/luni/src/main/java/java/lang/Readable.java b/luni/src/main/java/java/lang/Readable.java index 1eca6cc..b536f59 100644 --- a/luni/src/main/java/java/lang/Readable.java +++ b/luni/src/main/java/java/lang/Readable.java @@ -22,8 +22,6 @@ import java.nio.CharBuffer; /** * Represents a sequence of characters that can be incrementally read (copied) * into a {@link CharBuffer}. - * - * @since Android 1.0 */ public interface Readable { @@ -37,7 +35,6 @@ public interface Readable { * {@code Readable} reaches its end * @throws IOException * if an I/O error occurs. - * @since Android 1.0 */ int read(CharBuffer cb) throws IOException; } diff --git a/luni/src/main/java/java/lang/Runnable.java b/luni/src/main/java/java/lang/Runnable.java index 2cca717..b09d914 100644 --- a/luni/src/main/java/java/lang/Runnable.java +++ b/luni/src/main/java/java/lang/Runnable.java @@ -21,8 +21,6 @@ package java.lang; /** * Represents a command that can be executed. Often used to run code in a * different {@link Thread}. - * - * @since Android 1.0 */ public interface Runnable { @@ -30,8 +28,6 @@ public interface Runnable { * Starts executing the active part of the class' code. This method is * called when a thread is started that has been created with a class which * implements {@code Runnable}. - * - * @since Android 1.0 */ public void run(); } diff --git a/luni/src/main/java/java/lang/RuntimeException.java b/luni/src/main/java/java/lang/RuntimeException.java index e519bf1..9229b0c 100644 --- a/luni/src/main/java/java/lang/RuntimeException.java +++ b/luni/src/main/java/java/lang/RuntimeException.java @@ -23,8 +23,6 @@ package java.lang; * the virtual machine. Unlike checked exceptions (exceptions where the type * doesn't extend {@code RuntimeException} or {@link Error}), the compiler does * not require code to handle runtime exceptions. - * - * @since Android 1.0 */ public class RuntimeException extends Exception { @@ -33,8 +31,6 @@ public class RuntimeException extends Exception { /** * Constructs a new {@code RuntimeException} that includes the current stack * trace. - * - * @since Android 1.0 */ public RuntimeException() { super(); @@ -46,7 +42,6 @@ public class RuntimeException extends Exception { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public RuntimeException(String detailMessage) { super(detailMessage); @@ -60,7 +55,6 @@ public class RuntimeException extends Exception { * the detail message for this exception. * @param throwable * the cause of this exception. - * @since Android 1.0 */ public RuntimeException(String detailMessage, Throwable throwable) { super(detailMessage, throwable); @@ -72,7 +66,6 @@ public class RuntimeException extends Exception { * * @param throwable * the cause of this exception. - * @since Android 1.0 */ public RuntimeException(Throwable throwable) { super(throwable); diff --git a/luni/src/main/java/java/lang/RuntimePermission.java b/luni/src/main/java/java/lang/RuntimePermission.java index 0f856a0..ba7e665 100644 --- a/luni/src/main/java/java/lang/RuntimePermission.java +++ b/luni/src/main/java/java/lang/RuntimePermission.java @@ -23,8 +23,6 @@ import java.security.BasicPermission; * Represents the permission to execute a runtime-related function. There is no * action list associated with a {@code RuntimePermission}; the user either has * the permission or he doesn't. - * - * @since Android 1.0 */ public final class RuntimePermission extends BasicPermission { @@ -83,7 +81,6 @@ public final class RuntimePermission extends BasicPermission { * * @param permissionName * the name of the new permission. - * @since Android 1.0 */ public RuntimePermission(String permissionName) { super(permissionName); @@ -97,7 +94,6 @@ public final class RuntimePermission extends BasicPermission { * the name of the new permission. * @param actions * ignored. - * @since Android 1.0 */ public RuntimePermission(String name, String actions) { super(name, actions); diff --git a/luni/src/main/java/java/lang/SecurityException.java b/luni/src/main/java/java/lang/SecurityException.java index 7387088..c977be0 100644 --- a/luni/src/main/java/java/lang/SecurityException.java +++ b/luni/src/main/java/java/lang/SecurityException.java @@ -19,8 +19,6 @@ package java.lang; /** * Thrown when a security manager check fails. - * - * @since Android 1.0 */ public class SecurityException extends java.lang.RuntimeException { @@ -29,8 +27,6 @@ public class SecurityException extends java.lang.RuntimeException { /** * Constructs a new {@code SecurityException} that includes the current * stack trace. - * - * @since Android 1.0 */ public SecurityException() { super(); @@ -42,7 +38,6 @@ public class SecurityException extends java.lang.RuntimeException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public SecurityException(String detailMessage) { super(detailMessage); @@ -56,7 +51,7 @@ public class SecurityException extends java.lang.RuntimeException { * the detail message for this exception. * @param cause * the optional cause of this exception, may be {@code null}. - * @since Android 1.0 + * @since 1.5 */ public SecurityException(String message, Throwable cause) { super(message, cause); @@ -68,7 +63,7 @@ public class SecurityException extends java.lang.RuntimeException { * * @param cause * the optional cause of this exception, may be {@code null}. - * @since Android 1.0 + * @since 1.5 */ public SecurityException(Throwable cause) { super((cause == null ? null : cause.toString()), cause); diff --git a/luni/src/main/java/java/lang/SecurityManager.java b/luni/src/main/java/java/lang/SecurityManager.java index dc624e3..9125850 100644 --- a/luni/src/main/java/java/lang/SecurityManager.java +++ b/luni/src/main/java/java/lang/SecurityManager.java @@ -49,8 +49,6 @@ import org.apache.harmony.luni.util.PriviAction; * operation is not allowed, then they throw a {@link SecurityException}. The * only exception is {@link #checkTopLevelWindow(Object)}, which returns a * boolean to indicate permission. - * - * @since Android 1.0 */ public class SecurityManager { @@ -63,9 +61,8 @@ public class SecurityManager { /** * Flag to indicate whether a security check is in progress. - * + * * @deprecated Use {@link #checkPermission} - * @since Android 1.0 */ @Deprecated protected boolean inCheck; @@ -75,9 +72,6 @@ public class SecurityManager { * <p> * The {@code RuntimePermission("createSecurityManager")} is checked if a * security manager is installed. - * </p> - * - * @since Android 1.0 */ public SecurityManager() { SecurityManager security = System.getSecurityManager(); @@ -94,7 +88,7 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to accept socket * connections. - * + * * @param host * the address of the host that attempts to connect. * @param port @@ -104,7 +98,6 @@ public class SecurityManager { * @throws SecurityException * if the calling thread is not allowed to accept socket * connections from {@code host} through {@code port}. - * @since Android 1.0 */ public void checkAccept(String host, int port) { if (host == null) { @@ -116,12 +109,11 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to modify the specified * thread. - * + * * @param thread * the thread to access. * @throws SecurityException * if the calling thread is not allowed to access {@code thread}. - * @since Android 1.0 */ public void checkAccess(Thread thread) { // Only worry about system threads. Dead threads have a null group. @@ -134,14 +126,13 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to modify the specified * thread group. - * + * * @param group * the thread group to access. * @throws NullPointerException * if {@code group} is {@code null}. * @throws SecurityException * if the calling thread is not allowed to access {@code group}. - * @since Android 1.0 */ public void checkAccess(ThreadGroup group) { // Only worry about system threads. @@ -157,7 +148,7 @@ public class SecurityManager { * Checks whether the calling thread is allowed to establish socket * connections. A -1 port indicates the caller is trying to resolve the * hostname. - * + * * @param host * the address of the host to connect to. * @param port @@ -167,7 +158,6 @@ public class SecurityManager { * @throws SecurityException * if the calling thread is not allowed to connect to {@code * host} through {@code port}. - * @since Android 1.0 */ public void checkConnect(String host, int port) { if (host == null) { @@ -184,7 +174,7 @@ public class SecurityManager { * Checks whether the specified security context is allowed to establish * socket connections. A -1 port indicates the caller is trying to resolve * the hostname. - * + * * @param host * the address of the host to connect to. * @param port @@ -196,7 +186,6 @@ public class SecurityManager { * @throws SecurityException * if {@code context} is not allowed to connect to {@code host} * through {@code port}. - * @since Android 1.0 */ public void checkConnect(String host, int port, Object context) { // BEGIN android-added @@ -214,11 +203,10 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to create a class loader. - * + * * @throws SecurityException * if the calling thread is not allowed to create a class * loader. - * @since Android 1.0 */ public void checkCreateClassLoader() { checkPermission(RuntimePermission.permissionToCreateClassLoader); @@ -227,12 +215,11 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to delete the file with the * specified name, which should be passed in canonical form. - * + * * @param file * the name of the file to delete. * @throws SecurityException * if the calling thread is not allowed to delete {@code file}. - * @since Android 1.0 */ public void checkDelete(String file) { checkPermission(new FilePermission(file, "delete")); //$NON-NLS-1$ @@ -241,12 +228,11 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to execute the specified * platform specific command. - * + * * @param cmd * the command line to execute. * @throws SecurityException * if the calling thread is not allowed to execute {@code cmd}. - * @since Android 1.0 */ public void checkExec(String cmd) { checkPermission(new FilePermission(new File(cmd).isAbsolute() ? cmd @@ -256,14 +242,13 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to terminate the virtual * machine. - * + * * @param status * the status that the virtual machine returns when it is * terminated. * @throws SecurityException * if the calling thread is not allowed to terminate the virtual * machine with {@code status}. - * @since Android 1.0 */ public void checkExit(int status) { checkPermission(RuntimePermission.permissionToExitVM); @@ -272,12 +257,11 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to load the specified native * library. - * + * * @param libName * the name of the library to load. * @throws SecurityException * if the calling thread is not allowed to load {@code libName}. - * @since Android 1.0 */ public void checkLink(String libName) { if (libName == null) { @@ -289,12 +273,11 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to listen on the specified * port. - * + * * @param port * the port number to check. * @throws SecurityException * if the calling thread is not allowed listen on {@code port}. - * @since Android 1.0 */ public void checkListen(int port) { if (port == 0) { @@ -312,7 +295,7 @@ public class SecurityManager { * reflect API). Due to the nature of the check, overriding implementations * cannot call {@code super.checkMemberAccess()} since the stack would no * longer be of the expected shape. - * + * * @param cls * the class of which members are accessed. * @param type @@ -322,7 +305,6 @@ public class SecurityManager { * @throws SecurityException * if the calling thread is not allowed to access members of * {@code cls}. - * @since Android 1.0 */ public void checkMemberAccess(Class<?> cls, int type) { if (cls == null) { @@ -352,12 +334,11 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to use the specified IP * multicast group address. - * + * * @param maddr * the internet group address to use. * @throws SecurityException * if the calling thread is not allowed to use {@code maddr}. - * @since Android 1.0 */ public void checkMulticast(InetAddress maddr) { checkPermission(new SocketPermission(maddr.getHostAddress(), @@ -367,7 +348,7 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to use the specified IP * multicast group address. - * + * * @param maddr * the internet group address to use. * @param ttl @@ -376,7 +357,6 @@ public class SecurityManager { * @throws SecurityException * if the calling thread is not allowed to use {@code maddr}. * @deprecated use {@link #checkMulticast(java.net.InetAddress)} - * @since Android 1.0 */ @Deprecated public void checkMulticast(InetAddress maddr, byte ttl) { @@ -387,13 +367,12 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to access the specified * package. - * + * * @param packageName * the name of the package to access. * @throws SecurityException * if the calling thread is not allowed to access {@code * packageName}. - * @since Android 1.0 */ public void checkPackageAccess(String packageName) { if (packageName == null) { @@ -408,13 +387,12 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to define new classes in the * specified package. - * + * * @param packageName * the name of the package to add a class to. * @throws SecurityException * if the calling thread is not allowed to add classes to * {@code packageName}. - * @since Android 1.0 */ public void checkPackageDefinition(String packageName) { if (packageName == null) { @@ -459,11 +437,10 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to access the system * properties. - * + * * @throws SecurityException * if the calling thread is not allowed to access system * properties. - * @since Android 1.0 */ public void checkPropertiesAccess() { checkPermission(READ_WRITE_ALL_PROPERTIES_PERMISSION); @@ -472,13 +449,12 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to access a particular * system property. - * + * * @param key * the name of the property to access. * @throws SecurityException * if the calling thread is not allowed to access the {@code * key} system property. - * @since Android 1.0 */ public void checkPropertyAccess(String key) { checkPermission(new PropertyPermission(key, "read")); //$NON-NLS-1$ @@ -487,12 +463,11 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to read from the file with * the specified file descriptor. - * + * * @param fd * the file descriptor of the file to read from. * @throws SecurityException * if the calling thread is not allowed to read from {@code fd}. - * @since Android 1.0 */ public void checkRead(FileDescriptor fd) { if (fd == null) { @@ -504,13 +479,12 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to read from the file with * the specified name, which should be passed in canonical form. - * + * * @param file * the name of the file or directory to read from. * @throws SecurityException * if the calling thread is not allowed to read from {@code * file}. - * @since Android 1.0 */ public void checkRead(String file) { checkPermission(new FilePermission(file, "read")); //$NON-NLS-1$ @@ -519,14 +493,13 @@ public class SecurityManager { /** * Checks whether the given security context is allowed to read from the * file named by the argument, which should be passed in canonical form. - * + * * @param file * the name of the file or directory to check. * @param context * the security context to use for the check. * @throws SecurityException * if {@code context} is not allowed to read from {@code file}. - * @since Android 1.0 */ public void checkRead(String file, Object context) { checkPermission(new FilePermission(file, "read"), context); //$NON-NLS-1$ @@ -535,13 +508,12 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to perform the security * operation named by the target. - * + * * @param target * the name of the operation to perform. * @throws SecurityException * if the calling thread is not allowed to perform * {@code target}. - * @since Android 1.0 */ public void checkSecurityAccess(String target) { checkPermission(new SecurityPermission(target)); @@ -550,11 +522,10 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to set the net object * factories. - * + * * @throws SecurityException * if the calling thread is not allowed to set the net object * factories. - * @since Android 1.0 */ public void checkSetFactory() { checkPermission(RuntimePermission.permissionToSetFactory); @@ -563,14 +534,13 @@ public class SecurityManager { /** * Checks whether the calling thread is trusted to show the specified top * level window. - * + * * @param window * the window to show. * @return {@code true} if the calling thread is allowed to show {@code * window}; {@code false} otherwise. * @throws NullPointerException * if {@code window} is {@code null}. - * @since Android 1.0 */ public boolean checkTopLevelWindow(Object window) { if (window == null) { @@ -597,11 +567,10 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to access the system * clipboard. - * + * * @throws SecurityException * if the calling thread is not allowed to access the system * clipboard. - * @since Android 1.0 */ public void checkSystemClipboardAccess() { try { @@ -623,11 +592,10 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to access the AWT event * queue. - * + * * @throws SecurityException * if the calling thread is not allowed to access the AWT event * queue. - * @since Android 1.0 */ public void checkAwtEventQueueAccess() { try { @@ -648,11 +616,10 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to start a new print job. - * + * * @throws SecurityException * if the calling thread is not allowed to start a new print * job. - * @since Android 1.0 */ public void checkPrintJobAccess() { checkPermission(RuntimePermission.permissionToQueuePrintJob); @@ -661,12 +628,11 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to write to the file with * the specified file descriptor. - * + * * @param fd * the file descriptor of the file to write to. * @throws SecurityException * if the calling thread is not allowed to write to {@code fd}. - * @since Android 1.0 */ public void checkWrite(FileDescriptor fd) { if (fd == null) { @@ -678,13 +644,12 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to write to the file with * the specified name, which should be passed in canonical form. - * + * * @param file * the name of the file or directory to write to. * @throws SecurityException - * if the calling thread is not allowed to write to + * if the calling thread is not allowed to write to * {@code file}. - * @since Android 1.0 */ public void checkWrite(String file) { checkPermission(new FilePermission(file, "write")); //$NON-NLS-1$ @@ -692,11 +657,10 @@ public class SecurityManager { /** * Indicates if this security manager is currently checking something. - * + * * @return {@code true} if this security manager is executing a security * check method; {@code false} otherwise. * @deprecated Use {@link #checkPermission}. - * @since Android 1.0 */ @Deprecated public boolean getInCheck() { @@ -707,9 +671,8 @@ public class SecurityManager { * Returns an array containing one entry for each method in the current * execution stack. Each entry is the {@code java.lang.Class} which * represents the class in which the method is defined. - * + * * @return all classes in the execution stack. - * @since Android 1.0 */ @SuppressWarnings("unchecked") protected Class[] getClassContext() { @@ -719,10 +682,9 @@ public class SecurityManager { /** * Returns the class loader of the first class in the execution stack whose * class loader is not a system class loader. - * + * * @return the most recent non-system class loader. * @deprecated Use {@link #checkPermission}. - * @since Android 1.0 */ @Deprecated protected ClassLoader currentClassLoader() { @@ -755,11 +717,10 @@ public class SecurityManager { /** * Returns the index in the call stack of the first class whose class loader * is not a system class loader. - * + * * @return the frame index of the first method whose class was loaded by a * non-system class loader. * @deprecated Use {@link #checkPermission}. - * @since Android 1.0 */ @Deprecated protected int classLoaderDepth() { @@ -791,10 +752,9 @@ public class SecurityManager { /** * Returns the first class in the call stack that was loaded by a class * loader which is not a system class loader. - * + * * @return the most recent class loaded by a non-system class loader. * @deprecated Use {@link #checkPermission}. - * @since Android 1.0 */ @Deprecated protected Class<?> currentLoadedClass() { @@ -827,13 +787,12 @@ public class SecurityManager { * Returns the index in the call stack of the first method which is * contained in the class with the specified name. Returns -1 if no methods * from this class are in the stack. - * + * * @param name * the name of the class to look for. * @return the frame index of the first method found is contained in the * class identified by {@code name}. * @deprecated Use {@link #checkPermission}. - * @since Android 1.0 */ @Deprecated protected int classDepth(String name) { @@ -849,13 +808,12 @@ public class SecurityManager { /** * Indicates whether there is a method in the call stack from the class with * the specified name. - * + * * @param name * the name of the class to look for. * @return {@code true} if a method from the class identified by {@code * name} is executing; {@code false} otherwise. * @deprecated Use {@link #checkPermission}. - * @since Android 1.0 */ @Deprecated protected boolean inClass(String name) { @@ -865,11 +823,10 @@ public class SecurityManager { /** * Indicates whether there is a method in the call stack from a class which * was defined by a non-system class loader. - * + * * @return {@code true} if a method from a class that was defined by a * non-system class loader is executing; {@code false} otherwise. * @deprecated Use {@link #checkPermission} - * @since Android 1.0 */ @Deprecated protected boolean inClassLoader() { @@ -880,9 +837,8 @@ public class SecurityManager { * Returns the thread group which should be used to instantiate new threads. * By default, this is the same as the thread group of the thread running * this method. - * + * * @return ThreadGroup the thread group to create new threads in. - * @since Android 1.0 */ public ThreadGroup getThreadGroup() { return Thread.currentThread().getThreadGroup(); @@ -890,12 +846,11 @@ public class SecurityManager { /** * Returns an object which encapsulates the security state of the current - * point in the execution. In the Android reference implementation, this is - * an {@link java.security.AccessControlContext}. - * + * point in the execution. In our case, this is an {@link + * java.security.AccessControlContext}. + * * @return an object that encapsulates information about the current * execution environment. - * @since Android 1.0 */ public Object getSecurityContext() { return AccessController.getContext(); @@ -904,13 +859,12 @@ public class SecurityManager { /** * Checks whether the calling thread is allowed to access the resource being * guarded by the specified permission object. - * + * * @param permission * the permission to check. * @throws SecurityException * if the requested {@code permission} is denied according to * the current security policy. - * @since Android 1.0 */ public void checkPermission(Permission permission) { try { @@ -924,7 +878,7 @@ public class SecurityManager { /** * Checks whether the specified security context is allowed to access the * resource being guarded by the specified permission object. - * + * * @param permission * the permission to check. * @param context @@ -934,7 +888,6 @@ public class SecurityManager { * AccessControlContext} or if the requested {@code permission} * is denied for {@code context} according to the current * security policy. - * @since Android 1.0 */ public void checkPermission(Permission permission, Object context) { try { diff --git a/luni/src/main/java/java/lang/Short.java b/luni/src/main/java/java/lang/Short.java index cf95d22..9baf3a8 100644 --- a/luni/src/main/java/java/lang/Short.java +++ b/luni/src/main/java/java/lang/Short.java @@ -21,11 +21,11 @@ package java.lang; * The wrapper for the primitive type {@code short}. * * @see java.lang.Number - * @since Android 1.0 + * @since 1.1 */ public final class Short extends Number implements Comparable<Short> { - private static final long serialVersionUID = 7515723908773894738L; + private static final long serialVersionUID = 7515723908773894738L; /** * The value which the receiver represents. @@ -34,69 +34,61 @@ public final class Short extends Number implements Comparable<Short> { /** * Constant for the maximum {@code short} value, 2<sup>15</sup>-1. - * - * @since Android 1.0 */ public static final short MAX_VALUE = (short) 0x7FFF; /** * Constant for the minimum {@code short} value, -2<sup>15</sup>. - * - * @since Android 1.0 */ public static final short MIN_VALUE = (short) 0x8000; /** * Constant for the number of bits needed to represent a {@code short} in * two's complement form. - * - * @since Android 1.0 + * + * @since 1.5 */ public static final int SIZE = 16; /** - * The {@link Class} object that represents the primitive type {@code + * The {@link Class} object that represents the primitive type {@code * short}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final Class<Short> TYPE = (Class<Short>) new short[0] .getClass().getComponentType(); - // Note: This can't be set to "short.class", since *that* is - // defined to be "java.lang.Short.TYPE"; + // Note: This can't be set to "short.class", since *that* is + // defined to be "java.lang.Short.TYPE"; /** * Constructs a new {@code Short} from the specified string. - * + * * @param string * the string representation of a short value. * @throws NumberFormatException * if {@code string} can not be decoded into a short value. * @see #parseShort(String) - * @since Android 1.0 */ - public Short(String string) throws NumberFormatException { - this(parseShort(string)); - } + public Short(String string) throws NumberFormatException { + this(parseShort(string)); + } /** * Constructs a new {@code Short} with the specified primitive short value. - * + * * @param value * the primitive short value to store in the new instance. - * @since Android 1.0 */ - public Short(short value) { - this.value = value; - } + public Short(short value) { + this.value = value; + } - @Override + @Override public byte byteValue() { - return (byte) value; - } + return (byte) value; + } /** * Compares this object to the specified short object to determine their @@ -108,98 +100,97 @@ public final class Short extends Number implements Comparable<Short> { * value of {@code object}; 0 if the value of this short and the * value of {@code object} are equal; a positive value if the value * of this short is greater than the value of {@code object}. + * @throws NullPointerException + * if {@code object} is null. * @see java.lang.Comparable - * @since Android 1.0 + * @since 1.2 */ - public int compareTo(Short object) { - return value > object.value ? 1 : (value < object.value ? -1 : 0); - } + public int compareTo(Short object) { + return value > object.value ? 1 : (value < object.value ? -1 : 0); + } /** * Parses the specified string and returns a {@code Short} instance if the * string can be decoded into a short value. The string may be an optional * minus sign "-" followed by a hexadecimal ("0x..." or "#..."), octal * ("0..."), or decimal ("...") representation of a short. - * + * * @param string * a string representation of a short value. * @return a {@code Short} containing the value represented by * {@code string}. * @throws NumberFormatException * if {@code string} can not be parsed as a short value. - * @since Android 1.0 */ - public static Short decode(String string) throws NumberFormatException { - int intValue = Integer.decode(string).intValue(); - short result = (short) intValue; - if (result == intValue) { + public static Short decode(String string) throws NumberFormatException { + int intValue = Integer.decode(string).intValue(); + short result = (short) intValue; + if (result == intValue) { return valueOf(result); } - throw new NumberFormatException(); - } + throw new NumberFormatException(); + } - @Override + @Override public double doubleValue() { - return value; - } + return value; + } /** * Compares this instance with the specified object and indicates if they * are equal. In order to be equal, {@code object} must be an instance of * {@code Short} and have the same short value as this object. - * + * * @param object * the object to compare this short with. * @return {@code true} if the specified object is equal to this * {@code Short}; {@code false} otherwise. - * @since Android 1.0 */ - @Override + @Override public boolean equals(Object object) { - return (object instanceof Short) - && (value == ((Short) object).value); - } + return (object instanceof Short) + && (value == ((Short) object).value); + } - @Override + @Override public float floatValue() { - return value; - } + return value; + } - @Override + @Override public int hashCode() { - return value; - } + return value; + } - @Override + @Override public int intValue() { - return value; - } + return value; + } - @Override + @Override public long longValue() { - return value; - } + return value; + } /** * Parses the specified string as a signed decimal short value. The ASCII * character \u002d ('-') is recognized as the minus sign. - * + * * @param string * the string representation of a short value. * @return the primitive short value represented by {@code string}. * @throws NumberFormatException * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a short value. - * @since Android 1.0 */ - public static short parseShort(String string) throws NumberFormatException { - return parseShort(string, 10); - } + public static short parseShort(String string) throws NumberFormatException { + return parseShort(string, 10); + } /** * Parses the specified string as a signed short value using the specified * radix. The ASCII character \u002d ('-') is recognized as the minus sign. - * + * * @param string * the string representation of a short value. * @param radix @@ -211,50 +202,47 @@ public final class Short extends Number implements Comparable<Short> { * {@code radix < Character.MIN_RADIX}, * {@code radix > Character.MAX_RADIX}, or if {@code string} * can not be parsed as a short value. - * @since Android 1.0 */ - public static short parseShort(String string, int radix) - throws NumberFormatException { - int intValue = Integer.parseInt(string, radix); - short result = (short) intValue; - if (result == intValue) { + public static short parseShort(String string, int radix) + throws NumberFormatException { + int intValue = Integer.parseInt(string, radix); + short result = (short) intValue; + if (result == intValue) { return result; } - throw new NumberFormatException(); - } + throw new NumberFormatException(); + } /** * Gets the primitive value of this short. - * + * * @return this object's primitive value. - * @since Android 1.0 */ @Override public short shortValue() { - return value; - } + return value; + } - @Override + @Override public String toString() { - return Integer.toString(value); - } + return Integer.toString(value); + } /** * Returns a string containing a concise, human-readable description of the * specified short value with radix 10. - * + * * @param value * the short to convert to a string. * @return a printable representation of {@code value}. - * @since Android 1.0 */ - public static String toString(short value) { - return Integer.toString(value); - } + public static String toString(short value) { + return Integer.toString(value); + } /** * Parses the specified string as a signed decimal short value. - * + * * @param string * the string representation of a short value. * @return a {@code Short} instance containing the short value represented @@ -263,16 +251,15 @@ public final class Short extends Number implements Comparable<Short> { * if {@code string} is {@code null}, has a length of zero or * can not be parsed as a short value. * @see #parseShort(String) - * @since Android 1.0 */ - public static Short valueOf(String string) throws NumberFormatException { - return valueOf(parseShort(string)); - } + public static Short valueOf(String string) throws NumberFormatException { + return valueOf(parseShort(string)); + } /** * Parses the specified string as a signed short value using the specified * radix. - * + * * @param string * the string representation of a short value. * @param radix @@ -285,12 +272,11 @@ public final class Short extends Number implements Comparable<Short> { * {@code radix > Character.MAX_RADIX}, or if {@code string} * can not be parsed as a short value. * @see #parseShort(String, int) - * @since Android 1.0 */ - public static Short valueOf(String string, int radix) - throws NumberFormatException { - return valueOf(parseShort(string, radix)); - } + public static Short valueOf(String string, int radix) + throws NumberFormatException { + return valueOf(parseShort(string, radix)); + } /** * Reverses the bytes of the specified short. @@ -298,7 +284,7 @@ public final class Short extends Number implements Comparable<Short> { * @param s * the short value for which to reverse bytes. * @return the reversed value. - * @since Android 1.0 + * @since 1.5 */ public static short reverseBytes(short s) { int high = (s >> 8) & 0xFF; @@ -312,12 +298,11 @@ public final class Short extends Number implements Comparable<Short> { * If it is not necessary to get a new {@code Short} instance, it is * recommended to use this method instead of the constructor, since it * maintains a cache of instances which may result in better performance. - * </p> - * + * * @param s * the short value to store in the instance. * @return a {@code Short} instance containing {@code s}. - * @since Android 1.0 + * @since 1.5 */ public static Short valueOf(short s) { if (s < -128 || s > 127) { @@ -328,9 +313,7 @@ public final class Short extends Number implements Comparable<Short> { static class valueOfCache { /** - * <p> * A cache of instances used by {@link Short#valueOf(short)} and auto-boxing. - * </p> */ private static final Short[] CACHE = new Short[256]; diff --git a/luni/src/main/java/java/lang/StackOverflowError.java b/luni/src/main/java/java/lang/StackOverflowError.java index dd63b6b..3cbc0c7 100644 --- a/luni/src/main/java/java/lang/StackOverflowError.java +++ b/luni/src/main/java/java/lang/StackOverflowError.java @@ -22,8 +22,6 @@ package java.lang; * platform or virtual machine specific limit. Typically, this will occur only * when a program becomes infinitely recursive, but it can also occur in * correctly written (but deeply recursive) programs. - * - * @since Android 1.0 */ public class StackOverflowError extends java.lang.VirtualMachineError { @@ -32,8 +30,6 @@ public class StackOverflowError extends java.lang.VirtualMachineError { /** * Constructs a new {@code StackOverflowError} that includes the current * stack trace. - * - * @since Android 1.0 */ public StackOverflowError() { super(); @@ -45,7 +41,6 @@ public class StackOverflowError extends java.lang.VirtualMachineError { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public StackOverflowError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/StrictMath.java b/luni/src/main/java/java/lang/StrictMath.java index 66e4771..7a2da8e 100644 --- a/luni/src/main/java/java/lang/StrictMath.java +++ b/luni/src/main/java/java/lang/StrictMath.java @@ -37,25 +37,19 @@ package java.lang; * Library" (fdlibm), version 5.3. * <p> * <a href="http://www.netlib.org/fdlibm/">http://www.netlib.org/fdlibm/</a> - * - * @since Android 1.0 */ public final class StrictMath { - /** + /** * The double value closest to e, the base of the natural logarithm. - * - * @since Android 1.0 - */ - public final static double E = Math.E; + */ + public final static double E = Math.E; - /** + /** * The double value closest to pi, the ratio of a circle's circumference to * its diameter. - * - * @since Android 1.0 - */ - public final static double PI = Math.PI; + */ + public final static double PI = Math.PI; private static java.util.Random random; @@ -65,7 +59,7 @@ public final class StrictMath { private StrictMath() { } - /** + /** * Returns the absolute value of the argument. * <p> * Special cases: @@ -75,18 +69,16 @@ public final class StrictMath { * <li>{@code abs(-infinity) = +infinity}</li> * <li>{@code abs(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose absolute value has to be computed. * @return the absolute value of the argument. - * @since Android 1.0 */ - 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. @@ -98,52 +90,47 @@ public final class StrictMath { * <li>{@code abs(-infinity) = +infinity}</li> * <li>{@code abs(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param f * the value whose absolute value has to be computed. * @return the argument if it is positive, otherwise the negation of the * argument. - * @since Android 1.0 */ - 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. - * @since Android 1.0 */ - 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. * <p> * If the argument is {@code Long.MIN_VALUE}, {@code Long.MIN_VALUE} is * returned. - * </p> - * + * * @param l * the value whose absolute value has to be computed. * @return the argument if it is positive, otherwise the negation of the * argument. - * @since Android 1.0 */ - 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 @@ -155,14 +142,12 @@ public final class StrictMath { * <li>{@code acos((anything < -1) = NaN}</li> * <li>{@code acos(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value to compute arc cosine of. * @return the arc cosine of the argument. - * @since Android 1.0 */ - 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 @@ -174,14 +159,12 @@ public final class StrictMath { * <li>{@code asin((anything < -1)) = NaN}</li> * <li>{@code asin(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose arc sine has to be computed. * @return the arc sine of the argument. - * @since Android 1.0 */ - 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 @@ -195,14 +178,12 @@ public final class StrictMath { * <li>{@code atan(-infinity) = -pi/2}</li> * <li>{@code atan(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose arc tangent has to be computed. * @return the arc tangent of the argument. - * @since Android 1.0 */ - public static native double atan(double d); + public static native double atan(double d); /** * Returns the closest double approximation of the arc tangent of @@ -234,20 +215,15 @@ public final class StrictMath { * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))} * {@code =} {@code -pi/2}</li> * </ul> - * </p> - * + * * @param y * the numerator of the value whose atan has to be computed. * @param x * the denominator of the value whose atan has to be computed. * @return the arc tangent of {@code y/x}. - * @since Android 1.0 */ - public static native double atan2(double y, double x); - // BEGIN android-note - // parameter names changed from d1 / d2 to x / y - // END android-note - + public static native double atan2(double y, double x); + /** * Returns the closest double approximation of the cube root of the * argument. @@ -260,12 +236,10 @@ public final class StrictMath { * <li>{@code cbrt(-infinity) = -infinity}</li> * <li>{@code cbrt(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose cube root has to be computed. * @return the cube root of the argument. - * @since Android 1.0 */ public static native double cbrt(double d); @@ -282,15 +256,14 @@ public final class StrictMath { * <li>{@code ceil(-infinity) = -infinity}</li> * <li>{@code ceil(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose closest integer value has to be computed. * @return the ceiling of the argument. - * @since Android 1.0 */ - public static native double ceil(double d); - + public static native double ceil(double d); + + /** * Returns the closest double approximation of the hyperbolic cosine of the * argument. @@ -301,12 +274,10 @@ public final class StrictMath { * <li>{@code cosh(-infinity) = +infinity}</li> * <li>{@code cosh(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose hyperbolic cosine has to be computed. * @return the hyperbolic cosine of the argument. - * @since Android 1.0 */ public static native double cosh(double d); @@ -319,12 +290,10 @@ public final class StrictMath { * <li>{@code cos(-infinity) = NaN}</li> * <li>{@code cos(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the angle whose cosine has to be computed, in radians. * @return the cosine of the argument. - * @since Android 1.0 */ public static native double cos(double d); @@ -338,15 +307,13 @@ public final class StrictMath { * <li>{@code exp(-infinity) = +0.0}</li> * <li>{@code exp(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose exponential has to be computed. * @return the exponential of the argument. - * @since Android 1.0 */ 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 @@ -361,14 +328,12 @@ public final class StrictMath { * <li>{@code expm1(-infinity) = -1.0}</li> * <li>{@code expm1(NaN) = NaN}</li> * </ul> - * </p> - * + * * @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. - * @since Android 1.0 */ public static native double expm1(double d); @@ -384,14 +349,12 @@ public final class StrictMath { * <li>{@code floor(-infinity) = -infinity}</li> * <li>{@code floor(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d the value whose closest integer value has to be computed. * @return the floor of the argument. - * @since Android 1.0 */ public static native double floor(double d); - + /** * 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 @@ -405,8 +368,7 @@ public final class StrictMath { * <li>{@code hypot((anything including NaN), -infinity) = +infinity}</li> * <li>{@code hypot(NaN, NaN) = NaN}</li> * </ul> - * </p> - * + * * @param x * a double number. * @param y @@ -414,7 +376,6 @@ public final class StrictMath { * @return the {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} * <i> {@code y}</i><sup>{@code 2}</sup>{@code )} value of the * arguments. - * @since Android 1.0 */ public static native double hypot(double x, double y); @@ -436,19 +397,14 @@ public final class StrictMath { * <li>{@code IEEEremainder(x, -infinity) = x } where x is anything but * +/-infinity</li> * </ul> - * </p> - * + * * @param x * the numerator of the operation. * @param y * the denominator of the operation. * @return the IEEE754 floating point reminder of of {@code x/y}. - * @since Android 1.0 */ - public static native double IEEEremainder(double x, double y); - // BEGIN android-note - // parameter names changed from d1 / d2 to x / y - // END android-note + public static native double IEEEremainder(double x, double y); /** * Returns the closest double approximation of the natural logarithm of the @@ -463,15 +419,13 @@ public final class StrictMath { * <li>{@code log(-infinity) = NaN}</li> * <li>{@code log(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose log has to be computed. * @return the natural logarithm of the argument. - * @since Android 1.0 */ public static native double log(double d); - + /** * Returns the closest double approximation of the base 10 logarithm of the * argument. @@ -485,15 +439,13 @@ public final class StrictMath { * <li>{@code log10(-infinity) = NaN}</li> * <li>{@code log10(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose base 10 log has to be computed. * @return the natural logarithm of the argument. - * @since Android 1.0 */ public static native double log10(double d); - + /** * Returns the closest double approximation of the natural logarithm of the * sum of the argument and 1. If the argument is very close to 0, it is much @@ -510,12 +462,10 @@ public final class StrictMath { * <li>{@code log1p(-infinity) = NaN}</li> * <li>{@code log1p(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value to compute the {@code ln(1+d)} of. * @return the natural logarithm of the sum of the argument and 1. - * @since Android 1.0 */ public static native double log1p(double d); @@ -530,29 +480,27 @@ public final class StrictMath { * <li>{@code max(+0.0, -0.0) = +0.0}</li> * <li>{@code max(-0.0, +0.0) = +0.0}</li> * </ul> - * </p> - * + * * @param d1 * the first argument. * @param d2 * the second argument. * @return the larger of {@code d1} and {@code d2}. - * @since Android 1.0 */ - public static double max(double d1, double d2) { - if (d1 > d2) - return d1; - if (d1 < d2) - return d2; - /* if either arg is NaN, return NaN */ - if (d1 != d2) - return Double.NaN; - /* max( +0.0,-0.0) == +0.0 */ - if (d1 == 0.0 - && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0) - return 0.0; - return d1; - } + public static double max(double d1, double d2) { + if (d1 > d2) + return d1; + if (d1 < d2) + return d2; + /* if either arg is NaN, return NaN */ + if (d1 != d2) + return Double.NaN; + /* max( +0.0,-0.0) == +0.0 */ + if (d1 == 0.0 + && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0) + return 0.0; + return d1; + } /** * Returns the most positive (closest to positive infinity) of the two @@ -565,59 +513,55 @@ public final class StrictMath { * <li>{@code max(+0.0, -0.0) = +0.0}</li> * <li>{@code max(-0.0, +0.0) = +0.0}</li> * </ul> - * </p> - * + * * @param f1 * the first argument. * @param f2 * the second argument. * @return the larger of {@code f1} and {@code f2}. - * @since Android 1.0 */ - public static float max(float f1, float f2) { - if (f1 > f2) - return f1; - if (f1 < f2) - return f2; - /* if either arg is NaN, return NaN */ - if (f1 != f2) - return Float.NaN; - /* max( +0.0,-0.0) == +0.0 */ - if (f1 == 0.0f - && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0) - return 0.0f; - return f1; - } + public static float max(float f1, float f2) { + if (f1 > f2) + return f1; + if (f1 < f2) + return f2; + /* if either arg is NaN, return NaN */ + if (f1 != f2) + return Float.NaN; + /* max( +0.0,-0.0) == +0.0 */ + if (f1 == 0.0f + && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0) + return 0.0f; + return f1; + } /** * 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}. - * @since Android 1.0 */ - 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}. - * @since Android 1.0 */ - 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 @@ -630,29 +574,27 @@ public final class StrictMath { * <li>{@code min(+0.0, -0.0) = -0.0}</li> * <li>{@code min(-0.0, +0.0) = -0.0}</li> * </ul> - * </p> - * + * * @param d1 * the first argument. * @param d2 * the second argument. * @return the smaller of {@code d1} and {@code d2}. - * @since Android 1.0 */ - public static double min(double d1, double d2) { - if (d1 > d2) - return d2; - if (d1 < d2) - return d1; - /* if either arg is NaN, return NaN */ - if (d1 != d2) - return Double.NaN; - /* min( +0.0,-0.0) == -0.0 */ - if (d1 == 0.0 - && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0) - return 0.0 * (-1.0); - return d1; - } + public static double min(double d1, double d2) { + if (d1 > d2) + return d2; + if (d1 < d2) + return d1; + /* if either arg is NaN, return NaN */ + if (d1 != d2) + return Double.NaN; + /* min( +0.0,-0.0) == -0.0 */ + if (d1 == 0.0 + && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0) + return 0.0 * (-1.0); + return d1; + } /** * Returns the most negative (closest to negative infinity) of the two @@ -665,59 +607,55 @@ public final class StrictMath { * <li>{@code min(+0.0, -0.0) = -0.0}</li> * <li>{@code min(-0.0, +0.0) = -0.0}</li> * </ul> - * </p> - * + * * @param f1 * the first argument. * @param f2 * the second argument. * @return the smaller of {@code f1} and {@code f2}. - * @since Android 1.0 */ - public static float min(float f1, float f2) { - if (f1 > f2) - return f2; - if (f1 < f2) - return f1; - /* if either arg is NaN, return NaN */ - if (f1 != f2) - return Float.NaN; - /* min( +0.0,-0.0) == -0.0 */ - if (f1 == 0.0f - && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0) - return 0.0f * (-1.0f); - return f1; - } + public static float min(float f1, float f2) { + if (f1 > f2) + return f2; + if (f1 < f2) + return f1; + /* if either arg is NaN, return NaN */ + if (f1 != f2) + return Float.NaN; + /* min( +0.0,-0.0) == -0.0 */ + if (f1 == 0.0f + && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0) + return 0.0f * (-1.0f); + return f1; + } /** * 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}. - * @since Android 1.0 */ - 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}. - * @since Android 1.0 */ - 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 @@ -750,26 +688,20 @@ public final class StrictMath { * <li>{@code pow((-anything except 0 and infinity), (non-integer))} * {@code =} {@code NAN}</li> * </ul> - * </p> - * + * * @param x * the base of the operation. * @param y * the exponent of the operation. * @return {@code x} to the power of {@code y}. - * @since Android 1.0 */ - public static native double pow(double x, double y); - // BEGIN android-note - // parameter names changed from d1 / d2 to x / y - // END android-note + public static native double pow(double x, double y); /** * Returns a pseudo-random number between 0.0 (inclusive) and 1.0 * (exclusive). - * + * * @return a pseudo-random number. - * @since Android 1.0 */ public static double random() { // BEGIN android-changed @@ -777,8 +709,8 @@ public final class StrictMath { random = new java.util.Random(); } // END android-changed - return random.nextDouble(); - } + return random.nextDouble(); + } /** * Returns the double conversion of the result of rounding the argument to @@ -792,12 +724,10 @@ public final class StrictMath { * <li>{@code rint(-infinity) = -infinity}</li> * <li>{@code rint(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value to be rounded. * @return the closest integer to the argument (as a double). - * @since Android 1.0 */ public static native double rint(double d); @@ -815,19 +745,17 @@ public final class StrictMath { * <li>{@code round(-infinity) = Long.MIN_VALUE}</li> * <li>{@code round(NaN) = +0.0}</li> * </ul> - * </p> - * + * * @param d * the value to be rounded. * @return the closest integer to the argument. - * @since Android 1.0 */ - public static long round(double d) { - // check for NaN - if (d != d) - return 0L; - return (long) Math.floor(d + 0.5d); - } + public static long round(double d) { + // check for NaN + if (d != d) + return 0L; + return (long) Math.floor(d + 0.5d); + } /** * Returns the result of rounding the argument to an integer. The result is @@ -843,19 +771,17 @@ public final class StrictMath { * <li>{@code round(-infinity) = Integer.MIN_VALUE}</li> * <li>{@code round(NaN) = +0.0}</li> * </ul> - * </p> - * + * * @param f * the value to be rounded. * @return the closest integer to the argument. - * @since Android 1.0 */ - public static int round(float f) { - // check for NaN - if (f != f) - return 0; - return (int) Math.floor(f + 0.5f); - } + public static int round(float f) { + // check for NaN + if (f != f) + return 0; + return (int) Math.floor(f + 0.5f); + } /** * Returns the signum function of the argument. If the argument is less than @@ -871,12 +797,10 @@ public final class StrictMath { * <li>{@code signum(-infinity) = -1.0}</li> * <li>{@code signum(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose signum has to be computed. * @return the value of the signum function. - * @since Android 1.0 */ public static double signum(double d){ if(Double.isNaN(d)){ @@ -905,12 +829,10 @@ public final class StrictMath { * <li>{@code signum(-infinity) = -1.0}</li> * <li>{@code signum(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param f * the value whose signum has to be computed. * @return the value of the signum function. - * @since Android 1.0 */ public static float signum(float f){ if(Float.isNaN(f)){ @@ -937,15 +859,13 @@ public final class StrictMath { * <li>{@code sinh(-infinity) = -infinity}</li> * <li>{@code sinh(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose hyperbolic sine has to be computed. * @return the hyperbolic sine of the argument. - * @since Android 1.0 */ public static native double sinh(double d); - + /** * Returns the closest double approximation of the sine of the argument. * <p> @@ -957,12 +877,10 @@ public final class StrictMath { * <li>{@code sin(-infinity) = NaN}</li> * <li>{@code sin(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the angle whose sin has to be computed, in radians. * @return the sine of the argument. - * @since Android 1.0 */ public static native double sin(double d); @@ -978,12 +896,10 @@ public final class StrictMath { * <li>{@code sqrt(+infinity) = +infinity}</li> * <li>{@code sqrt(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose square root has to be computed. * @return the square root of the argument. - * @since Android 1.0 */ public static native double sqrt(double d); @@ -998,12 +914,10 @@ public final class StrictMath { * <li>{@code tan(-infinity) = NaN}</li> * <li>{@code tan(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the angle whose tangens has to be computed, in radians. * @return the tangent of the argument. - * @since Android 1.0 */ public static native double tan(double d); @@ -1019,15 +933,13 @@ public final class StrictMath { * <li>{@code tanh(-infinity) = -1.0}</li> * <li>{@code tanh(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the value whose hyperbolic tangent has to be computed. * @return the hyperbolic tangent of the argument - * @since Android 1.0 */ public static native double tanh(double d); - + /** * Returns the measure in degrees of the supplied radian angle. The result * is {@code angrad * 180 / pi}. @@ -1040,16 +952,14 @@ public final class StrictMath { * <li>{@code toDegrees(-infinity) = -infinity}</li> * <li>{@code toDegrees(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param angrad * an angle in radians. * @return the degree measure of the angle. - * @since Android 1.0 */ - public static double toDegrees(double angrad) { - return angrad * 180d / PI; - } + public static double toDegrees(double angrad) { + return angrad * 180d / PI; + } /** * Returns the measure in radians of the supplied degree angle. The result @@ -1063,18 +973,16 @@ public final class StrictMath { * <li>{@code toRadians(-infinity) = -infinity}</li> * <li>{@code toRadians(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param angdeg * an angle in degrees. * @return the radian measure of the angle. - * @since Android 1.0 */ - public static double toRadians(double angdeg) { - return angdeg / 180d * PI; - } - - /** + public static double toRadians(double angdeg) { + return angdeg / 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}, @@ -1088,12 +996,10 @@ public final class StrictMath { * <li>{@code ulp(-infintiy) = infinity}</li> * <li>{@code ulp(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param d * the floating-point value to compute ulp of. * @return the size of a ulp of the argument. - * @since Android 1.0 */ public static double ulp(double d) { // special cases @@ -1120,12 +1026,10 @@ public final class StrictMath { * <li>{@code ulp(-infintiy) = infinity}</li> * <li>{@code ulp(NaN) = NaN}</li> * </ul> - * </p> - * + * * @param f * the floating-point value to compute ulp of. * @return the size of a ulp of the argument. - * @since Android 1.0 */ public static float ulp(float f) { // special cases diff --git a/luni/src/main/java/java/lang/String.java b/luni/src/main/java/java/lang/String.java index b257a36..22f72cb 100644 --- a/luni/src/main/java/java/lang/String.java +++ b/luni/src/main/java/java/lang/String.java @@ -21,9 +21,6 @@ import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.util.Comparator; import java.util.Formatter; -// BEGIN android-added -import java.util.IllegalFormatException; -// END android-added import java.util.Locale; import java.util.regex.Pattern; @@ -50,7 +47,7 @@ import org.apache.harmony.luni.util.PriviAction; * @see StringBuffer * @see StringBuilder * @see Charset - * @since Android 1.0 + * @since 1.0 */ public final class String implements Serializable, Comparable<String>, CharSequence { @@ -80,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 */ @@ -138,8 +135,6 @@ public final class String implements Serializable, Comparable<String>, /** * A comparator ignoring the case of the characters. - * - * @since Android 1.0 */ public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); @@ -166,8 +161,6 @@ public final class String implements Serializable, Comparable<String>, /** * Creates an empty string. - * - * @since Android 1.0 */ public String() { value = new char[0]; @@ -189,10 +182,9 @@ 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. - * @since Android 1.0 */ public String(byte[] data) { this(data, 0, data.length); @@ -201,14 +193,15 @@ 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 * the high byte to use. + * @throws NullPointerException + * when {@code data} is {@code null}. * @deprecated Use {@link #String(byte[])} or * {@link #String(byte[], String)} instead. - * @since Android 1.0 */ @Deprecated public String(byte[] data, int high) { @@ -220,17 +213,18 @@ 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 * the starting offset in the byte array. * @param length * the number of bytes to convert. + * @throws NullPointerException + * when {@code data} is {@code null}. * @throws IndexOutOfBoundsException * if {@code length < 0, start < 0} or {@code start + length > * data.length}. - * @since Android 1.0 */ public String(byte[] data, int start, int length) { // start + length could overflow, start/length maybe MaxInt @@ -264,13 +258,13 @@ public final class String implements Serializable, Comparable<String>, * the starting offset in the byte array. * @param length * the number of bytes to convert. - * + * @throws NullPointerException + * when {@code data} is {@code null}. * @throws IndexOutOfBoundsException * if {@code length < 0, start < 0} or * {@code start + length > data.length} * * @deprecated Use {@link #String(byte[], int, int)} instead. - * @since Android 1.0 */ @Deprecated public String(byte[] data, int high, int start, int length) { @@ -294,7 +288,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 @@ -303,12 +297,13 @@ public final class String implements Serializable, Comparable<String>, * the number of bytes to convert. * @param encoding * the encoding. + * @throws NullPointerException + * when {@code data} is {@code null}. * @throws IndexOutOfBoundsException * if {@code length < 0, start < 0} or {@code start + length > * data.length}. * @throws UnsupportedEncodingException * if {@code encoding} is not supported. - * @since Android 1.0 */ public String(byte[] data, int start, int length, final String encoding) throws UnsupportedEncodingException { @@ -444,7 +439,7 @@ public final class String implements Serializable, Comparable<String>, try { cb = charset.decode(ByteBuffer.wrap(data, start, length)); } catch (Exception e) { - // do nothing. according to spec: + // do nothing. according to spec: // behavior is unspecified for invalid array cb = CharBuffer.wrap("\u003f".toCharArray()); //$NON-NLS-1$ } @@ -462,14 +457,15 @@ 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 * the encoding. + * @throws NullPointerException + * when {@code data} is {@code null}. * @throws UnsupportedEncodingException * if {@code encoding} is not supported. - * @since Android 1.0 */ public String(byte[] data, String encoding) throws UnsupportedEncodingException { this(data, 0, data.length, encoding); @@ -479,10 +475,11 @@ 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. - * @since Android 1.0 + * @throws NullPointerException + * when {@code data} is {@code null}. */ public String(char[] data) { this(data, 0, data.length); @@ -492,17 +489,18 @@ 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 * the starting offset in the character array. * @param length * the number of characters to use. + * @throws NullPointerException + * when {@code data} is {@code null}. * @throws IndexOutOfBoundsException * if {@code length < 0, start < 0} or {@code start + length > * data.length} - * @since Android 1.0 */ public String(char[] data, int start, int length) { // range check everything so a new char[] is not created @@ -529,10 +527,9 @@ 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. - * @since Android 1.0 */ public String(String string) { value = string.value; @@ -543,10 +540,9 @@ public final class String implements Serializable, Comparable<String>, /** * Creates a {@code String} from the contents of the specified * {@code StringBuffer}. - * + * * @param stringbuffer * the buffer to get the contents from. - * @since Android 1.0 */ public String(StringBuffer stringbuffer) { offset = 0; @@ -558,7 +554,7 @@ public final class String implements Serializable, Comparable<String>, /** * Creates a {@code String} from the sub-array of Unicode code points. - * + * * @param codePoints * the array of Unicode code points to convert. * @param offset @@ -566,13 +562,15 @@ public final class String implements Serializable, Comparable<String>, * converting from. * @param count * the number of elements in {@code codePoints} to copy. + * @throws NullPointerException + * if {@code codePoints} is {@code null}. * @throws IllegalArgumentException * if any of the elements of {@code codePoints} are not valid * Unicode code points. * @throws IndexOutOfBoundsException * if {@code offset} or {@code count} are not within the bounds * of {@code codePoints}. - * @since Android 1.0 + * @since 1.5 */ public String(int[] codePoints, int offset, int count) { super(); @@ -596,10 +594,12 @@ 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. - * @since Android 1.0 + * @throws NullPointerException + * if {@code sb} is {@code null}. + * @since 1.5 */ public String(StringBuilder sb) { if (sb == null) { @@ -630,13 +630,12 @@ 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. * @throws IndexOutOfBoundsException * if {@code index < 0} or {@code index >= length()}. - * @since Android 1.0 */ public char charAt(int index) { if (0 <= index && index < count) { @@ -645,6 +644,39 @@ public final class String implements Serializable, Comparable<String>, throw new StringIndexOutOfBoundsException(); } + // Optimized for ASCII + private char compareValue(char ch) { + if (ch < 128) { + if ('A' <= ch && ch <= 'Z') { + return (char) (ch + ('a' - 'A')); + } + return ch; + } + return Character.toLowerCase(Character.toUpperCase(ch)); + } + + // Optimized for ASCII + private char toLowerCase(char ch) { + if (ch < 128) { + if ('A' <= ch && ch <= 'Z') { + return (char) (ch + ('a' - 'A')); + } + return ch; + } + return Character.toLowerCase(ch); + } + + // Optimized for ASCII + private char toUpperCase(char ch) { + if (ch < 128) { + if ('a' <= ch && ch <= 'z') { + return (char) (ch - ('a' - 'A')); + } + return ch; + } + return Character.toUpperCase(ch); + } + /** * Compares the specified string to this string using the Unicode values of * the characters. Returns 0 if the strings contain the same characters in @@ -656,13 +688,14 @@ 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 * before the specified string, or a positive integer if this string * is after the specified string. - * @since Android 1.0 + * @throws NullPointerException + * if {@code string} is {@code null}. */ public int compareTo(String string) { // Code adapted from K&R, pg 101 @@ -688,13 +721,14 @@ 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 * before the specified string, or a positive integer if this string * is after the specified string. - * @since Android 1.0 + * @throws NullPointerException + * if {@code string} is {@code null}. */ public int compareToIgnoreCase(String string) { int o1 = offset, o2 = string.offset, result; @@ -705,8 +739,8 @@ public final class String implements Serializable, Comparable<String>, if ((c1 = value[o1++]) == (c2 = target[o2++])) { continue; } - c1 = Character.toLowerCase(Character.toUpperCase(c1)); - c2 = Character.toLowerCase(Character.toUpperCase(c2)); + c1 = compareValue(c1); + c2 = compareValue(c2); if ((result = c1 - c2) != 0) { return result; } @@ -716,12 +750,11 @@ 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 * specified string. - * @since Android 1.0 */ public String concat(String string) { if (string.count > 0 && count > 0) { @@ -738,11 +771,12 @@ 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. - * @since Android 1.0 + * @throws NullPointerException + * if {@code data} is {@code null}. */ public static String copyValueOf(char[] data) { return new String(data, 0, data.length); @@ -752,7 +786,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 @@ -760,10 +794,11 @@ public final class String implements Serializable, Comparable<String>, * @param length * the number of characters to use. * @return the new string. + * @throws NullPointerException + * if {@code data} is {@code null}. * @throws IndexOutOfBoundsException * if {@code length < 0, start < 0} or {@code start + length > * data.length}. - * @since Android 1.0 */ public static String copyValueOf(char[] data, int start, int length) { return new String(data, start, length); @@ -794,12 +829,13 @@ 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, * {@code false} otherwise. - * @since Android 1.0 + * @throws NullPointerException + * if {@code suffix} is {@code null}. */ public boolean endsWith(String suffix) { return regionMatches(count - suffix.count, suffix, 0, suffix.count); @@ -809,13 +845,12 @@ 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, * {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -850,12 +885,11 @@ 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, * {@code false} otherwise. - * @since Android 1.0 */ public boolean equalsIgnoreCase(String string) { if (string == this) { @@ -871,9 +905,9 @@ public final class String implements Serializable, Comparable<String>, char[] target = string.value; while (o1 < end) { if ((c1 = value[o1++]) != (c2 = target[o2++]) - && Character.toUpperCase(c1) != Character.toUpperCase(c2) + && toUpperCase(c1) != toUpperCase(c2) // Required for unicode that we test both cases - && Character.toLowerCase(c1) != Character.toLowerCase(c2)) { + && toLowerCase(c1) != toLowerCase(c2)) { return false; } } @@ -885,9 +919,8 @@ 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. - * @since Android 1.0 */ public byte[] getBytes() { ByteBuffer buffer = defaultCharset().encode( @@ -900,7 +933,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 @@ -909,11 +942,12 @@ public final class String implements Serializable, Comparable<String>, * the destination byte array. * @param index * the starting offset in the destination byte array. + * @throws NullPointerException + * if {@code data} is {@code null}. * @throws IndexOutOfBoundsException * if {@code start < 0}, {@code end > length()}, {@code index < * 0} or {@code end - start > data.length - index}. * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)} - * @since Android 1.0 */ @Deprecated public void getBytes(int start, int end, byte[] data, int index) { @@ -933,13 +967,12 @@ 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. * @throws UnsupportedEncodingException * if the encoding is not supported. - * @since Android 1.0 */ public byte[] getBytes(String encoding) throws UnsupportedEncodingException { ByteBuffer buffer = getCharset(encoding).encode( @@ -970,7 +1003,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 @@ -979,11 +1012,12 @@ public final class String implements Serializable, Comparable<String>, * the destination character array. * @param index * the starting offset in the character array. + * @throws NullPointerException + * if {@code buffer} is {@code null}. * @throws IndexOutOfBoundsException * if {@code start < 0}, {@code end > length()}, {@code start > * end}, {@code index < 0}, {@code end - start > buffer.length - * index} - * @since Android 1.0 */ public void getChars(int start, int end, char[] buffer, int index) { // NOTE last character not copied! @@ -1031,12 +1065,11 @@ 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 * character isn't found. - * @since Android 1.0 */ public int indexOf(int c) { // BEGIN android-changed @@ -1059,14 +1092,13 @@ 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 * the starting offset. * @return the index in this string of the specified character, -1 if the * character isn't found. - * @since Android 1.0 */ public int indexOf(int c, int start) { // BEGIN android-changed @@ -1092,12 +1124,13 @@ 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 * string, -1 if the specified string is not a substring. - * @since Android 1.0 + * @throws NullPointerException + * if {@code string} is {@code null}. */ public int indexOf(String string) { // BEGIN android-changed @@ -1136,14 +1169,15 @@ 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 * the starting offset. * @return the index of the first character of the specified string in this * string, -1 if the specified string is not a substring. - * @since Android 1.0 + * @throws NullPointerException + * if {@code subString} is {@code null}. */ public int indexOf(String subString, int start) { // BEGIN android-changed @@ -1185,9 +1219,8 @@ 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. - * @since Android 1.0 */ native public String intern(); @@ -1196,12 +1229,11 @@ public final class String implements Serializable, Comparable<String>, * 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 * character isn't found. - * @since Android 1.0 */ public int lastIndexOf(int c) { // BEGIN android-changed @@ -1221,14 +1253,13 @@ 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 * the starting offset. * @return the index in this string of the specified character, -1 if the * character isn't found. - * @since Android 1.0 */ public int lastIndexOf(int c, int start) { // BEGIN android-changed @@ -1253,12 +1284,13 @@ 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 * string, -1 if the specified string is not a substring. - * @since Android 1.0 + * @throws NullPointerException + * if {@code string} is {@code null}. */ public int lastIndexOf(String string) { // Use count instead of count - 1 so lastIndexOf("") returns count @@ -1269,14 +1301,15 @@ 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 * the starting offset. * @return the index of the first character of the specified string in this * string , -1 if the specified string is not a substring. - * @since Android 1.0 + * @throws NullPointerException + * if {@code subString} is {@code null}. */ public int lastIndexOf(String subString, int start) { int subCount = subString.count; @@ -1312,9 +1345,8 @@ public final class String implements Serializable, Comparable<String>, /** * Returns the size of this string. - * + * * @return the number of characters in this string. - * @since Android 1.0 */ public int length() { return count; @@ -1323,7 +1355,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 @@ -1334,7 +1366,8 @@ public final class String implements Serializable, Comparable<String>, * the number of characters to compare. * @return {@code true} if the ranges of characters are equal, {@code false} * otherwise - * @since Android 1.0 + * @throws NullPointerException + * if {@code string} is {@code null}. */ public boolean regionMatches(int thisStart, String string, int start, int length) { @@ -1367,7 +1400,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 @@ -1380,7 +1413,8 @@ public final class String implements Serializable, Comparable<String>, * the number of characters to compare. * @return {@code true} if the ranges of characters are equal, {@code false} * otherwise. - * @since Android 1.0 + * @throws NullPointerException + * if {@code string} is {@code null}. */ public boolean regionMatches(boolean ignoreCase, int thisStart, String string, int start, int length) { @@ -1403,11 +1437,9 @@ public final class String implements Serializable, Comparable<String>, char[] target = string.value; while (thisStart < end) { if ((c1 = value[thisStart++]) != (c2 = target[start++]) - && Character.toUpperCase(c1) != Character - .toUpperCase(c2) + && toUpperCase(c1) != toUpperCase(c2) // Required for unicode that we test both cases - && Character.toLowerCase(c1) != Character - .toLowerCase(c2)) { + && toLowerCase(c1) != toLowerCase(c2)) { return false; } } @@ -1419,13 +1451,12 @@ 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 * the replacement character. * @return a new string with occurrences of oldChar replaced by newChar. - * @since Android 1.0 */ public String replace(char oldChar, char newChar) { // BEGIN endroid-changed @@ -1454,18 +1485,19 @@ 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 * the replacement sequence. * @return the resulting string. - * @since Android 1.0 + * @throws NullPointerException + * if {@code target} or {@code replacement} is {@code null}. */ public String replace(CharSequence target, CharSequence replacement) { if (target == null) { @@ -1489,7 +1521,7 @@ public final class String implements Serializable, Comparable<String>, buffer.append(rs); tail = index + tl; } while ((index = indexOf(ts, tail)) != -1); - //append trailing chars + //append trailing chars buffer.append(value, offset + tail, count - tail); return buffer.toString(); @@ -1498,12 +1530,13 @@ 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, * {@code false} otherwise - * @since Android 1.0 + * @throws NullPointerException + * if {@code prefix} is {@code null}. */ public boolean startsWith(String prefix) { return startsWith(prefix, 0); @@ -1512,14 +1545,15 @@ 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 * the starting offset. * @return {@code true} if the specified string occurs in this string at the * specified offset, {@code false} otherwise. - * @since Android 1.0 + * @throws NullPointerException + * if {@code prefix} is {@code null}. */ public boolean startsWith(String prefix, int start) { return regionMatches(start, prefix, 0, prefix.count); @@ -1527,14 +1561,13 @@ 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 * the string. * @throws IndexOutOfBoundsException * if {@code start < 0} or {@code start > length()}. - * @since Android 1.0 */ public String substring(int start) { if (start == 0) { @@ -1548,7 +1581,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 @@ -1557,7 +1590,6 @@ public final class String implements Serializable, Comparable<String>, * @throws IndexOutOfBoundsException * if {@code start < 0}, {@code start > end} or {@code end > * length()}. - * @since Android 1.0 */ public String substring(int start, int end) { if (start == 0 && end == count) { @@ -1573,9 +1605,8 @@ 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. - * @since Android 1.0 */ public char[] toCharArray() { char[] buffer = new char[count]; @@ -1586,10 +1617,9 @@ 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. - * @since Android 1.0 */ public String toLowerCase() { return toLowerCase(Locale.getDefault()); @@ -1598,17 +1628,16 @@ 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 * the characters in this string. - * @since Android 1.0 */ public String toLowerCase(Locale locale) { for (int o = offset, end = offset + count; o < end; o++) { char ch = value[o]; - if (ch != Character.toLowerCase(ch)) { + if (ch != toLowerCase(ch)) { char[] buffer = new char[count]; int i = o - offset; // Not worth checking for i == 0 case @@ -1616,12 +1645,12 @@ public final class String implements Serializable, Comparable<String>, // Turkish if (!"tr".equals(locale.getLanguage())) { //$NON-NLS-1$ while (i < count) { - buffer[i++] = Character.toLowerCase(value[o++]); + buffer[i++] = toLowerCase(value[o++]); } } else { while (i < count) { - buffer[i++] = (ch = value[o++]) != 0x49 ? Character - .toLowerCase(ch) : (char) 0x131; + buffer[i++] = (ch = value[o++]) != 0x49 ? toLowerCase(ch) + : (char) 0x131; } } return new String(0, count, buffer); @@ -1634,7 +1663,6 @@ public final class String implements Serializable, Comparable<String>, * Returns this string. * * @return this string. - * @since Android 1.0 */ @Override public String toString() { @@ -1644,15 +1672,17 @@ 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. - * @since Android 1.0 */ public String toUpperCase() { return toUpperCase(Locale.getDefault()); } + // BEGIN android-note + // put this in a helper class so that it's only initialized on demand? + // END android-note private static final char[] upperValues = "SS\u0000\u02bcN\u0000J\u030c\u0000\u0399\u0308\u0301\u03a5\u0308\u0301\u0535\u0552\u0000H\u0331\u0000T\u0308\u0000W\u030a\u0000Y\u030a\u0000A\u02be\u0000\u03a5\u0313\u0000\u03a5\u0313\u0300\u03a5\u0313\u0301\u03a5\u0313\u0342\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1fba\u0399\u0000\u0391\u0399\u0000\u0386\u0399\u0000\u0391\u0342\u0000\u0391\u0342\u0399\u0391\u0399\u0000\u1fca\u0399\u0000\u0397\u0399\u0000\u0389\u0399\u0000\u0397\u0342\u0000\u0397\u0342\u0399\u0397\u0399\u0000\u0399\u0308\u0300\u0399\u0308\u0301\u0399\u0342\u0000\u0399\u0308\u0342\u03a5\u0308\u0300\u03a5\u0308\u0301\u03a1\u0313\u0000\u03a5\u0342\u0000\u03a5\u0308\u0342\u1ffa\u0399\u0000\u03a9\u0399\u0000\u038f\u0399\u0000\u03a9\u0342\u0000\u03a9\u0342\u0399\u03a9\u0399\u0000FF\u0000FI\u0000FL\u0000FFIFFLST\u0000ST\u0000\u0544\u0546\u0000\u0544\u0535\u0000\u0544\u053b\u0000\u054e\u0546\u0000\u0544\u053d\u0000".value; //$NON-NLS-1$ /** @@ -1716,12 +1746,11 @@ 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 * the characters in this string. - * @since Android 1.0 */ public String toUpperCase(Locale locale) { boolean turkish = "tr".equals(locale.getLanguage()); //$NON-NLS-1$ @@ -1736,8 +1765,8 @@ public final class String implements Serializable, Comparable<String>, System.arraycopy(output, 0, newoutput, 0, output.length); output = newoutput; } - char upch = !turkish ? Character.toUpperCase(ch) - : (ch != 0x69 ? Character.toUpperCase(ch) + char upch = !turkish ? toUpperCase(ch) + : (ch != 0x69 ? toUpperCase(ch) : (char) 0x130); if (ch != upch) { if (output == null) { @@ -1782,10 +1811,9 @@ 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. - * @since Android 1.0 */ public String trim() { int start = offset, last = offset + count - 1; @@ -1806,11 +1834,12 @@ 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. - * @since Android 1.0 + * @throws NullPointerException + * if {@code data} is {@code null}. */ public static String valueOf(char[] data) { return new String(data, 0, data.length); @@ -1820,7 +1849,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 @@ -1831,7 +1860,8 @@ public final class String implements Serializable, Comparable<String>, * @throws IndexOutOfBoundsException * if {@code length < 0}, {@code start < 0} or {@code start + * length > data.length} - * @since Android 1.0 + * @throws NullPointerException + * if {@code data} is {@code null}. */ public static String valueOf(char[] data, int start, int length) { return new String(data, start, length); @@ -1839,11 +1869,10 @@ 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. - * @since Android 1.0 */ public static String valueOf(char value) { String s; @@ -1858,11 +1887,10 @@ 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. - * @since Android 1.0 */ public static String valueOf(double value) { return Double.toString(value); @@ -1870,11 +1898,10 @@ 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. - * @since Android 1.0 */ public static String valueOf(float value) { return Float.toString(value); @@ -1882,11 +1909,10 @@ 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. - * @since Android 1.0 */ public static String valueOf(int value) { return Integer.toString(value); @@ -1894,11 +1920,10 @@ 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. - * @since Android 1.0 */ public static String valueOf(long value) { return Long.toString(value); @@ -1908,11 +1933,10 @@ 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"}. - * @since Android 1.0 */ public static String valueOf(Object value) { return value != null ? value.toString() : "null"; //$NON-NLS-1$ @@ -1922,11 +1946,10 @@ 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. - * @since Android 1.0 */ public static String valueOf(boolean value) { return value ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$ @@ -1935,13 +1958,15 @@ 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 * those in this string. If they are not, {@code false} will be * returned. - * @since Android 1.0 + * @throws NullPointerException + * if {@code strbuf} is {@code null}. + * @since 1.4 */ public boolean contentEquals(StringBuffer strbuf) { synchronized (strbuf) { @@ -1957,11 +1982,11 @@ public final class String implements Serializable, Comparable<String>, /** * Compares a {@code CharSequence} to this {@code String} to determine if * their contents are equal. - * + * * @param cs * the character sequence to compare to. * @return {@code true} if equal, otherwise {@code false} - * @since Android 1.0 + * @since 1.5 */ public boolean contentEquals(CharSequence cs) { if (cs == null) { @@ -1983,14 +2008,16 @@ 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}. * @throws PatternSyntaxException * if the syntax of the supplied regular expression is not * valid. - * @since Android 1.0 + * @throws NullPointerException + * if {@code expr} is {@code null}. + * @since 1.4 */ public boolean matches(String expr) { return Pattern.matches(expr, this); @@ -1999,7 +2026,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 @@ -2009,7 +2036,7 @@ public final class String implements Serializable, Comparable<String>, * if the syntax of the supplied regular expression is not * valid. * @see Pattern - * @since Android 1.0 + * @since 1.4 */ public String replaceAll(String expr, String substitute) { return Pattern.compile(expr).matcher(this).replaceAll(substitute); @@ -2018,7 +2045,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 @@ -2027,8 +2054,10 @@ public final class String implements Serializable, Comparable<String>, * @throws PatternSyntaxException * if the syntax of the supplied regular expression is not * valid. + * @throws NullPointerException + * if {@code strbuf} is {@code null}. * @see Pattern - * @since Android 1.0 + * @since 1.4 */ public String replaceFirst(String expr, String substitute) { return Pattern.compile(expr).matcher(this).replaceFirst(substitute); @@ -2036,16 +2065,18 @@ 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 * matches of the regular expression. + * @throws NullPointerException + * if {@code expr} is {@code null}. * @throws PatternSyntaxException * if the syntax of the supplied regular expression is not * valid. * @see Pattern - * @since Android 1.0 + * @since 1.4 */ public String[] split(String expr) { return Pattern.compile(expr).split(this); @@ -2055,18 +2086,20 @@ 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 * the number of entries in the resulting array. * @return an array of Strings created by separating the string along * matches of the regular expression. + * @throws NullPointerException + * if {@code expr} is {@code null}. * @throws PatternSyntaxException * if the syntax of the supplied regular expression is not * valid. * @see Pattern#split(CharSequence, int) - * @since Android 1.0 + * @since 1.4 */ public String[] split(String expr, int max) { return Pattern.compile(expr).split(this, max); @@ -2075,7 +2108,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 @@ -2085,7 +2118,7 @@ public final class String implements Serializable, Comparable<String>, * if {@code start < 0}, {@code end < 0}, {@code start > end} or * {@code end > length()}. * @see java.lang.CharSequence#subSequence(int, int) - * @since Android 1.0 + * @since 1.4 */ public CharSequence subSequence(int start, int end) { return substring(start, end); @@ -2094,7 +2127,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. @@ -2102,7 +2135,7 @@ public final class String implements Serializable, Comparable<String>, * if {@code index} is negative or greater than or equal to * {@code length()}. * @see Character#codePointAt(char[], int, int) - * @since Android 1.0 + * @since 1.5 */ public int codePointAt(int index) { if (index < 0 || index >= count) { @@ -2115,7 +2148,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. @@ -2123,7 +2156,7 @@ public final class String implements Serializable, Comparable<String>, * if {@code index} is less than 1 or greater than * {@code length()}. * @see Character#codePointBefore(char[], int, int) - * @since Android 1.0 + * @since 1.5 */ public int codePointBefore(int index) { if (index < 1 || index > count) { @@ -2136,7 +2169,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 @@ -2147,7 +2180,7 @@ public final class String implements Serializable, Comparable<String>, * endIndex} or {@code endIndex} is greater than {@code * length()}. * @see Character#codePointCount(CharSequence, int, int) - * @since Android 1.0 + * @since 1.5 */ public int codePointCount(int beginIndex, int endIndex) { if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { @@ -2160,12 +2193,12 @@ public final class String implements Serializable, Comparable<String>, /** * Determines if this {@code String} contains the sequence of characters in * the {@code CharSequence} passed. - * + * * @param cs * the character sequence to search for. * @return {@code true} if the sequence of characters are contained in this * string, otherwise {@code false}. - * @since Android 1.0 + * @since 1.5 */ public boolean contains(CharSequence cs) { if (cs == null) { @@ -2177,7 +2210,7 @@ public final class String implements Serializable, Comparable<String>, /** * Returns the index within this object that is offset from {@code index} by * {@code codePointOffset} code points. - * + * * @param index * the index within this object to calculate the offset from. * @param codePointOffset @@ -2187,7 +2220,7 @@ public final class String implements Serializable, Comparable<String>, * if {@code index} is negative or greater than {@code length()} * or if there aren't enough code points before or after {@code * index} to match {@code codePointOffset}. - * @since Android 1.0 + * @since 1.5 */ public int offsetByCodePoints(int index, int codePointOffset) { int s = index + offset; @@ -2199,16 +2232,18 @@ 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 * arguments to replace format specifiers (may be none). * @return the formatted string. - * @throws IllegalFormatException + * @throws NullPointerException + * if {@code format} is {@code null}. + * @throws java.util.IllegalFormatException * if the format is invalid. * @see java.util.Formatter - * @since Android 1.0 + * @since 1.5 */ public static String format(String format, Object... args) { return format(Locale.getDefault(), format, args); @@ -2224,7 +2259,7 @@ public final class String implements Serializable, Comparable<String>, * if you use the method only rarely, but if you rely on it for formatting a * large number of strings, consider creating and reusing your own * {@link java.util.Formatter} instance instead. - * + * * @param loc * the locale to apply; {@code null} value means no localization. * @param format @@ -2232,10 +2267,12 @@ public final class String implements Serializable, Comparable<String>, * @param args * arguments to replace format specifiers (may be none). * @return the formatted string. - * @throws IllegalFormatException + * @throws NullPointerException + * if {@code format} is {@code null}. + * @throws java.util.IllegalFormatException * if the format is invalid. * @see java.util.Formatter - * @since Android 1.0 + * @since 1.5 */ public static String format(Locale loc, String format, Object... args) { if (format == null) { diff --git a/luni/src/main/java/java/lang/StringBuffer.java b/luni/src/main/java/java/lang/StringBuffer.java index 5cb5c24..3ec43dc 100644 --- a/luni/src/main/java/java/lang/StringBuffer.java +++ b/luni/src/main/java/java/lang/StringBuffer.java @@ -39,7 +39,7 @@ import java.io.Serializable; * * @see String * @see StringBuilder - * @since Android 1.0 + * @since 1.0 */ public final class StringBuffer extends AbstractStringBuilder implements Appendable, Serializable, CharSequence { @@ -53,8 +53,6 @@ public final class StringBuffer extends AbstractStringBuilder implements /** * Constructs a new StringBuffer using the default capacity which is 16. - * - * @since Android 1.0 */ public StringBuffer() { super(); @@ -65,7 +63,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * * @param capacity * the initial capacity. - * @since Android 1.0 */ public StringBuffer(int capacity) { super(capacity); @@ -73,12 +70,13 @@ public final class StringBuffer extends AbstractStringBuilder implements /** * Constructs a new StringBuffer containing the characters in the specified - * stringy. The capacity of the new buffer will be the length of the + * string. The capacity of the new buffer will be the length of the * {@code String} plus the default capacity. * * @param string * the string content with which to initialize the new instance. - * @since Android 1.0 + * @throws NullPointerException + * if {@code string} is {@code null}. */ public StringBuffer(String string) { super(string); @@ -91,7 +89,9 @@ public final class StringBuffer extends AbstractStringBuilder implements * * @param cs * the content to initialize the instance. - * @since Android 1.0 + * @throws NullPointerException + * if {@code cs} is {@code null}. + * @since 1.5 */ public StringBuffer(CharSequence cs) { super(cs.toString()); @@ -103,13 +103,11 @@ public final class StringBuffer extends AbstractStringBuilder implements * <p> * If the argument is {@code true} the string {@code "true"} is appended, * otherwise the string {@code "false"} is appended. - * </p> - * + * * @param b * the boolean to append. * @return this StringBuffer. * @see String#valueOf(boolean) - * @since Android 1.0 */ public StringBuffer append(boolean b) { return append(b ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$ @@ -122,7 +120,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * the character to append. * @return this StringBuffer. * @see String#valueOf(char) - * @since Android 1.0 */ public synchronized StringBuffer append(char ch) { append0(ch); @@ -137,7 +134,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * the double to append. * @return this StringBuffer. * @see String#valueOf(double) - * @since Android 1.0 */ public StringBuffer append(double d) { return append(Double.toString(d)); @@ -151,7 +147,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * the float to append. * @return this StringBuffer. * @see String#valueOf(float) - * @since Android 1.0 */ public StringBuffer append(float f) { return append(Float.toString(f)); @@ -165,7 +160,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * the integer to append. * @return this StringBuffer. * @see String#valueOf(int) - * @since Android 1.0 */ public StringBuffer append(int i) { return append(Integer.toString(i)); @@ -179,7 +173,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * the long to append. * @return this StringBuffer. * @see String#valueOf(long) - * @since Android 1.0 */ public StringBuffer append(long l) { return append(Long.toString(l)); @@ -192,13 +185,11 @@ public final class StringBuffer extends AbstractStringBuilder implements * If the specified object is {@code null} the string {@code "null"} is * appended, otherwise the objects {@code toString} is used to get its * string representation. - * </p> - * + * * @param obj * the object to append (may be null). * @return this StringBuffer. * @see String#valueOf(Object) - * @since Android 1.0 */ public synchronized StringBuffer append(Object obj) { if (obj == null) { @@ -214,12 +205,10 @@ public final class StringBuffer extends AbstractStringBuilder implements * <p> * If the specified string is {@code null} the string {@code "null"} is * appended, otherwise the contents of the specified string is appended. - * </p> - * + * * @param string * the string to append (may be null). * @return this StringBuffer. - * @since Android 1.0 */ public synchronized StringBuffer append(String string) { append0(string); @@ -232,12 +221,12 @@ public final class StringBuffer extends AbstractStringBuilder implements * If the specified StringBuffer is {@code null} the string {@code "null"} * is appended, otherwise the contents of the specified StringBuffer is * appended. - * </p> - * + * * @param sb * the StringBuffer to append (may be null). * @return this StringBuffer. - * @since Android 1.0 + * + * @since 1.4 */ public synchronized StringBuffer append(StringBuffer sb) { if (sb == null) { @@ -256,7 +245,8 @@ public final class StringBuffer extends AbstractStringBuilder implements * @param chars * the character array to append. * @return this StringBuffer. - * @since Android 1.0 + * @throws NullPointerException + * if {@code chars} is {@code null}. */ public synchronized StringBuffer append(char chars[]) { append0(chars); @@ -276,7 +266,8 @@ public final class StringBuffer extends AbstractStringBuilder implements * @throws ArrayIndexOutOfBoundsException * if {@code length < 0} , {@code start < 0} or {@code start + * length > chars.length}. - * @since Android 1.0 + * @throws NullPointerException + * if {@code chars} is {@code null}. */ public synchronized StringBuffer append(char chars[], int start, int length) { append0(chars, start, length); @@ -289,12 +280,11 @@ public final class StringBuffer extends AbstractStringBuilder implements * If the specified CharSequence is {@code null} the string {@code "null"} * is appended, otherwise the contents of the specified CharSequence is * appended. - * </p> - * + * * @param s * the CharSequence to append. * @return this StringBuffer. - * @since Android 1.0 + * @since 1.5 */ public synchronized StringBuffer append(CharSequence s) { if (s == null) { @@ -310,8 +300,7 @@ public final class StringBuffer extends AbstractStringBuilder implements * <p> * If the specified CharSequence is {@code null}, then the string {@code * "null"} is used to extract a subsequence. - * </p> - * + * * @param s * the CharSequence to append. * @param start @@ -323,7 +312,7 @@ public final class StringBuffer extends AbstractStringBuilder implements * if {@code start} or {@code end} are negative, {@code start} * is greater than {@code end} or {@code end} is greater than * the length of {@code s}. - * @since Android 1.0 + * @since 1.5 */ public synchronized StringBuffer append(CharSequence s, int start, int end) { append0(s, start, end); @@ -336,13 +325,12 @@ public final class StringBuffer extends AbstractStringBuilder implements * <p> * The code point is converted to a {@code char[]} as defined by * {@link Character#toChars(int)}. - * </p> - * + * * @param codePoint * the Unicode code point to encode and append. * @return this StringBuffer. * @see Character#toChars(int) - * @since Android 1.0 + * @since 1.5 */ public StringBuffer appendCodePoint(int codePoint) { return append(Character.toChars(codePoint)); @@ -379,7 +367,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @throws StringIndexOutOfBoundsException * if {@code start < 0}, {@code start > end} or {@code end > * length()}. - * @since Android 1.0 */ public synchronized StringBuffer delete(int start, int end) { delete0(start, end); @@ -394,7 +381,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this StringBuffer. * @throws StringIndexOutOfBoundsException * if {@code location < 0} or {@code location >= length()} - * @since Android 1.0 */ public synchronized StringBuffer deleteCharAt(int location) { deleteCharAt0(location); @@ -405,6 +391,7 @@ public final class StringBuffer extends AbstractStringBuilder implements public synchronized void ensureCapacity(int min) { super.ensureCapacity(min); } + /** * Copies the requested sequence of characters to the {@code char[]} passed * starting at {@code idx}. @@ -421,7 +408,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * if {@code start < 0}, {@code end > length()}, {@code start > * end}, {@code index < 0}, {@code end - start > buffer.length - * index} - * @since Android 1.0 */ @Override public synchronized void getChars(int start, int end, char[] buffer, int idx) { @@ -443,7 +429,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws ArrayIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 */ public synchronized StringBuffer insert(int index, char ch) { insert0(index, ch); @@ -461,7 +446,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws StringIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 */ public StringBuffer insert(int index, boolean b) { return insert(index, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -478,7 +462,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws StringIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 */ public StringBuffer insert(int index, int i) { return insert(index, Integer.toString(i)); @@ -495,7 +478,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws StringIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 */ public StringBuffer insert(int index, long l) { return insert(index, Long.toString(l)); @@ -512,7 +494,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws StringIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 */ public StringBuffer insert(int index, double d) { return insert(index, Double.toString(d)); @@ -529,7 +510,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws StringIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 */ public StringBuffer insert(int index, float f) { return insert(index, Float.toString(f)); @@ -542,8 +522,7 @@ public final class StringBuffer extends AbstractStringBuilder implements * If the specified object is {@code null}, the string {@code "null"} is * inserted, otherwise the objects {@code toString} method is used to get * its string representation. - * </p> - * + * * @param index * the index at which to insert. * @param obj @@ -551,7 +530,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws StringIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 */ public StringBuffer insert(int index, Object obj) { return insert(index, obj == null ? "null" : obj.toString()); //$NON-NLS-1$ @@ -562,8 +540,7 @@ public final class StringBuffer extends AbstractStringBuilder implements * <p> * If the specified string is {@code null}, the string {@code "null"} is * inserted, otherwise the contents of the string is inserted. - * </p> - * + * * @param index * the index at which to insert. * @param string @@ -571,7 +548,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws StringIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 */ public synchronized StringBuffer insert(int index, String string) { insert0(index, string); @@ -588,7 +564,8 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws StringIndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 + * @throws NullPointerException + * if {@code chars} is {@code null}. */ public synchronized StringBuffer insert(int index, char[] chars) { insert0(index, chars); @@ -608,11 +585,12 @@ public final class StringBuffer extends AbstractStringBuilder implements * @param length * the number of characters. * @return this buffer. + * @throws NullPointerException + * if {@code chars} is {@code null}. * @throws StringIndexOutOfBoundsException * if {@code length < 0}, {@code start < 0}, {@code start + * length > chars.length}, {@code index < 0} or {@code index > * length()} - * @since Android 1.0 */ public synchronized StringBuffer insert(int index, char chars[], int start, int length) { @@ -626,8 +604,7 @@ public final class StringBuffer extends AbstractStringBuilder implements * <p> * If the specified CharSequence is {@code null}, the string {@code "null"} * is inserted, otherwise the contents of the CharSequence. - * </p> - * + * * @param index * The index at which to insert. * @param s @@ -635,7 +612,7 @@ public final class StringBuffer extends AbstractStringBuilder implements * @return this buffer. * @throws IndexOutOfBoundsException * if {@code index < 0} or {@code index > length()}. - * @since Android 1.0 + * @since 1.5 */ public synchronized StringBuffer insert(int index, CharSequence s) { insert0(index, s == null ? "null" : s.toString()); //$NON-NLS-1$ @@ -648,7 +625,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * <p> * If the specified CharSequence is {@code null}, the string {@code "null"} * is inserted, otherwise the contents of the CharSequence. - * </p> * * @param index * The index at which to insert. @@ -664,7 +640,7 @@ public final class StringBuffer extends AbstractStringBuilder implements * length, {@code start} or {@code end} are negative, {@code * start} is greater than {@code end} or {@code end} is greater * than the length of {@code s}. - * @since Android 1.0 + * @since 1.5 */ public synchronized StringBuffer insert(int index, CharSequence s, int start, int end) { @@ -697,7 +673,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * if {@code start} or {@code end} are negative, {@code start} * is greater than {@code end} or {@code end} is greater than * the length of {@code s}. - * @since Android 1.0 */ public synchronized StringBuffer replace(int start, int end, String string) { replace0(start, end, string); @@ -708,7 +683,6 @@ public final class StringBuffer extends AbstractStringBuilder implements * Reverses the order of characters in this buffer. * * @return this buffer. - * @since Android 1.0 */ public synchronized StringBuffer reverse() { reverse0(); diff --git a/luni/src/main/java/java/lang/StringBuilder.java b/luni/src/main/java/java/lang/StringBuilder.java index d62f900..12d401f 100644 --- a/luni/src/main/java/java/lang/StringBuilder.java +++ b/luni/src/main/java/java/lang/StringBuilder.java @@ -32,13 +32,13 @@ import java.io.Serializable; * StringBuilder}, so that, like {@code StringBuffer}s, they can be used in * chaining method calls together. For example, {@code new StringBuilder("One * should ").append("always strive ").append("to achieve Harmony")}. - * </p> * * @see CharSequence * @see Appendable * @see StringBuffer * @see String - * @since Android 1.0 + * + * @since 1.5 */ public final class StringBuilder extends AbstractStringBuilder implements Appendable, CharSequence, Serializable { @@ -49,7 +49,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * Constructs an instance with an initial capacity of {@code 16}. * * @see #capacity() - * @since Android 1.0 */ public StringBuilder() { super(); @@ -57,13 +56,12 @@ public final class StringBuilder extends AbstractStringBuilder implements /** * Constructs an instance with the specified capacity. - * + * * @param capacity * the initial capacity to use. * @throws NegativeArraySizeException * if the specified {@code capacity} is negative. * @see #capacity() - * @since Android 1.0 */ public StringBuilder(int capacity) { super(capacity); @@ -73,10 +71,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Constructs an instance that's initialized with the contents of the * specified {@code CharSequence}. The capacity of the new builder will be * the length of the {@code CharSequence} plus 16. - * + * * @param seq * the {@code CharSequence} to copy into the builder. - * @since Android 1.0 + * @throws NullPointerException + * if {@code seq} is {@code null}. */ public StringBuilder(CharSequence seq) { super(seq.toString()); @@ -86,10 +85,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Constructs an instance that's initialized with the contents of the * specified {@code String}. The capacity of the new builder will be the * length of the {@code String} plus 16. - * + * * @param str * the {@code String} to copy into the builder. - * @since Android 1.0 + * @throws NullPointerException + * if {@code str} is {@code null}. */ public StringBuilder(String str) { super(str); @@ -99,12 +99,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code boolean} value. * The {@code boolean} value is converted to a String according to the rule * defined by {@link String#valueOf(boolean)}. - * + * * @param b * the {@code boolean} value to append. * @return this builder. * @see String#valueOf(boolean) - * @since Android 1.0 */ public StringBuilder append(boolean b) { append0(b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -115,12 +114,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code char} value. * The {@code char} value is converted to a string according to the rule * defined by {@link String#valueOf(char)}. - * + * * @param c * the {@code char} value to append. * @return this builder. * @see String#valueOf(char) - * @since Android 1.0 */ public StringBuilder append(char c) { append0(c); @@ -131,12 +129,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code int} value. The * {@code int} value is converted to a string according to the rule defined * by {@link String#valueOf(int)}. - * + * * @param i * the {@code int} value to append. * @return this builder. * @see String#valueOf(int) - * @since Android 1.0 */ public StringBuilder append(int i) { append0(Integer.toString(i)); @@ -147,12 +144,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code long} value. * The {@code long} value is converted to a string according to the rule * defined by {@link String#valueOf(long)}. - * + * * @param lng * the {@code long} value. * @return this builder. * @see String#valueOf(long) - * @since Android 1.0 */ public StringBuilder append(long lng) { append0(Long.toString(lng)); @@ -163,12 +159,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code float} value. * The {@code float} value is converted to a string according to the rule * defined by {@link String#valueOf(float)}. - * + * * @param f * the {@code float} value to append. * @return this builder. * @see String#valueOf(float) - * @since Android 1.0 */ public StringBuilder append(float f) { append0(Float.toString(f)); @@ -179,12 +174,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code double} value. * The {@code double} value is converted to a string according to the rule * defined by {@link String#valueOf(double)}. - * + * * @param d * the {@code double} value to append. * @return this builder. * @see String#valueOf(double) - * @since Android 1.0 */ public StringBuilder append(double d) { append0(Double.toString(d)); @@ -195,12 +189,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code Object}. * The {@code Object} value is converted to a string according to the rule * defined by {@link String#valueOf(Object)}. - * + * * @param obj * the {@code Object} to append. * @return this builder. * @see String#valueOf(Object) - * @since Android 1.0 */ public StringBuilder append(Object obj) { if (obj == null) { @@ -214,11 +207,10 @@ public final class StringBuilder extends AbstractStringBuilder implements /** * Appends the contents of the specified string. If the string is {@code * null}, then the string {@code "null"} is appended. - * + * * @param str * the string to append. * @return this builder. - * @since Android 1.0 */ public StringBuilder append(String str) { append0(str); @@ -229,11 +221,10 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the contents of the specified {@code StringBuffer}. If the * StringBuffer is {@code null}, then the string {@code "null"} is * appended. - * + * * @param sb * the {@code StringBuffer} to append. * @return this builder. - * @since Android 1.0 */ public StringBuilder append(StringBuffer sb) { if (sb == null) { @@ -248,12 +239,11 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code char[]}. * The {@code char[]} is converted to a string according to the rule * defined by {@link String#valueOf(char[])}. - * + * * @param ch * the {@code char[]} to append.. * @return this builder. * @see String#valueOf(char[]) - * @since Android 1.0 */ public StringBuilder append(char[] ch) { append0(ch); @@ -264,7 +254,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified subset of the {@code * char[]}. The {@code char[]} value is converted to a String according to * the rule defined by {@link String#valueOf(char[],int,int)}. - * + * * @param str * the {@code char[]} to append. * @param offset @@ -276,7 +266,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} and {@code len} do not specify a valid * subsequence. * @see String#valueOf(char[],int,int) - * @since Android 1.0 */ public StringBuilder append(char[] str, int offset, int len) { append0(str, offset, len); @@ -287,11 +276,10 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified {@code CharSequence}. * If the {@code CharSequence} is {@code null}, then the string {@code * "null"} is appended. - * + * * @param csq * the {@code CharSequence} to append. * @return this builder. - * @since Android 1.0 */ public StringBuilder append(CharSequence csq) { if (csq == null) { @@ -306,7 +294,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * Appends the string representation of the specified subsequence of the * {@code CharSequence}. If the {@code CharSequence} is {@code null}, then * the string {@code "null"} is used to extract the subsequence from. - * + * * @param csq * the {@code CharSequence} to append. * @param start @@ -318,7 +306,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code start} or {@code end} are negative, {@code start} * is greater than {@code end} or {@code end} is greater than * the length of {@code csq}. - * @since Android 1.0 */ public StringBuilder append(CharSequence csq, int start, int end) { append0(csq, start, end); @@ -328,12 +315,11 @@ public final class StringBuilder extends AbstractStringBuilder implements /** * Appends the encoded Unicode code point. The code point is converted to a * {@code char[]} as defined by {@link Character#toChars(int)}. - * + * * @param codePoint * the Unicode code point to encode and append. * @return this builder. * @see Character#toChars(int) - * @since Android 1.0 */ public StringBuilder appendCodePoint(int codePoint) { append0(Character.toChars(codePoint)); @@ -352,7 +338,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * @throws StringIndexOutOfBoundsException * if {@code start} is less than zero, greater than the current * length or greater than {@code end}. - * @since Android 1.0 */ public StringBuilder delete(int start, int end) { delete0(start, end); @@ -369,7 +354,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * @throws StringIndexOutOfBoundsException * if {@code index} is less than zero or is greater than or * equal to the current length. - * @since Android 1.0 */ public StringBuilder deleteCharAt(int index) { deleteCharAt0(index); @@ -381,7 +365,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * at the specified {@code offset}. The {@code boolean} value is converted * to a string according to the rule defined by * {@link String#valueOf(boolean)}. - * + * * @param offset * the index to insert at. * @param b @@ -391,7 +375,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {@code length}. * @see String#valueOf(boolean) - * @since Android 1.0 */ public StringBuilder insert(int offset, boolean b) { insert0(offset, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -402,7 +385,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * Inserts the string representation of the specified {@code char} value at * the specified {@code offset}. The {@code char} value is converted to a * string according to the rule defined by {@link String#valueOf(char)}. - * + * * @param offset * the index to insert at. * @param c @@ -412,7 +395,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {@code length()}. * @see String#valueOf(char) - * @since Android 1.0 */ public StringBuilder insert(int offset, char c) { insert0(offset, c); @@ -423,7 +405,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * Inserts the string representation of the specified {@code int} value at * the specified {@code offset}. The {@code int} value is converted to a * String according to the rule defined by {@link String#valueOf(int)}. - * + * * @param offset * the index to insert at. * @param i @@ -433,7 +415,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {@code length()}. * @see String#valueOf(int) - * @since Android 1.0 */ public StringBuilder insert(int offset, int i) { insert0(offset, Integer.toString(i)); @@ -444,7 +425,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * Inserts the string representation of the specified {@code long} value at * the specified {@code offset}. The {@code long} value is converted to a * String according to the rule defined by {@link String#valueOf(long)}. - * + * * @param offset * the index to insert at. * @param l @@ -454,7 +435,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {code length()}. * @see String#valueOf(long) - * @since Android 1.0 */ public StringBuilder insert(int offset, long l) { insert0(offset, Long.toString(l)); @@ -465,7 +445,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * Inserts the string representation of the specified {@code float} value at * the specified {@code offset}. The {@code float} value is converted to a * string according to the rule defined by {@link String#valueOf(float)}. - * + * * @param offset * the index to insert at. * @param f @@ -475,7 +455,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {@code length()}. * @see String#valueOf(float) - * @since Android 1.0 */ public StringBuilder insert(int offset, float f) { insert0(offset, Float.toString(f)); @@ -487,7 +466,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * at the specified {@code offset}. The {@code double} value is converted * to a String according to the rule defined by * {@link String#valueOf(double)}. - * + * * @param offset * the index to insert at. * @param d @@ -497,7 +476,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {@code length()}. * @see String#valueOf(double) - * @since Android 1.0 */ public StringBuilder insert(int offset, double d) { insert0(offset, Double.toString(d)); @@ -508,7 +486,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * Inserts the string representation of the specified {@code Object} at the * specified {@code offset}. The {@code Object} value is converted to a * String according to the rule defined by {@link String#valueOf(Object)}. - * + * * @param offset * the index to insert at. * @param obj @@ -518,7 +496,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {@code length()}. * @see String#valueOf(Object) - * @since Android 1.0 */ public StringBuilder insert(int offset, Object obj) { insert0(offset, obj == null ? "null" : obj.toString()); //$NON-NLS-1$ @@ -528,7 +505,7 @@ public final class StringBuilder extends AbstractStringBuilder implements /** * Inserts the specified string at the specified {@code offset}. If the * specified string is null, then the String {@code "null"} is inserted. - * + * * @param offset * the index to insert at. * @param str @@ -537,7 +514,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * @throws StringIndexOutOfBoundsException * if {@code offset} is negative or greater than the current * {@code length()}. - * @since Android 1.0 */ public StringBuilder insert(int offset, String str) { insert0(offset, str); @@ -548,7 +524,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * Inserts the string representation of the specified {@code char[]} at the * specified {@code offset}. The {@code char[]} value is converted to a * String according to the rule defined by {@link String#valueOf(char[])}. - * + * * @param offset * the index to insert at. * @param ch @@ -558,7 +534,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {@code length()}. * @see String#valueOf(char[]) - * @since Android 1.0 */ public StringBuilder insert(int offset, char[] ch) { insert0(offset, ch); @@ -570,7 +545,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * {@code char[]} at the specified {@code offset}. The {@code char[]} value * is converted to a String according to the rule defined by * {@link String#valueOf(char[],int,int)}. - * + * * @param offset * the index to insert at. * @param str @@ -585,7 +560,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * {@code length()}, or {@code strOffset} and {@code strLen} do * not specify a valid subsequence. * @see String#valueOf(char[],int,int) - * @since Android 1.0 */ public StringBuilder insert(int offset, char[] str, int strOffset, int strLen) { @@ -598,7 +572,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * at the specified {@code offset}. The {@code CharSequence} is converted * to a String as defined by {@link CharSequence#toString()}. If {@code s} * is {@code null}, then the String {@code "null"} is inserted. - * + * * @param offset * the index to insert at. * @param s @@ -608,7 +582,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * if {@code offset} is negative or greater than the current * {@code length()}. * @see CharSequence#toString() - * @since Android 1.0 */ public StringBuilder insert(int offset, CharSequence s) { insert0(offset, s == null ? "null" : s.toString()); //$NON-NLS-1$ @@ -622,7 +595,7 @@ public final class StringBuilder extends AbstractStringBuilder implements * {@link CharSequence#subSequence(int, int)}. If the {@code CharSequence} * is {@code null}, then the string {@code "null"} is used to determine the * subsequence. - * + * * @param offset * the index to insert at. * @param s @@ -637,7 +610,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * {@code length()}, or {@code start} and {@code end} do not * specify a valid subsequence. * @see CharSequence#subSequence(int, int) - * @since Android 1.0 */ public StringBuilder insert(int offset, CharSequence s, int start, int end) { insert0(offset, s, start, end); @@ -658,7 +630,8 @@ public final class StringBuilder extends AbstractStringBuilder implements * @throws StringIndexOutOfBoundsException * if {@code start} is negative, greater than the current * {@code length()} or greater than {@code end}. - * @since Android 1.0 + * @throws NullPointerException + * if {@code str} is {@code null}. */ public StringBuilder replace(int start, int end, String str) { replace0(start, end, str); @@ -669,7 +642,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * Reverses the order of characters in this builder. * * @return this buffer. - * @since Android 1.0 */ public StringBuilder reverse() { reverse0(); @@ -680,7 +652,6 @@ public final class StringBuilder extends AbstractStringBuilder implements * Returns the contents of this builder. * * @return the string representation of the data in this builder. - * @since Android 1.0 */ @Override public String toString() { @@ -695,7 +666,7 @@ public final class StringBuilder extends AbstractStringBuilder implements /** * Reads the state of a {@code StringBuilder} from the passed stream and * restores it to this instance. - * + * * @param in * the stream to read the state from. * @throws IOException @@ -713,7 +684,7 @@ public final class StringBuilder extends AbstractStringBuilder implements /** * Writes the state of this object to the stream passed. - * + * * @param out * the stream to write the state to. * @throws IOException diff --git a/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java b/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java index a2fca9a..b3fbf7e 100644 --- a/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java +++ b/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java @@ -23,8 +23,6 @@ import org.apache.harmony.luni.util.Msg; /** * Thrown when the a string is indexed with a value less than zero, or greater * than or equal to the size of the array. - * - * @since Android 1.0 */ public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException { @@ -33,8 +31,6 @@ public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException { /** * Constructs a new {@code StringIndexOutOfBoundsException} that includes * the current stack trace. - * - * @since Android 1.0 */ public StringIndexOutOfBoundsException() { super(); @@ -47,7 +43,6 @@ public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException { * * @param index * the index which is out of bounds. - * @since Android 1.0 */ public StringIndexOutOfBoundsException(int index) { super(Msg.getString("K0055", index)); //$NON-NLS-1$ @@ -59,7 +54,6 @@ public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public StringIndexOutOfBoundsException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/SuppressWarnings.java b/luni/src/main/java/java/lang/SuppressWarnings.java index d3b4289..1ff0e42 100644 --- a/luni/src/main/java/java/lang/SuppressWarnings.java +++ b/luni/src/main/java/java/lang/SuppressWarnings.java @@ -1,12 +1,12 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed 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 - * +/* 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. @@ -16,15 +16,9 @@ package java.lang; -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.LOCAL_VARIABLE; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** @@ -35,18 +29,17 @@ import java.lang.annotation.Target; * <p> * It is recommended that programmers always use this annotation on the most * deeply nested element where it is actually needed. - * </p> - * - * @since Android 1.0 + * + * @since 1.5 */ -@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE}) -@Retention(value=SOURCE) -public @interface SuppressWarnings -{ +@Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, + ElementType.PARAMETER, ElementType.CONSTRUCTOR, + ElementType.LOCAL_VARIABLE }) +@Retention(RetentionPolicy.SOURCE) +public @interface SuppressWarnings { + /** * The list of warnings a compiler should not issue. - * - * @since Android 1.0 */ - String[] value(); + public String[] value(); } diff --git a/luni/src/main/java/java/lang/ThreadDeath.java b/luni/src/main/java/java/lang/ThreadDeath.java index e4f2cc2..3006865 100644 --- a/luni/src/main/java/java/lang/ThreadDeath.java +++ b/luni/src/main/java/java/lang/ThreadDeath.java @@ -20,8 +20,6 @@ package java.lang; /** * ThreadDeath is thrown when a thread stops executing. It is used to aid in the * orderly unrolling of the thread's stack (eg. cleanup of monitors). - * - * @since Android 1.0 */ public class ThreadDeath extends Error { @@ -31,8 +29,6 @@ public class ThreadDeath extends Error { * Constructs a new instance of this class. Note that in the case of * ThreadDeath, the stacktrace may <em>not</em> be filled in a way which * allows a stack trace to be printed. - * - * @since Android 1.0 */ public ThreadDeath() { } diff --git a/luni/src/main/java/java/lang/ThreadLocal.java b/luni/src/main/java/java/lang/ThreadLocal.java index 58e85be..90250b3 100644 --- a/luni/src/main/java/java/lang/ThreadLocal.java +++ b/luni/src/main/java/java/lang/ThreadLocal.java @@ -16,6 +16,12 @@ package java.lang; +/* + * Android's thread local is not derived from Harmony's classlib. It is used in + * Harmony's DRLVM, however, whose source is here: + * http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/ + */ + import java.lang.ref.WeakReference; import java.lang.ref.Reference; import java.util.concurrent.atomic.AtomicInteger; @@ -29,7 +35,6 @@ import java.util.concurrent.atomic.AtomicInteger; * * @see java.lang.Thread * @author Bob Lee - * @since Android 1.0 */ public class ThreadLocal<T> { @@ -97,6 +102,8 @@ public class ThreadLocal<T> { * is followed by a {@link #get()} before a {@link #set}, * {@code #get()} will call {@link #initialValue()} and create a new * entry with the resulting value. + * + * @since 1.5 */ public void remove() { Thread currentThread = Thread.currentThread(); diff --git a/luni/src/main/java/java/lang/TypeNotPresentException.java b/luni/src/main/java/java/lang/TypeNotPresentException.java index 11ef4c1..d96f766 100644 --- a/luni/src/main/java/java/lang/TypeNotPresentException.java +++ b/luni/src/main/java/java/lang/TypeNotPresentException.java @@ -21,8 +21,8 @@ package java.lang; * type through a string that contains the type's name and the type cannot be * found. This exception is an unchecked alternative to * {@link java.lang.ClassNotFoundException}. - * - * @since Android 1.0 + * + * @since 1.5 */ public class TypeNotPresentException extends RuntimeException { private static final long serialVersionUID = -5101214195716534496L; @@ -38,7 +38,6 @@ public class TypeNotPresentException extends RuntimeException { * the fully qualified name of the type that could not be found. * @param cause * the optional cause of this exception, may be {@code null}. - * @since Android 1.0 */ public TypeNotPresentException(String typeName, Throwable cause) { super("Type " + typeName + " not present", cause); diff --git a/luni/src/main/java/java/lang/UnknownError.java b/luni/src/main/java/java/lang/UnknownError.java index a98a5d4..ecdb008 100644 --- a/luni/src/main/java/java/lang/UnknownError.java +++ b/luni/src/main/java/java/lang/UnknownError.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when the virtual machine must throw an error which does not match any * known exceptional condition. - * - * @since Android 1.0 */ public class UnknownError extends VirtualMachineError { @@ -30,8 +28,6 @@ public class UnknownError extends VirtualMachineError { /** * Constructs a new {@code UnknownError} that includes the current stack * trace. - * - * @since Android 1.0 */ public UnknownError() { super(); @@ -43,7 +39,6 @@ public class UnknownError extends VirtualMachineError { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public UnknownError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/UnsatisfiedLinkError.java b/luni/src/main/java/java/lang/UnsatisfiedLinkError.java index 489601f..12429a0 100644 --- a/luni/src/main/java/java/lang/UnsatisfiedLinkError.java +++ b/luni/src/main/java/java/lang/UnsatisfiedLinkError.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when an attempt is made to invoke a native for which an implementation * could not be found. - * - * @since Android 1.0 */ public class UnsatisfiedLinkError extends LinkageError { @@ -30,8 +28,6 @@ public class UnsatisfiedLinkError extends LinkageError { /** * Constructs a new {@code UnsatisfiedLinkError} that includes the current * stack trace. - * - * @since Android 1.0 */ public UnsatisfiedLinkError() { super(); @@ -43,7 +39,6 @@ public class UnsatisfiedLinkError extends LinkageError { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public UnsatisfiedLinkError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/UnsupportedClassVersionError.java b/luni/src/main/java/java/lang/UnsupportedClassVersionError.java index 3ee8f8c..7670f70 100644 --- a/luni/src/main/java/java/lang/UnsupportedClassVersionError.java +++ b/luni/src/main/java/java/lang/UnsupportedClassVersionError.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when an attempt is made to load a class with a format version that is * not supported by the virtual machine. - * - * @since Android 1.0 */ public class UnsupportedClassVersionError extends ClassFormatError { @@ -30,8 +28,6 @@ public class UnsupportedClassVersionError extends ClassFormatError { /** * Constructs a new {@code UnsupportedClassVersionError} that includes the * current stack trace. - * - * @since Android 1.0 */ public UnsupportedClassVersionError() { super(); @@ -43,7 +39,6 @@ public class UnsupportedClassVersionError extends ClassFormatError { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public UnsupportedClassVersionError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/UnsupportedOperationException.java b/luni/src/main/java/java/lang/UnsupportedOperationException.java index 8b78226..ac27518 100644 --- a/luni/src/main/java/java/lang/UnsupportedOperationException.java +++ b/luni/src/main/java/java/lang/UnsupportedOperationException.java @@ -19,8 +19,6 @@ package java.lang; /** * Thrown when an unsupported operation is attempted. - * - * @since Android 1.0 */ public class UnsupportedOperationException extends RuntimeException { @@ -29,13 +27,8 @@ public class UnsupportedOperationException extends RuntimeException { /** * Constructs a new {@code UnsupportedOperationException} that includes the * current stack trace. - * - * @since Android 1.0 */ public UnsupportedOperationException() { - // BEGIN android-added - super(); - // END android-added } /** @@ -44,7 +37,6 @@ public class UnsupportedOperationException extends RuntimeException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public UnsupportedOperationException(String detailMessage) { super(detailMessage); @@ -58,7 +50,7 @@ public class UnsupportedOperationException extends RuntimeException { * the detail message for this exception. * @param cause * the optional cause of this exception, may be {@code null}. - * @since Android 1.0 + * @since 1.5 */ public UnsupportedOperationException(String message, Throwable cause) { super(message, cause); @@ -70,7 +62,7 @@ public class UnsupportedOperationException extends RuntimeException { * * @param cause * the optional cause of this exception, may be {@code null}. - * @since Android 1.0 + * @since 1.5 */ public UnsupportedOperationException(Throwable cause) { super((cause == null ? null : cause.toString()), cause); diff --git a/luni/src/main/java/java/lang/VerifyError.java b/luni/src/main/java/java/lang/VerifyError.java index ddf4de7..35cf34b 100644 --- a/luni/src/main/java/java/lang/VerifyError.java +++ b/luni/src/main/java/java/lang/VerifyError.java @@ -20,8 +20,6 @@ package java.lang; /** * Thrown when the virtual machine notices that an attempt is made to load a * class which does not pass the class verification phase. - * - * @since Android 1.0 */ public class VerifyError extends LinkageError { @@ -30,8 +28,6 @@ public class VerifyError extends LinkageError { /** * Constructs a new {@code VerifyError} that includes the current stack * trace. - * - * @since Android 1.0 */ public VerifyError() { super(); @@ -43,7 +39,6 @@ public class VerifyError extends LinkageError { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public VerifyError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/VirtualMachineError.java b/luni/src/main/java/java/lang/VirtualMachineError.java index 107f562..87a6342 100644 --- a/luni/src/main/java/java/lang/VirtualMachineError.java +++ b/luni/src/main/java/java/lang/VirtualMachineError.java @@ -23,7 +23,6 @@ package java.lang; * during the operation of the virtual machine. * * @see Error - * @since Android 1.0 */ public abstract class VirtualMachineError extends Error { @@ -32,8 +31,6 @@ public abstract class VirtualMachineError extends Error { /** * Constructs a new {@code VirtualMachineError} that includes the current * stack trace. - * - * @since Android 1.0 */ public VirtualMachineError() { super(); @@ -45,7 +42,6 @@ public abstract class VirtualMachineError extends Error { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public VirtualMachineError(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/lang/Void.java b/luni/src/main/java/java/lang/Void.java index 8d06b64..4132e41 100644 --- a/luni/src/main/java/java/lang/Void.java +++ b/luni/src/main/java/java/lang/Void.java @@ -21,15 +21,13 @@ import java.lang.reflect.Method; /** * Placeholder class for the Java keyword {@code void}. - * - * @since Android 1.0 + * + * @since 1.1 */ public final class Void extends Object { /** * The {@link Class} object that represents the primitive type {@code void}. - * - * @since Android 1.0 */ public static final Class<Void> TYPE = lookupType(); @@ -48,6 +46,6 @@ public final class Void extends Object { return (Class<Void>) voidType; } - private Void() { - } + private Void() { + } } diff --git a/luni/src/main/java/java/lang/ref/ReferenceQueue.java b/luni/src/main/java/java/lang/ref/ReferenceQueue.java index eb6280b..ac6d695 100644 --- a/luni/src/main/java/java/lang/ref/ReferenceQueue.java +++ b/luni/src/main/java/java/lang/ref/ReferenceQueue.java @@ -16,25 +16,24 @@ */ // BEGIN android-note -// This implementation was changed significantly. Changes where not marked. +// This implementation is quite different from Harmony. Changes are not marked. // END android-note + package java.lang.ref; /** * The {@code ReferenceQueue} is the container on which reference objects are * enqueued when the garbage collector detects the reachability type specified * for the referent. - * - * @since Android 1.0 + * + * @since 1.2 */ public class ReferenceQueue<T> { - + private Reference<? extends T> head; /** * Constructs a new instance of this class. - * - * @since Android 1.0 */ public ReferenceQueue() { super(); @@ -43,11 +42,9 @@ public class ReferenceQueue<T> { /** * Returns the next available reference from the queue, removing it in the * process. Does not wait for a reference to become available. - * + * * @return the next available reference, or {@code null} if no reference is * immediately available - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public synchronized Reference<? extends T> poll() { @@ -73,37 +70,31 @@ public class ReferenceQueue<T> { /** * Returns the next available reference from the queue, removing it in the * process. Waits indefinitely for a reference to become available. - * + * * @return the next available reference - * + * * @throws InterruptedException - * if the blocking call was interrupted for some reason - * - * @since Android 1.0 + * if the blocking call was interrupted for some reason */ public Reference<? extends T> remove() throws InterruptedException { return remove(0L); } - + /** * Returns the next available reference from the queue, removing it in the * process. Waits for a reference to become available or the given timeout * period to elapse, whichever happens first. - * + * * @param timeout * maximum time (in ms) to spend waiting for a reference object * to become available. A value of zero results in the method * waiting indefinitely. - * * @return the next available reference, or {@code null} if no reference * becomes available within the timeout period - * * @throws IllegalArgumentException * if the wait period is negative. * @throws InterruptedException - * if the blocking call was interrupted for some reason - * - * @since Android 1.0 + * if the blocking call was interrupted for some reason */ public synchronized Reference<? extends T> remove(long timeout) throws IllegalArgumentException, InterruptedException { @@ -128,20 +119,20 @@ public class ReferenceQueue<T> { } /** - * Enqueues the reference object on the receiver. - * - * @param toQueue + * Enqueue the reference object on the receiver. + * + * @param reference * reference object to be enqueued. - * - * @since Android 1.0 + * @return boolean true if reference is enqueued. false if reference failed + * to enqueue. */ - synchronized void enqueue(Reference<? extends T> toQueue) { + synchronized void enqueue(Reference<? extends T> reference) { if (head == null) { - toQueue.queueNext = toQueue; + reference.queueNext = reference; } else { - toQueue.queueNext = head; + reference.queueNext = head; } - head = toQueue; + head = reference; notify(); } } diff --git a/luni/src/main/java/java/lang/reflect/AnnotatedElement.java b/luni/src/main/java/java/lang/reflect/AnnotatedElement.java index 1f081b9..426daba 100644 --- a/luni/src/main/java/java/lang/reflect/AnnotatedElement.java +++ b/luni/src/main/java/java/lang/reflect/AnnotatedElement.java @@ -21,8 +21,8 @@ import java.lang.annotation.Annotation; /** * This interface provides reflective access to annotation information. - * - * @since Android 1.0 + * + * @since 1.5 */ public interface AnnotatedElement { @@ -33,13 +33,9 @@ public interface AnnotatedElement { * * @param annotationType * the type of the annotation to search for - * * @return the annotation with the specified type or {@code null} - * * @throws NullPointerException * if {@code annotationType} is {@code null} - * - * @since Android 1.0 */ <T extends Annotation> T getAnnotation(Class<T> annotationType); @@ -49,8 +45,6 @@ public interface AnnotatedElement { * returns a zero length array. * * @return an array of all annotations for this element - * - * @since Android 1.0 */ Annotation[] getAnnotations(); @@ -60,8 +54,6 @@ public interface AnnotatedElement { * method returns a zero length array. * * @return an array of annotations declared for this element - * - * @since Android 1.0 */ Annotation[] getDeclaredAnnotations(); @@ -71,13 +63,9 @@ public interface AnnotatedElement { * * @param annotationType * the type of the annotation to search for - * * @return {@code true} if the annotation exists, {@code false} otherwise - * * @throws NullPointerException * if {@code annotationType} is {@code null} - * - * @since Android 1.0 */ boolean isAnnotationPresent(Class<? extends Annotation> annotationType); } diff --git a/luni/src/main/java/java/lang/reflect/GenericArrayType.java b/luni/src/main/java/java/lang/reflect/GenericArrayType.java index 81fb39f..56f873d 100644 --- a/luni/src/main/java/java/lang/reflect/GenericArrayType.java +++ b/luni/src/main/java/java/lang/reflect/GenericArrayType.java @@ -21,22 +21,19 @@ package java.lang.reflect; * This interface represents an array type with a component type that is either * a parameterized type or a type variable. * - * @since Android 1.0 + * @since 1.5 */ public interface GenericArrayType extends Type { - /** * Returns the component type of this array. * * @return the component type of this array - * + * * @throws TypeNotPresentException * if the component type points to a missing type * @throws MalformedParameterizedTypeException * if the component type points to a type that cannot be * instantiated for some reason - * - * @since Android 1.0 */ Type getGenericComponentType(); -} +}
\ No newline at end of file diff --git a/luni/src/main/java/java/lang/reflect/GenericDeclaration.java b/luni/src/main/java/java/lang/reflect/GenericDeclaration.java index c7cedcf..880350b 100644 --- a/luni/src/main/java/java/lang/reflect/GenericDeclaration.java +++ b/luni/src/main/java/java/lang/reflect/GenericDeclaration.java @@ -18,8 +18,8 @@ package java.lang.reflect; /** * Common interface for language constructs that declare type parameters. - * - * @since Android 1.0 + * + * @since 1.5 */ public interface GenericDeclaration { @@ -28,11 +28,8 @@ public interface GenericDeclaration { * no type parameters, this method returns a zero length array. * * @return the declared type parameters in declaration order - * * @throws GenericSignatureFormatError * if the signature is malformed - * - * @since Android 1.0 */ TypeVariable<?>[] getTypeParameters(); } diff --git a/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java b/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java index bb901fd..c113006 100644 --- a/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java +++ b/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java @@ -20,8 +20,8 @@ package java.lang.reflect; /** * Indicates that a malformed signature has been encountered via a reflective * method. - * - * @since Android 1.0 + * + * @since 1.5 */ public class GenericSignatureFormatError extends ClassFormatError { @@ -29,8 +29,6 @@ public class GenericSignatureFormatError extends ClassFormatError { /** * Constructs a new {@code GenericSignatureFormatError} instance. - * - * @since Android 1.0 */ public GenericSignatureFormatError() { super(); diff --git a/luni/src/main/java/java/lang/reflect/InvocationHandler.java b/luni/src/main/java/java/lang/reflect/InvocationHandler.java index b28d535..fe3eaba 100644 --- a/luni/src/main/java/java/lang/reflect/InvocationHandler.java +++ b/luni/src/main/java/java/lang/reflect/InvocationHandler.java @@ -21,8 +21,6 @@ package java.lang.reflect; * Implementors of this interface dispatch methods invoked on proxy instances. * * @see Proxy - * - * @since Android 1.0 */ public interface InvocationHandler { @@ -58,8 +56,6 @@ public interface InvocationHandler { * The exception must match one of the declared exception types * of the invoked method or any unchecked exception type. If not * then an {@code UndeclaredThrowableException} is thrown - * - * @since Android 1.0 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; diff --git a/luni/src/main/java/java/lang/reflect/InvocationTargetException.java b/luni/src/main/java/java/lang/reflect/InvocationTargetException.java index 2d69135..6dc44e7 100644 --- a/luni/src/main/java/java/lang/reflect/InvocationTargetException.java +++ b/luni/src/main/java/java/lang/reflect/InvocationTargetException.java @@ -23,8 +23,6 @@ package java.lang.reflect; * * @see Method#invoke * @see Constructor#newInstance - * - * @since Android 1.0 */ public class InvocationTargetException extends Exception { @@ -35,8 +33,6 @@ public class InvocationTargetException extends Exception { /** * Constructs a new {@code InvocationTargetException} instance with a * {@code null} cause / target exception. - * - * @since Android 1.0 */ protected InvocationTargetException() { super((Throwable) null); @@ -49,8 +45,6 @@ public class InvocationTargetException extends Exception { * @param exception * the exception which occurred while running the Method or * Constructor - * - * @since Android 1.0 */ public InvocationTargetException(Throwable exception) { super(null, exception); @@ -66,8 +60,6 @@ public class InvocationTargetException extends Exception { * @param exception * the exception which occurred while running the Method or * Constructor - * - * @since Android 1.0 */ public InvocationTargetException(Throwable exception, String detailMessage) { super(detailMessage, exception); @@ -78,8 +70,6 @@ public class InvocationTargetException extends Exception { * Returns the target exception, which may be {@code null}. * * @return the target exception - * - * @since Android 1.0 */ public Throwable getTargetException() { return target; @@ -89,8 +79,6 @@ public class InvocationTargetException extends Exception { * Returns the cause of this exception, which may be {@code null}. * * @return the cause of this exception - * - * @since Android 1.0 */ @Override public Throwable getCause() { diff --git a/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java b/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java index 7dfbc6f..71f2819 100644 --- a/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java +++ b/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java @@ -21,7 +21,7 @@ package java.lang.reflect; * Indicates that a malformed parameterized type has been encountered by a * reflective method. * - * @since Android 1.0 + * @since 1.5 */ public class MalformedParameterizedTypeException extends RuntimeException { @@ -29,8 +29,6 @@ public class MalformedParameterizedTypeException extends RuntimeException { /** * Constructs a new {@code MalformedParameterizedTypeException} instance. - * - * @since Android 1.0 */ public MalformedParameterizedTypeException() { super(); diff --git a/luni/src/main/java/java/lang/reflect/Member.java b/luni/src/main/java/java/lang/reflect/Member.java index fb0739f..a91e108 100644 --- a/luni/src/main/java/java/lang/reflect/Member.java +++ b/luni/src/main/java/java/lang/reflect/Member.java @@ -8,11 +8,11 @@ * * 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. + * 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 java.lang.reflect; @@ -23,28 +23,22 @@ package java.lang.reflect; * @see Field * @see Constructor * @see Method - * - * @since Android 1.0 */ public interface Member { /** * Designates all public members of a class or interface (including * inherited members). - * + * * @see java.lang.SecurityManager#checkMemberAccess - * - * @since Android 1.0 */ public static final int PUBLIC = 0; /** * Designates all declared members of a class or interface (without * inherited members). - * + * * @see java.lang.SecurityManager#checkMemberAccess - * - * @since Android 1.0 */ public static final int DECLARED = 1; @@ -52,8 +46,6 @@ public interface Member { * Returns the class that declares this member. * * @return the declaring class - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") Class getDeclaringClass(); @@ -63,10 +55,8 @@ public interface Member { * be used to decode the result. * * @return the modifiers for this member - * + * * @see Modifier - * - * @since Android 1.0 */ int getModifiers(); @@ -74,8 +64,6 @@ public interface Member { * Returns the name of this member. * * @return the name of this member - * - * @since Android 1.0 */ String getName(); @@ -84,8 +72,6 @@ public interface Member { * introduced by the compiler). * * @return {@code true} if this member is synthetic, {@code false} otherwise - * - * @since Android 1.0 */ boolean isSynthetic(); } diff --git a/luni/src/main/java/java/lang/reflect/Modifier.java b/luni/src/main/java/java/lang/reflect/Modifier.java index ed201aa..0f9dc98 100644 --- a/luni/src/main/java/java/lang/reflect/Modifier.java +++ b/luni/src/main/java/java/lang/reflect/Modifier.java @@ -22,100 +22,74 @@ package java.lang.reflect; * * @see Class#getModifiers() * @see Member#getModifiers() - * - * @since Android 1.0 */ public class Modifier { /** * The {@code int} value representing the {@code public} * modifier. - * - * @since Android 1.0 */ public static final int PUBLIC = 0x1; /** * The {@code int} value representing the {@code private} * modifier. - * - * @since Android 1.0 */ public static final int PRIVATE = 0x2; /** * The {@code int} value representing the {@code protected} * modifier. - * - * @since Android 1.0 */ public static final int PROTECTED = 0x4; /** * The {@code int} value representing the {@code static} modifier. - * - * @since Android 1.0 */ public static final int STATIC = 0x8; /** * The {@code int} value representing the {@code final} modifier. - * - * @since Android 1.0 */ public static final int FINAL = 0x10; /** * The {@code int} value representing the {@code synchronized} * modifier. - * - * @since Android 1.0 */ public static final int SYNCHRONIZED = 0x20; /** * The {@code int} value representing the {@code volatile} * modifier. - * - * @since Android 1.0 */ public static final int VOLATILE = 0x40; /** * The {@code int} value representing the {@code transient} * modifier. - * - * @since Android 1.0 */ public static final int TRANSIENT = 0x80; /** * The {@code int} value representing the {@code native} modifier. - * - * @since Android 1.0 */ public static final int NATIVE = 0x100; /** * The {@code int} value representing the {@code interface} * modifier. - * - * @since Android 1.0 */ public static final int INTERFACE = 0x200; /** * The {@code int} value representing the {@code abstract} * modifier. - * - * @since Android 1.0 */ public static final int ABSTRACT = 0x400; /** * The {@code int} value representing the {@code strict} modifier. - * - * @since Android 1.0 */ public static final int STRICT = 0x800; @@ -132,8 +106,6 @@ public class Modifier { /** * Constructs a new {@code Modifier} instance. - * - * @since Android 1.0 */ public Modifier() { } @@ -144,11 +116,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * abstract} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isAbstract(int modifiers) { return ((modifiers & ABSTRACT) != 0); @@ -160,11 +129,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * final} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isFinal(int modifiers) { return ((modifiers & FINAL) != 0); @@ -176,11 +142,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * interface} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isInterface(int modifiers) { return ((modifiers & INTERFACE) != 0); @@ -192,11 +155,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * native} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isNative(int modifiers) { return ((modifiers & NATIVE) != 0); @@ -208,11 +168,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * private} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isPrivate(int modifiers) { return ((modifiers & PRIVATE) != 0); @@ -224,11 +181,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * protected} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isProtected(int modifiers) { return ((modifiers & PROTECTED) != 0); @@ -240,11 +194,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * public} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isPublic(int modifiers) { return ((modifiers & PUBLIC) != 0); @@ -256,11 +207,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * static} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isStatic(int modifiers) { return ((modifiers & STATIC) != 0); @@ -272,11 +220,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * strict} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isStrict(int modifiers) { return ((modifiers & STRICT) != 0); @@ -288,11 +233,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * synchronized} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isSynchronized(int modifiers) { return ((modifiers & SYNCHRONIZED) != 0); @@ -304,11 +246,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * transient} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isTransient(int modifiers) { return ((modifiers & TRANSIENT) != 0); @@ -320,11 +259,8 @@ public class Modifier { * * @param modifiers * the modifiers to test - * * @return {@code true} if the specified modifiers contain the {@code * volatile} modifier, {@code false} otherwise - * - * @since Android 1.0 */ public static boolean isVolatile(int modifiers) { return ((modifiers & VOLATILE) != 0); @@ -339,10 +275,7 @@ public class Modifier { * * @param modifiers * the modifiers to print - * * @return a printable representation of the modifiers - * - * @since Android 1.0 */ @SuppressWarnings("nls") public static java.lang.String toString(int modifiers) { diff --git a/luni/src/main/java/java/lang/reflect/ParameterizedType.java b/luni/src/main/java/java/lang/reflect/ParameterizedType.java index 3d03921..91f2520 100644 --- a/luni/src/main/java/java/lang/reflect/ParameterizedType.java +++ b/luni/src/main/java/java/lang/reflect/ParameterizedType.java @@ -18,10 +18,10 @@ package java.lang.reflect; /** - * This interface represents a parameterized type such as {@code + * This interface represents a parameterized type such as {@code * 'Set<String>'}. - * - * @since Android 1.0 + * + * @since 1.5 */ public interface ParameterizedType extends Type { @@ -32,25 +32,23 @@ public interface ParameterizedType extends Type { * parameterized type, this method returns a zero length array. The generic * type of the following {@code field} declaration is an example for a * parameterized type without type arguments. - * + * * <pre> * A<String>.B field; - * + * * class A<T> { * class B { * } * }</pre> - * - * + * + * * @return the actual type arguments - * + * * @throws TypeNotPresentException * if one of the type arguments cannot be found * @throws MalformedParameterizedTypeException * if one of the type arguments cannot be instantiated for some * reason - * - * @since Android 1.0 */ Type[] getActualTypeArguments(); @@ -59,13 +57,11 @@ public interface ParameterizedType extends Type { * {@code null} is returned if this is a top-level type. * * @return the owner type or {@code null} if this is a top-level type - * + * * @throws TypeNotPresentException * if one of the type arguments cannot be found * @throws MalformedParameterizedTypeException * if the owner type cannot be instantiated for some reason - * - * @since Android 1.0 */ Type getOwnerType(); @@ -73,10 +69,8 @@ public interface ParameterizedType extends Type { * Returns the declaring type of this parameterized type. * <p> * The raw type of {@code Set<String> field;} is {@code Set}. - * + * * @return the raw type of this parameterized type - * - * @since Android 1.0 */ Type getRawType(); } diff --git a/luni/src/main/java/java/lang/reflect/Proxy.java b/luni/src/main/java/java/lang/reflect/Proxy.java index 29d15c5..cc0c956 100644 --- a/luni/src/main/java/java/lang/reflect/Proxy.java +++ b/luni/src/main/java/java/lang/reflect/Proxy.java @@ -35,8 +35,7 @@ import org.apache.harmony.luni.util.Msg; * invocations to an {@code InvocationHandler}. * * @see InvocationHandler - * - * @since Android 1.0 + * @since 1.3 */ public class Proxy implements Serializable { @@ -52,8 +51,6 @@ public class Proxy implements Serializable { /** * The invocation handler on which the method calls are dispatched. - * - * @since Android 1.0 */ protected InvocationHandler h; @@ -64,11 +61,9 @@ public class Proxy implements Serializable { /** * Constructs a new {@code Proxy} instance with the specified invocation * handler. - * + * * @param h * the invocation handler for the newly created proxy - * - * @since Android 1.0 */ protected Proxy(InvocationHandler h) { this.h = h; @@ -81,24 +76,20 @@ public class Proxy implements Serializable { * different order result in different generated classes. The interfaces * must be visible from the supplied class loader; no duplicates are * permitted. All non-public interfaces must be defined in the same package. - * + * * @param loader * the class loader that will define the proxy class * @param interfaces * an array of {@code Class} objects, each one identifying an * interface that will be implemented by the returned proxy * class - * * @return a proxy class that implements all of the interfaces referred to * in the contents of {@code interfaces} - * * @throws IllegalArgumentException * if any of the interface restrictions are violated * @throws NullPointerException * if either {@code interfaces} or any of its elements are * {@code null} - * - * @since Android 1.0 */ public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException { @@ -174,19 +165,17 @@ public class Proxy implements Serializable { WeakReference<Class<?>> ref = interfaceCache.get(interfaceKey); if (ref == null) { String nextClassName = "$Proxy" + NextClassNameIndex++; //$NON-NLS-1$ - if (commonPackageName != null) { + if (commonPackageName != null && commonPackageName.length() > 0) { nextClassName = commonPackageName + "." + nextClassName; //$NON-NLS-1$ } // BEGIN android-changed - //byte[] classFileBytes = ProxyClassFile.generateBytes( - // nextClassName, interfaces); - // END android-changed + // byte[] classFileBytes = ProxyClassFile.generateBytes( + // nextClassName, interfaces); + // newClass = defineClassImpl(loader, nextClassName.replace('.', + // '/'), classFileBytes); if (loader == null) { loader = ClassLoader.getSystemClassLoader(); } - // BEGIN android-changed - //newClass = defineClassImpl(loader, nextClassName.replace('.', - // '/'), classFileBytes); newClass = generateProxy(nextClassName.replace('.', '/'), interfaces, loader); // END android-changed @@ -200,6 +189,10 @@ public class Proxy implements Serializable { } } else { newClass = ref.get(); + assert newClass != null : "\ninterfaceKey=\"" + interfaceKey + "\"" + + "\nloaderCache=\"" + loaderCache + "\"" + + "\nintfCache=\"" + interfaceCache + "\"" + + "\nproxyCache=\"" + proxyCache + "\""; } return newClass; } @@ -211,7 +204,7 @@ public class Proxy implements Serializable { * the specified invocation handler. The interfaces must be visible from the * supplied class loader; no duplicates are permitted. All non-public * interfaces must be defined in the same package. - * + * * @param loader * the class loader that will define the proxy class * @param interfaces @@ -221,15 +214,11 @@ public class Proxy implements Serializable { * @param h * the invocation handler that handles the dispatched method * invocations - * * @return a new proxy object that delegates to the handler {@code h} - * * @throws IllegalArgumentException * if any of the interface restrictions are violated * @throws NullPointerException * if the interfaces or any of its elements are null - * - * @since Android 1.0 */ public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) @@ -260,17 +249,13 @@ public class Proxy implements Serializable { /** * Indicates whether or not the specified class is a dynamically generated * proxy class. - * + * * @param cl * the class - * * @return {@code true} if the class is a proxy class, {@code false} * otherwise - * * @throws NullPointerException * if the class is {@code null} - * - * @since Android 1.0 */ public static boolean isProxyClass(Class<?> cl) { if (cl == null) { @@ -283,16 +268,12 @@ public class Proxy implements Serializable { /** * Returns the invocation handler of the specified proxy instance. - * + * * @param proxy * the proxy instance - * * @return the invocation handler of the specified proxy instance - * * @throws IllegalArgumentException * if the supplied {@code proxy} is not a proxy object - * - * @since Android 1.0 */ public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException { diff --git a/luni/src/main/java/java/lang/reflect/ReflectPermission.java b/luni/src/main/java/java/lang/reflect/ReflectPermission.java index b568663..93eef39 100644 --- a/luni/src/main/java/java/lang/reflect/ReflectPermission.java +++ b/luni/src/main/java/java/lang/reflect/ReflectPermission.java @@ -22,8 +22,6 @@ import java.security.BasicPermission; /** * A {@code ReflectPermission} object represents a permission to access * operations in the reflection layer. - * - * @since Android 1.0 */ public final class ReflectPermission extends BasicPermission { @@ -35,13 +33,10 @@ public final class ReflectPermission extends BasicPermission { * * @param permissionName * the name of the new permission - * * @throws IllegalArgumentException * if {@code name} is empty * @throws NullPointerException * if {@code name} is {@code null} - * - * @since Android 1.0 */ public ReflectPermission(String permissionName) { super(permissionName); @@ -55,13 +50,10 @@ public final class ReflectPermission extends BasicPermission { * the name of the new permission * @param actions * this parameter will be ignored - * * @throws IllegalArgumentException * if {@code name} is empty * @throws NullPointerException * if {@code name} is {@code null} - * - * @since Android 1.0 */ public ReflectPermission(String name, String actions) { super(name, actions); diff --git a/luni/src/main/java/java/lang/reflect/Type.java b/luni/src/main/java/java/lang/reflect/Type.java index abd4978..a057088 100644 --- a/luni/src/main/java/java/lang/reflect/Type.java +++ b/luni/src/main/java/java/lang/reflect/Type.java @@ -18,8 +18,8 @@ package java.lang.reflect; /** * Common interface implemented by all Java types. - * - * @since Android 1.0 + * + * @since 1.5 */ public interface Type { // Empty diff --git a/luni/src/main/java/java/lang/reflect/TypeVariable.java b/luni/src/main/java/java/lang/reflect/TypeVariable.java index 99aca77..e3f8c1d 100644 --- a/luni/src/main/java/java/lang/reflect/TypeVariable.java +++ b/luni/src/main/java/java/lang/reflect/TypeVariable.java @@ -17,15 +17,14 @@ package java.lang.reflect; /** - * This interface represents a type variables such as {@code 'T'} in {@code - * 'public interface Comparable<T>'}, the bounded {@code 'T'} in {@code + * This interface represents a type variables such as {@code 'T'} in {@code + * 'public interface Comparable<T>'}, the bounded {@code 'T'} in {@code * 'public interface A<T extends Number>'} or the multiple bounded {@code * 'T'} in {@code 'public interface B<T extends Number & Cloneable>'}. - * + * * @param <D> * the generic declaration that declares this type variable - * - * @since Android 1.0 + * @since 1.5 */ public interface TypeVariable<D extends GenericDeclaration> extends Type { @@ -33,15 +32,13 @@ public interface TypeVariable<D extends GenericDeclaration> extends Type { * Returns the upper bounds of this type variable. {@code Object} is the * implicit upper bound if no other bounds are declared. * - * @return the upper bounds of this type variable - * + * @return the upper bounds of this type variable + * * @throws TypeNotPresentException * if any of the bounds points to a missing type * @throws MalformedParameterizedTypeException * if any of the bounds points to a type that cannot be * instantiated for some reason - * - * @since Android 1.0 */ Type[] getBounds(); @@ -49,8 +46,6 @@ public interface TypeVariable<D extends GenericDeclaration> extends Type { * Returns the language construct that declares this type variable. * * @return the generic declaration - * - * @since Android 1.0 */ D getGenericDeclaration(); @@ -59,8 +54,6 @@ public interface TypeVariable<D extends GenericDeclaration> extends Type { * code. * * @return the name of this type variable - * - * @since Android 1.0 */ String getName(); } diff --git a/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java b/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java index 108f98a..bd5adfa 100644 --- a/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java +++ b/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java @@ -22,8 +22,6 @@ package java.lang.reflect; * an InvocationHandler. * * @see java.lang.reflect.InvocationHandler#invoke - * - * @since Android 1.0 */ public class UndeclaredThrowableException extends RuntimeException { @@ -37,8 +35,6 @@ public class UndeclaredThrowableException extends RuntimeException { * * @param exception * the undeclared, checked exception that occurred - * - * @since Android 1.0 */ public UndeclaredThrowableException(Throwable exception) { super(); @@ -54,8 +50,6 @@ public class UndeclaredThrowableException extends RuntimeException { * the detail message for the exception * @param exception * the undeclared, checked exception that occurred - * - * @since Android 1.0 */ public UndeclaredThrowableException(Throwable exception, String detailMessage) { @@ -69,8 +63,6 @@ public class UndeclaredThrowableException extends RuntimeException { * {@code null}. * * @return the undeclared, checked exception that occurred - * - * @since Android 1.0 */ public Throwable getUndeclaredThrowable() { return undeclaredThrowable; @@ -81,8 +73,6 @@ public class UndeclaredThrowableException extends RuntimeException { * {@code null}. * * @return the undeclared, checked exception that occurred - * - * @since Android 1.0 */ @Override public Throwable getCause() { diff --git a/luni/src/main/java/java/lang/reflect/WildcardType.java b/luni/src/main/java/java/lang/reflect/WildcardType.java index 72a022d..affd526 100644 --- a/luni/src/main/java/java/lang/reflect/WildcardType.java +++ b/luni/src/main/java/java/lang/reflect/WildcardType.java @@ -22,24 +22,21 @@ package java.lang.reflect; * {@code '?'}, the upper bounded wildcard {@code '? extends Closeable'}, the * multiple upper bounded wildcard {@code '? extends Closeable & Flushable'} or * the lower bounded wildcard {@code '? super OutputStream'}. - * - * @since Android 1.0 + * + * @since 1.5 */ public interface WildcardType extends Type { - /** * Returns the array of types that represent the upper bounds of this type. * The default upper bound is {@code Object}. * * @return an array containing the upper bounds types - * + * * @throws TypeNotPresentException * if any of the bounds points to a missing type * @throws MalformedParameterizedTypeException * if any bound points to a type that cannot be instantiated for * some reason - * - * @since Android 1.0 */ Type[] getUpperBounds(); @@ -48,16 +45,14 @@ public interface WildcardType extends Type { * The default lower bound is {@code null}, in which case an empty array is * returned. Since only one lower bound is allowed, the returned array's * length will never exceed one. - * + * * @return an array containing the lower bounds types - * + * * @throws TypeNotPresentException * if any of the bounds points to a missing type * @throws MalformedParameterizedTypeException * if any of the bounds points to a type that cannot be * instantiated for some reason - * - * @since Android 1.0 */ Type[] getLowerBounds(); } diff --git a/luni/src/main/java/java/net/Authenticator.java b/luni/src/main/java/java/net/Authenticator.java index 1eea8d8..75d68fa 100644 --- a/luni/src/main/java/java/net/Authenticator.java +++ b/luni/src/main/java/java/net/Authenticator.java @@ -27,7 +27,6 @@ package java.net; * * @see #setDefault * @see #getPasswordAuthentication - * @since Android 1.0 */ public abstract class Authenticator { @@ -63,10 +62,8 @@ public abstract class Authenticator { * default which is {@code null}. * <p> * Returns {@code null} by default. - * </p> - * + * * @return collected password authentication data. - * @since Android 1.0 */ protected PasswordAuthentication getPasswordAuthentication() { return null; @@ -76,7 +73,6 @@ public abstract class Authenticator { * Returns the port of the connection that requests authorization. * * @return port of the connection. - * @since Android 1.0 */ protected final int getRequestingPort() { return this.port; @@ -87,7 +83,6 @@ public abstract class Authenticator { * {@code null} if unknown. * * @return address of the connection. - * @since Android 1.0 */ protected final InetAddress getRequestingSite() { return this.addr; @@ -98,7 +93,6 @@ public abstract class Authenticator { * authorization. * * @return prompt string of the connection. - * @since Android 1.0 */ protected final String getRequestingPrompt() { return this.prompt; @@ -108,7 +102,6 @@ public abstract class Authenticator { * Returns the protocol of the connection that requests authorization. * * @return protocol of the connection. - * @since Android 1.0 */ protected final String getRequestingProtocol() { return this.protocol; @@ -119,7 +112,6 @@ public abstract class Authenticator { * example HTTP Basic Authentication. * * @return scheme of the connection. - * @since Android 1.0 */ protected final String getRequestingScheme() { return this.scheme; @@ -145,7 +137,6 @@ public abstract class Authenticator { * @throws SecurityException * if a security manager denies the password authentication * permission. - * @since Android 1.0 */ public static synchronized PasswordAuthentication requestPasswordAuthentication( InetAddress rAddr, int rPort, String rProtocol, String rPrompt, @@ -182,7 +173,6 @@ public abstract class Authenticator { * @throws SecurityException * if a security manager denies the password authentication * permission. - * @since Android 1.0 */ public static void setDefault(Authenticator a) { SecurityManager sm = System.getSecurityManager(); @@ -214,7 +204,6 @@ public abstract class Authenticator { * @throws SecurityException * if a security manager denies the password authentication * permission. - * @since Android 1.0 */ public static synchronized PasswordAuthentication requestPasswordAuthentication( String rHost, InetAddress rAddr, int rPort, String rProtocol, @@ -244,9 +233,8 @@ public abstract class Authenticator { /** * Returns the host name of the connection that requests authentication or * {@code null} if unknown. - * + * * @return name of the requesting host or {@code null}. - * @since Android 1.0 */ protected final String getRequestingHost() { return host; @@ -278,7 +266,6 @@ public abstract class Authenticator { * @throws SecurityException * if a security manager denies the password authentication * permission. - * @since Android 1.0 */ public static PasswordAuthentication requestPasswordAuthentication( String rHost, InetAddress rAddr, int rPort, String rProtocol, @@ -312,7 +299,6 @@ public abstract class Authenticator { * Returns the URL of the authentication request. * * @return authentication request url. - * @since Android 1.0 */ protected URL getRequestingURL() { return url; @@ -322,7 +308,6 @@ public abstract class Authenticator { * Returns the type of this request, it can be {@code PROXY} or {@code SERVER}. * * @return RequestorType of the authentication request. - * @since Android 1.0 */ protected Authenticator.RequestorType getRequestorType() { return rt; @@ -330,8 +315,6 @@ public abstract class Authenticator { /** * Enumeration class for the origin of the authentication request. - * - * @since Android 1.0 */ public enum RequestorType { diff --git a/luni/src/main/java/java/net/BindException.java b/luni/src/main/java/java/net/BindException.java index 69be315..48f1cf6 100644 --- a/luni/src/main/java/java/net/BindException.java +++ b/luni/src/main/java/java/net/BindException.java @@ -20,8 +20,6 @@ package java.net; /** * A {@code BindException} is thrown when a process cannot bind a local * address/port, either because it is already bound or reserved by the OS. - * - * @since Android 1.0 */ public class BindException extends SocketException { @@ -29,8 +27,6 @@ public class BindException extends SocketException { /** * Constructs a new instance with its walkback filled in. - * - * @since Android 1.0 */ public BindException() { super(); @@ -41,7 +37,6 @@ public class BindException extends SocketException { * * @param detailMessage * detail message of the exception. - * @since Android 1.0 */ public BindException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/CacheRequest.java b/luni/src/main/java/java/net/CacheRequest.java index 8c67a44..778cb13 100644 --- a/luni/src/main/java/java/net/CacheRequest.java +++ b/luni/src/main/java/java/net/CacheRequest.java @@ -29,14 +29,11 @@ import java.io.OutputStream; * the current cache store operation is abandoned. * * @see ResponseCache - * @since Android 1.0 */ public abstract class CacheRequest { /** * This implementation does nothing. - * - * @since Android 1.0 */ public CacheRequest() { super(); @@ -46,8 +43,6 @@ public abstract class CacheRequest { * Aborts the current cache operation. If an {@code IOException} occurs * while reading the response or writing resource data to the cache, the * current cache store operation is aborted. - * - * @since Android 1.0 */ public abstract void abort(); @@ -58,7 +53,6 @@ public abstract class CacheRequest { * @throws IOException * if an I/O error is encountered during writing response body * operation. - * @since Android 1.0 */ public abstract OutputStream getBody() throws IOException; } diff --git a/luni/src/main/java/java/net/CacheResponse.java b/luni/src/main/java/java/net/CacheResponse.java index ae5be44..b0ad094 100644 --- a/luni/src/main/java/java/net/CacheResponse.java +++ b/luni/src/main/java/java/net/CacheResponse.java @@ -28,13 +28,10 @@ import java.util.Map; * getHeaders()} to fetch the response headers. * * @see ResponseCache - * @since Android 1.0 */ public abstract class CacheResponse { /** * This implementation does nothing. - * - * @since Android 1.0 */ public CacheResponse() { super(); @@ -48,7 +45,6 @@ public abstract class CacheResponse { * @throws IOException * if an I/O error is encountered while retrieving the response * body. - * @since Android 1.0 */ public abstract InputStream getBody() throws IOException; @@ -62,7 +58,6 @@ public abstract class CacheResponse { * @throws IOException * if an I/O error is encountered while retrieving the response * headers. - * @since Android 1.0 */ public abstract Map<String, List<String>> getHeaders() throws IOException; } diff --git a/luni/src/main/java/java/net/ConnectException.java b/luni/src/main/java/java/net/ConnectException.java index 42389c7..84cd2bb 100644 --- a/luni/src/main/java/java/net/ConnectException.java +++ b/luni/src/main/java/java/net/ConnectException.java @@ -20,8 +20,6 @@ package java.net; /** * A {@code ConnectException} is thrown if a connection cannot be established to * a remote host on a specific port. - * - * @since Android 1.0 */ public class ConnectException extends SocketException { @@ -29,8 +27,6 @@ public class ConnectException extends SocketException { /** * This implementation does nothing. - * - * @since Android 1.0 */ public ConnectException() { super(); @@ -38,10 +34,9 @@ public class ConnectException extends SocketException { /** * This implementation does nothing. - * + * * @param detailMessage * detail message of the exception. - * @since Android 1.0 */ public ConnectException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/ContentHandler.java b/luni/src/main/java/java/net/ContentHandler.java index 05c6acf..8e0bbb7 100644 --- a/luni/src/main/java/java/net/ContentHandler.java +++ b/luni/src/main/java/java/net/ContentHandler.java @@ -23,28 +23,26 @@ import java.io.IOException; * This class converts the content of a certain format (i.e. a MIME type) into a * Java type object. It is created by {@code ContentHandlerFactory}. The data * values should be accessed via {@code URL} or {@code URLConnection}. - * + * * @see ContentHandlerFactory * @see URL#getContent() * @see URLConnection#getContent() - * @since Android 1.0 */ public abstract class ContentHandler { /** * Returns the object pointed by the specified URL connection {@code uConn}. - * + * * @param uConn * URL connection that points to the desired object. * @return object referred by {@code uConn}. * @throws IOException * if an IO error occurs during the retrieval of the object - * @since Android 1.0 */ public abstract Object getContent(URLConnection uConn) throws IOException; /** * Returns the object pointed by the specified URL connection {@code uConn}. - * + * * @param uConn * URL connection that points to the desired object. * @param types @@ -53,7 +51,6 @@ public abstract class ContentHandler { * content doesn't match one of the specified content types. * @throws IOException * if an error occurred while obtaining the content. - * @since Android 1.0 */ // Class arg not generified in the spec. @SuppressWarnings("unchecked") diff --git a/luni/src/main/java/java/net/ContentHandlerFactory.java b/luni/src/main/java/java/net/ContentHandlerFactory.java index 1a564ee..3089c04 100644 --- a/luni/src/main/java/java/net/ContentHandlerFactory.java +++ b/luni/src/main/java/java/net/ContentHandlerFactory.java @@ -21,7 +21,6 @@ package java.net; * Defines a factory which is responsible for creating a {@code ContentHandler}. * * @see ContentHandler - * @since Android 1.0 */ public interface ContentHandlerFactory { /** @@ -31,7 +30,6 @@ public interface ContentHandlerFactory { * specifies the content type which is handled by the returned * {@code ContentHandler}. * @return content handler object for a specific content type. - * @since Android 1.0 */ ContentHandler createContentHandler(String contentType); } diff --git a/luni/src/main/java/java/net/CookieHandler.java b/luni/src/main/java/java/net/CookieHandler.java index 29428ec..05eddde 100644 --- a/luni/src/main/java/java/net/CookieHandler.java +++ b/luni/src/main/java/java/net/CookieHandler.java @@ -22,8 +22,6 @@ import java.util.Map; /** * This class provides a way to manage cookies with a HTTP protocol handler. - * - * @since Android 1.0 */ public abstract class CookieHandler { @@ -37,9 +35,8 @@ public abstract class CookieHandler { /** * Returns the system-wide cookie handler or {@code null} if not set. - * + * * @return the system-wide cookie handler. - * @since Android 1.0 */ public static CookieHandler getDefault() { SecurityManager sm = System.getSecurityManager(); @@ -51,10 +48,9 @@ public abstract class CookieHandler { /** * Sets the system-wide cookie handler. - * + * * @param cHandler * a cookie handler to set as the system-wide default handler. - * @since Android 1.0 */ public static void setDefault(CookieHandler cHandler) { SecurityManager sm = System.getSecurityManager(); @@ -66,7 +62,7 @@ public abstract class CookieHandler { /** * Gets all cookies for a specific URI from the cookie cache. - * + * * @param uri * a URI to search for applicable cookies. * @param requestHeaders @@ -74,7 +70,6 @@ public abstract class CookieHandler { * @return an unchangeable map of all appropriate cookies. * @throws IOException * if an error occurs during the I/O operation. - * @since Android 1.0 */ public abstract Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException; @@ -82,14 +77,13 @@ public abstract class CookieHandler { /** * Sets all cookies of a specific URI in the {@code responseHeaders} into * the cookie cache. - * + * * @param uri * the origin URI of the cookies. * @param responseHeaders * a list of request headers. * @throws IOException * if an error occurs during the I/O operation. - * @since Android 1.0 */ public abstract void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException; diff --git a/luni/src/main/java/java/net/DatagramPacket.java b/luni/src/main/java/java/net/DatagramPacket.java index bcc531e..7bbf553 100644 --- a/luni/src/main/java/java/net/DatagramPacket.java +++ b/luni/src/main/java/java/net/DatagramPacket.java @@ -25,20 +25,30 @@ import org.apache.harmony.luni.util.Msg; * such as its source or destination host. * * @see DatagramSocket - * @since Android 1.0 */ public final class DatagramPacket { byte[] data; + /** + * Length of the data to be sent or size of data that was received via + * DatagramSocket#receive() method call. + */ int length; + /** + * Size of internal buffer that is used to store received data. Should be + * greater or equal to "length" field. + */ + int capacity; + InetAddress address; int port = -1; // The default port number is -1 int offset = 0; + /** * Constructs a new {@code DatagramPacket} object to receive data up to * {@code length} bytes. @@ -47,7 +57,6 @@ public final class DatagramPacket { * a byte array to store the read characters. * @param length * the length of the data buffer. - * @since Android 1.0 */ public DatagramPacket(byte[] data, int length) { this(data, 0, length); @@ -63,7 +72,6 @@ public final class DatagramPacket { * the offset of the byte array where the bytes is written. * @param length * the length of the data. - * @since Android 1.0 */ public DatagramPacket(byte[] data, int offset, int length) { super(); @@ -75,7 +83,7 @@ public final class DatagramPacket { * {@code aPort} of the address {@code host}. The {@code length} must be * lesser than or equal to the size of {@code data}. The first {@code * length} bytes from the byte array position {@code offset} are sent. - * + * * @param data * a byte array which stores the characters to be sent. * @param offset @@ -86,7 +94,6 @@ public final class DatagramPacket { * the address of the target host. * @param aPort * the port of the target host. - * @since Android 1.0 */ public DatagramPacket(byte[] data, int offset, int length, InetAddress host, int aPort) { @@ -100,7 +107,7 @@ public final class DatagramPacket { * {@code aPort} of the address {@code host}. The {@code length} must be * lesser than or equal to the size of {@code data}. The first {@code * length} bytes are sent. - * + * * @param data * a byte array which stores the characters to be sent. * @param length @@ -109,7 +116,6 @@ public final class DatagramPacket { * the address of the target host. * @param port * the port of the target host. - * @since Android 1.0 */ public DatagramPacket(byte[] data, int length, InetAddress host, int port) { this(data, 0, length, host, port); @@ -120,7 +126,6 @@ public final class DatagramPacket { * * @return the address from where the datagram was received or to which it * is sent. - * @since Android 1.0 */ public synchronized InetAddress getAddress() { return address; @@ -130,7 +135,6 @@ public final class DatagramPacket { * Gets the data of this datagram packet. * * @return the received data or the data to be sent. - * @since Android 1.0 */ public synchronized byte[] getData() { return data; @@ -140,7 +144,6 @@ public final class DatagramPacket { * Gets the length of the data stored in this datagram packet. * * @return the length of the received data or the data to be sent. - * @since Android 1.0 */ public synchronized int getLength() { return length; @@ -150,7 +153,6 @@ public final class DatagramPacket { * Gets the offset of the data stored in this datagram packet. * * @return the position of the received data or the data to be sent. - * @since Android 1.0 */ public synchronized int getOffset() { return offset; @@ -159,9 +161,8 @@ public final class DatagramPacket { /** * Gets the port number of the target or sender host of this datagram * packet. - * + * * @return the port number of the origin or target host. - * @since Android 1.0 */ public synchronized int getPort() { return port; @@ -172,7 +173,6 @@ public final class DatagramPacket { * * @param addr * the target host address. - * @since Android 1.0 */ public synchronized void setAddress(InetAddress addr) { address = addr; @@ -188,7 +188,6 @@ public final class DatagramPacket { * @param aLength * the length of the data to be sent or the length of buffer to * store the received data. - * @since Android 1.0 */ public synchronized void setData(byte[] buf, int anOffset, int aLength) { if (0 > anOffset || anOffset > buf.length || 0 > aLength @@ -198,6 +197,7 @@ public final class DatagramPacket { data = buf; offset = anOffset; length = aLength; + capacity = aLength; } /** @@ -206,10 +206,10 @@ public final class DatagramPacket { * * @param buf * the buffer to store the data. - * @since Android 1.0 */ public synchronized void setData(byte[] buf) { length = buf.length; // This will check for null + capacity = buf.length; data = buf; offset = 0; } @@ -220,13 +220,13 @@ public final class DatagramPacket { * * @param len * the length of this datagram packet. - * @since Android 1.0 */ public synchronized void setLength(int len) { if (0 > len || offset + len > data.length) { throw new IllegalArgumentException(Msg.getString("K002f")); //$NON-NLS-1$ } length = len; + capacity = len; } /** @@ -234,7 +234,6 @@ public final class DatagramPacket { * * @param aPort * the target host port number. - * @since Android 1.0 */ public synchronized void setPort(int aPort) { if (aPort < 0 || aPort > 65535) { @@ -257,9 +256,9 @@ public final class DatagramPacket { * the target host address and port. * @throws SocketException * if an error in the underlying protocol occurs. - * @since Android 1.0 */ - public DatagramPacket(byte[] data, int length, SocketAddress sockAddr) throws SocketException { + public DatagramPacket(byte[] data, int length, SocketAddress sockAddr) + throws SocketException { this(data, 0, length); setSocketAddress(sockAddr); } @@ -280,7 +279,6 @@ public final class DatagramPacket { * the target host address and port. * @throws SocketException * if an error in the underlying protocol occurs. - * @since Android 1.0 */ public DatagramPacket(byte[] data, int offset, int length, SocketAddress sockAddr) throws SocketException { @@ -291,9 +289,8 @@ public final class DatagramPacket { /** * Gets the host address and the port to which this datagram packet is sent * as a {@code SocketAddress} object. - * + * * @return the SocketAddress of the target host. - * @since Android 1.0 */ public synchronized SocketAddress getSocketAddress() { return new InetSocketAddress(getAddress(), getPort()); @@ -304,7 +301,6 @@ public final class DatagramPacket { * * @param sockAddr * the SocketAddress of the target host. - * @since Android 1.0 */ public synchronized void setSocketAddress(SocketAddress sockAddr) { if (!(sockAddr instanceof InetSocketAddress)) { diff --git a/luni/src/main/java/java/net/DatagramSocket.java b/luni/src/main/java/java/net/DatagramSocket.java index 0c7745f..6b3b6cc 100644 --- a/luni/src/main/java/java/net/DatagramSocket.java +++ b/luni/src/main/java/java/net/DatagramSocket.java @@ -20,19 +20,17 @@ package java.net; import java.io.IOException; import java.nio.channels.DatagramChannel; -import org.apache.harmony.luni.net.SocketImplProvider; +import org.apache.harmony.luni.net.PlainDatagramSocketImpl; import org.apache.harmony.luni.platform.Platform; - import org.apache.harmony.luni.util.Msg; /** * This class implements a UDP socket for sending and receiving {@code * DatagramPacket}. A {@code DatagramSocket} object can be used for both * endpoints of a connection for a packet delivery service. - * + * * @see DatagramPacket * @see DatagramSocketImplFactory - * @since Android 1.0 */ public class DatagramSocket { @@ -56,16 +54,15 @@ public class DatagramSocket { static { Platform.getNetworkSystem().oneTimeInitialization(true); } - + private Object lock = new Lock(); /** * Constructs a UDP datagram socket which is bound to any available port on * the localhost. - * + * * @throws SocketException * if an error occurs while creating or binding the socket. - * @since Android 1.0 */ public DatagramSocket() throws SocketException { this(0); @@ -75,12 +72,11 @@ public class DatagramSocket { * Constructs a UDP datagram socket which is bound to the specific port * {@code aPort} on the localhost. Valid values for {@code aPort} are * between 0 and 65535 inclusive. - * + * * @param aPort * the port to bind on the localhost. * @throws SocketException * if an error occurs while creating or binding the socket. - * @since Android 1.0 */ public DatagramSocket(int aPort) throws SocketException { super(); @@ -92,14 +88,13 @@ public class DatagramSocket { * Constructs a UDP datagram socket which is bound to the specific local * address {@code addr} on port {@code aPort}. Valid values for {@code * aPort} are between 0 and 65535 inclusive. - * + * * @param aPort * the port to bind on the localhost. * @param addr * the address to bind on the localhost. * @throws SocketException * if an error occurs while creating or binding the socket. - * @since Android 1.0 */ public DatagramSocket(int aPort, InetAddress addr) throws SocketException { super(); @@ -111,10 +106,9 @@ public class DatagramSocket { * Sends prior to attempting to bind the socket, checks whether the port is * within the valid port range and verifies with the security manager that * the port may be bound by the current context. - * + * * @param aPort * the port on the localhost that is to be bound. - * @since Android 1.0 */ void checkListen(int aPort) { if (aPort < 0 || aPort > 65535) { @@ -128,8 +122,6 @@ public class DatagramSocket { /** * Closes this UDP datagram socket and all possibly associated channels. - * - * @since Android 1.0 */ // In the documentation jdk1.1.7a/guide/net/miscNet.html, this method is // noted as not being synchronized. @@ -144,12 +136,11 @@ public class DatagramSocket { * validated, thereafter the only validation on {@code send()} and {@code * receive()} is to check whether the packet address/port matches the * connected target. - * + * * @param anAddress * the target address of this socket. * @param aPort * the target port of this socket. - * @since Android 1.0 */ public void connect(InetAddress anAddress, int aPort) { if (anAddress == null || aPort < 0 || aPort > 65535) { @@ -189,8 +180,6 @@ public class DatagramSocket { /** * Disconnects this UDP datagram socket from the remote host. This method * called on an unconnected socket does nothing. - * - * @since Android 1.0 */ public void disconnect() { if (isClosed() || !isConnected()) { @@ -205,7 +194,7 @@ public class DatagramSocket { synchronized void createSocket(int aPort, InetAddress addr) throws SocketException { impl = factory != null ? factory.createDatagramSocketImpl() - : SocketImplProvider.getDatagramSocketImpl(); + : new PlainDatagramSocketImpl(); impl.create(); try { impl.bind(aPort, addr); @@ -219,10 +208,9 @@ public class DatagramSocket { /** * Gets the {@code InetAddress} instance representing the remote address to * which this UDP datagram socket is connected. - * + * * @return the remote address this socket is connected to or {@code null} if * this socket is not connected. - * @since Android 1.0 */ public InetAddress getInetAddress() { return address; @@ -231,10 +219,9 @@ public class DatagramSocket { /** * Gets the {@code InetAddress} instance representing the bound local * address of this UDP datagram socket. - * + * * @return the local address to which this socket is bound to or {@code * null} if this socket is closed. - * @since Android 1.0 */ public InetAddress getLocalAddress() { if (isClosed()) { @@ -257,10 +244,9 @@ public class DatagramSocket { /** * Gets the local port which this socket is bound to. - * + * * @return the local port of this socket or {@code -1} if this socket is * closed and {@code 0} if it is unbound. - * @since Android 1.0 */ public int getLocalPort() { if (isClosed()) { @@ -274,10 +260,9 @@ public class DatagramSocket { /** * Gets the remote port which this socket is connected to. - * + * * @return the remote port of this socket. The return value {@code -1} * indicates that this socket is not connected. - * @since Android 1.0 */ public int getPort() { return port; @@ -285,9 +270,8 @@ public class DatagramSocket { /** * Indicates whether this socket is multicast or not. - * + * * @return the return value is always {@code false}. - * @since Android 1.0 */ boolean isMulticastSocket() { return false; @@ -295,11 +279,10 @@ public class DatagramSocket { /** * Gets the socket receive buffer size. ( {@code SocketOptions.SO_RCVBUF} ) - * + * * @return the input buffer size. - * @exception SocketException + * @throws SocketException * if an error occurs while getting the option value. - * @since Android 1.0 */ public synchronized int getReceiveBufferSize() throws SocketException { checkClosedAndBind(false); @@ -308,11 +291,10 @@ public class DatagramSocket { /** * Gets the socket send buffer size. ( {@code SocketOptions.SO_SNDBUF} ) - * + * * @return the output buffer size. - * @exception SocketException + * @throws SocketException * if an error occurs while getting the option value. - * @since Android 1.0 */ public synchronized int getSendBufferSize() throws SocketException { checkClosedAndBind(false); @@ -323,11 +305,10 @@ public class DatagramSocket { * Gets the socket receive timeout in milliseconds. The return value {@code * 0} implies the timeout is disabled/infinitive. ( {@code * SocketOptions.SO_TIMEOUT} ) - * + * * @return the socket receive timeout. - * @exception SocketException + * @throws SocketException * if an error occurs while getting the option value. - * @since Android 1.0 */ public synchronized int getSoTimeout() throws SocketException { checkClosedAndBind(false); @@ -342,42 +323,49 @@ public class DatagramSocket { * has expired. If a security manager exists, its {@code checkAccept} method * determines whether or not a packet is discarded. Any packets from * unacceptable origins are silently discarded. - * + * * @param pack * the {@code DatagramPacket} to store the received data. - * @exception IOException + * @throws IOException * if an error occurs while receiving the packet. - * @since Android 1.0 */ public synchronized void receive(DatagramPacket pack) throws IOException { checkClosedAndBind(true); - boolean secure = true; - - InetAddress senderAddr = null; - - int senderPort = 0; + InetAddress senderAddr; + int senderPort; DatagramPacket tempPack = new DatagramPacket(new byte[1], 1); + + // means that we have received the packet into the temporary buffer boolean copy = false; SecurityManager security = System.getSecurityManager(); - if (address != null || security != null) { // The socket is connected + + if (address != null || security != null) { + // The socket is connected or we need to check security permissions + // Check pack before peeking if (pack == null) { throw new NullPointerException(); } - secure = false; - while (!secure) { + + // iterate over incoming packets + while (true) { copy = false; + + // let's get sender's address and port try { senderPort = impl.peekData(tempPack); senderAddr = tempPack.getAddress(); } catch (SocketException e) { if (e.getMessage().equals( "The socket does not support the operation")) { //$NON-NLS-1$ - tempPack = new DatagramPacket(new byte[pack.length], - pack.getLength()); + // receive packet to temporary buffer + tempPack = new DatagramPacket(new byte[pack.capacity], + pack.capacity); impl.receive(tempPack); + // tempPack's length field is now updated, capacity is unchanged + // let's extract address & port senderAddr = tempPack.getAddress(); senderPort = tempPack.getPort(); copy = true; @@ -385,46 +373,45 @@ public class DatagramSocket { throw e; } } + if (address == null) { + // if we are not connected let's check if we are allowed to + // receive packets from sender's address and port try { security.checkAccept(senderAddr.getHostName(), senderPort); - if (!copy) { - secure = true; - } + // address & port are valid break; } catch (SecurityException e) { if (!copy) { - if (tempPack == null) { - tempPack = new DatagramPacket( - new byte[pack.length], pack.length); - } + // drop this packet and continue impl.receive(tempPack); } } } else if (port == senderPort && address.equals(senderAddr)) { - if (!copy) { - secure = true; - } + // we are connected and the packet came + // from the address & port we are connected to break; } else if (!copy) { - if (tempPack == null) { - tempPack = new DatagramPacket(new byte[pack.length], - pack.length); - } + // drop packet and continue impl.receive(tempPack); } } } + if (copy) { System.arraycopy(tempPack.getData(), 0, pack.getData(), pack .getOffset(), tempPack.getLength()); - pack.setLength(tempPack.getLength()); + // we shouldn't update the pack's capacity field in order to be + // compatible with RI + pack.length = tempPack.length; pack.setAddress(tempPack.getAddress()); pack.setPort(tempPack.getPort()); - } - if (secure) { + } else { + pack.setLength(pack.capacity); impl.receive(pack); + // pack's length field is now updated by native code call; + // pack's capacity field is unchanged } } @@ -433,12 +420,11 @@ public class DatagramSocket { * policy before it may be sent. If a security manager is installed, this * method checks whether it is allowed to send this packet to the specified * address. - * + * * @param pack * the {@code DatagramPacket} which has to be sent. - * @exception IOException + * @throws IOException * if an error occurs while sending the packet. - * @since Android 1.0 */ public void send(DatagramPacket pack) throws IOException { checkClosedAndBind(true); @@ -480,12 +466,11 @@ public class DatagramSocket { * maximum packet size is that can be sent over this socket. It depends on * the network implementation what will happen if the packet is bigger than * the buffer size. ( {@code SocketOptions.SO_SNDBUF} ) - * + * * @param size * the buffer size in bytes. The size must be at least one byte. - * @exception SocketException + * @throws SocketException * if an error occurs while setting the option. - * @since Android 1.0 */ public synchronized void setSendBufferSize(int size) throws SocketException { if (size < 1) { @@ -500,12 +485,11 @@ public class DatagramSocket { * the maximum packet size is that can be received over this socket. It * depends on the network implementation what will happen if the packet is * bigger than the buffer size. ( {@code SocketOptions.SO_RCVBUF} ) - * + * * @param size * the buffer size in bytes. The size must be at least one byte. - * @exception SocketException + * @throws SocketException * if an error occurs while setting the option. - * @since Android 1.0 */ public synchronized void setReceiveBufferSize(int size) throws SocketException { @@ -523,12 +507,11 @@ public class DatagramSocket { * {@code 0} (default) is used to set an infinite timeout. To have effect * this option must be set before the blocking method was called. ( {@code * SocketOptions.SO_TIMEOUT} ) - * + * * @param timeout * the timeout period in milliseconds or {@code 0} for infinite. - * @exception SocketException + * @throws SocketException * if an error occurs while setting the option. - * @since Android 1.0 */ public synchronized void setSoTimeout(int timeout) throws SocketException { if (timeout < 0) { @@ -545,13 +528,12 @@ public class DatagramSocket { * method {@code checkSetFactory()} is called to check if the operation is * allowed. A {@code SecurityException} is thrown if the operation is not * allowed. - * + * * @param fac * the socket factory to use. - * @exception IOException + * @throws IOException * if the factory has already been set. * @see DatagramSocketImplFactory - * @since Android 1.0 */ public static synchronized void setDatagramSocketImplFactory( DatagramSocketImplFactory fac) throws IOException { @@ -569,10 +551,9 @@ public class DatagramSocket { * Constructs a new {@code DatagramSocket} using the specific datagram * socket implementation {@code socketImpl}. The created {@code * DatagramSocket} will not be bound. - * + * * @param socketImpl * the DatagramSocketImpl to use. - * @since Android 1.0 */ protected DatagramSocket(DatagramSocketImpl socketImpl) { if (socketImpl == null) { @@ -585,12 +566,13 @@ public class DatagramSocket { * Constructs a new {@code DatagramSocket} bound to the host/port specified * by the {@code SocketAddress} {@code localAddr} or an unbound {@code * DatagramSocket} if the {@code SocketAddress} is {@code null}. - * + * * @param localAddr * the local machine address and port to bind to. + * @throws IllegalArgumentException + * if the SocketAddress is not supported * @throws SocketException * if a problem occurs creating or binding the socket. - * @since Android 1.0 */ public DatagramSocket(SocketAddress localAddr) throws SocketException { if (localAddr != null) { @@ -601,7 +583,7 @@ public class DatagramSocket { checkListen(((InetSocketAddress) localAddr).getPort()); } impl = factory != null ? factory.createDatagramSocketImpl() - : SocketImplProvider.getDatagramSocketImpl(); + : new PlainDatagramSocketImpl(); impl.create(); if (localAddr != null) { try { @@ -630,13 +612,14 @@ public class DatagramSocket { * Binds this socket to the local address and port specified by {@code * localAddr}. If this value is {@code null} any free port on a valid local * address is used. - * + * * @param localAddr * the local machine address and port to bind on. + * @throws IllegalArgumentException + * if the SocketAddress is not supported * @throws SocketException * if the socket is already bound or a problem occurs during * binding. - * @since Android 1.0 */ public void bind(SocketAddress localAddr) throws SocketException { checkClosedAndBind(false); @@ -665,12 +648,11 @@ public class DatagramSocket { * {@code remoteAddr}. The host and port are validated, thereafter the only * validation on {@code send()} and {@code receive()} is that the packet * address/port matches the connected target. - * + * * @param remoteAddr * the address and port of the target host. - * @exception SocketException + * @throws SocketException * if an error occurs during connecting. - * @since Android 1.0 */ public void connect(SocketAddress remoteAddr) throws SocketException { if (remoteAddr == null) { @@ -720,9 +702,8 @@ public class DatagramSocket { /** * Determines whether the socket is bound to an address or not. - * + * * @return {@code true} if the socket is bound, {@code false} otherwise. - * @since Android 1.0 */ public boolean isBound() { return isBound; @@ -730,9 +711,8 @@ public class DatagramSocket { /** * Determines whether the socket is connected to a target host. - * + * * @return {@code true} if the socket is connected, {@code false} otherwise. - * @since Android 1.0 */ public boolean isConnected() { return isConnected; @@ -741,9 +721,8 @@ public class DatagramSocket { /** * Gets the address and port of the connected remote host. If this socket is * not connected yet, {@code null} is returned. - * + * * @return the remote socket address. - * @since Android 1.0 */ public SocketAddress getRemoteSocketAddress() { if (!isConnected()) { @@ -755,9 +734,8 @@ public class DatagramSocket { /** * Gets the bound local address and port of this socket. If the socket is * unbound, {@code null} is returned. - * + * * @return the local socket address. - * @since Android 1.0 */ public SocketAddress getLocalSocketAddress() { if (!isBound()) { @@ -773,13 +751,11 @@ public class DatagramSocket { * <p> * There is an undefined behavior if this option is set after the socket is * already bound. - * </p> - * + * * @param reuse * the socket option value to enable or disable this option. * @throws SocketException * if the socket is closed or the option could not be set. - * @since Android 1.0 */ public void setReuseAddress(boolean reuse) throws SocketException { checkClosedAndBind(false); @@ -789,11 +765,10 @@ public class DatagramSocket { /** * Gets the state of the socket option {@code SocketOptions.SO_REUSEADDR}. - * + * * @return {@code true} if the option is enabled, {@code false} otherwise. * @throws SocketException * if the socket is closed or the option is invalid. - * @since Android 1.0 */ public boolean getReuseAddress() throws SocketException { checkClosedAndBind(false); @@ -804,12 +779,11 @@ public class DatagramSocket { /** * Sets the socket option {@code SocketOptions.SO_BROADCAST}. This option * must be enabled to send broadcast messages. - * + * * @param broadcast * the socket option value to enable or disable this option. * @throws SocketException * if the socket is closed or the option could not be set. - * @since Android 1.0 */ public void setBroadcast(boolean broadcast) throws SocketException { checkClosedAndBind(false); @@ -819,11 +793,10 @@ public class DatagramSocket { /** * Gets the state of the socket option {@code SocketOptions.SO_BROADCAST}. - * + * * @return {@code true} if the option is enabled, {@code false} otherwise. * @throws SocketException * if the socket is closed or the option is invalid. - * @since Android 1.0 */ public boolean getBroadcast() throws SocketException { checkClosedAndBind(false); @@ -839,13 +812,11 @@ public class DatagramSocket { * <p> * Values between {@code 0} and {@code 255} inclusive are valid for this * option. - * </p> - * + * * @param value * the socket option value to be set as type-of-service. * @throws SocketException * if the socket is closed or the option could not be set. - * @since Android 1.0 */ public void setTrafficClass(int value) throws SocketException { checkClosedAndBind(false); @@ -858,11 +829,10 @@ public class DatagramSocket { /** * Gets the value of the type-of-service socket option {@code * SocketOptions.IP_TOS}. - * + * * @return the type-of-service socket option value. * @throws SocketException * if the socket is closed or the option is invalid. - * @since Android 1.0 */ public int getTrafficClass() throws SocketException { checkClosedAndBind(false); @@ -871,9 +841,8 @@ public class DatagramSocket { /** * Gets the state of this socket. - * + * * @return {@code true} if the socket is closed, {@code false} otherwise. - * @since Android 1.0 */ public boolean isClosed() { return isClosed; @@ -882,10 +851,9 @@ public class DatagramSocket { /** * Gets the related DatagramChannel of this socket. This implementation * returns always {@code null}. - * + * * @return the related DatagramChannel or {@code null} if this socket was * not created by a {@code DatagramChannel} object. - * @since Android 1.0 */ public DatagramChannel getChannel() { return null; diff --git a/luni/src/main/java/java/net/DatagramSocketImpl.java b/luni/src/main/java/java/net/DatagramSocketImpl.java index 7915156..db3b9ec 100644 --- a/luni/src/main/java/java/net/DatagramSocketImpl.java +++ b/luni/src/main/java/java/net/DatagramSocketImpl.java @@ -25,29 +25,21 @@ import org.apache.harmony.luni.platform.Platform; /** * The abstract superclass for datagram and multicast socket implementations. - * - * @since Android 1.0 */ public abstract class DatagramSocketImpl implements SocketOptions { /** * File descriptor that is used to address this socket. - * - * @since Android 1.0 */ protected FileDescriptor fd; /** * The number of the local port to which this socket is bound. - * - * @since Android 1.0 */ protected int localPort; /** * Constructs an unbound datagram socket implementation. - * - * @since Android 1.0 */ public DatagramSocketImpl() { localPort = -1; @@ -61,28 +53,24 @@ public abstract class DatagramSocketImpl implements SocketOptions { * the port on the localhost to bind. * @param addr * the address on the multihomed localhost to bind. - * @exception SocketException + * @throws SocketException * if an error occurs while binding, for example, if the port * has been already bound. - * @since Android 1.0 */ protected abstract void bind(int port, InetAddress addr) throws SocketException; /** * Closes this socket. - * - * @since Android 1.0 */ protected abstract void close(); /** * This method allocates the socket descriptor in the underlying operating * system. - * + * * @throws SocketException * if an error occurs while creating the socket. - * @since Android 1.0 */ protected abstract void create() throws SocketException; @@ -91,7 +79,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * if the socket is closed or not bound. * * @return the current file descriptor of this socket. - * @since Android 1.0 */ protected FileDescriptor getFileDescriptor() { return fd; @@ -101,7 +88,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * Gets the local address to which the socket is bound. * * @return the local address to which the socket is bound. - * @since Android 1.0 */ InetAddress getLocalAddress() { return Platform.getNetworkSystem().getSocketLocalAddress(fd, @@ -112,7 +98,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * Gets the local port of this socket. * * @return the local port to which this socket is bound. - * @since Android 1.0 */ protected int getLocalPort() { return localPort; @@ -124,9 +109,8 @@ public abstract class DatagramSocketImpl implements SocketOptions { * @param optID * the ID of the socket option to be retrieved. * @return the requested option value. - * @exception SocketException + * @throws SocketException * if an error occurs while accessing the option. - * @since Android 1.0 */ public abstract Object getOption(int optID) throws SocketException; @@ -139,7 +123,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * value. * @deprecated Replaced by {@link #getTimeToLive} * @see #getTimeToLive() - * @since Android 1.0 */ @Deprecated protected abstract byte getTTL() throws IOException; @@ -148,12 +131,11 @@ public abstract class DatagramSocketImpl implements SocketOptions { * Gets the time-to-live (TTL) for multicast packets sent on this socket. * The TTL option defines how many routers a packet may be pass before it is * discarded. - * + * * @return the time-to-live option as an integer value. * @throws IOException * if an error occurs while getting the time-to-live option * value. - * @since Android 1.0 */ protected abstract int getTimeToLive() throws IOException; @@ -167,7 +149,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * @throws IOException * if an error occurs while joining the specified multicast * group. - * @since Android 1.0 */ protected abstract void join(InetAddress addr) throws IOException; @@ -184,7 +165,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * @throws IOException * if an error occurs while joining the specified multicast * group. - * @since Android 1.0 */ protected abstract void joinGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException; @@ -197,7 +177,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * @throws IOException * if an error occurs while leaving the group or no multicast * address was assigned. - * @since Android 1.0 */ protected abstract void leave(InetAddress addr) throws IOException; @@ -211,7 +190,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * removed. * @throws IOException * if an error occurs while leaving the group. - * @since Android 1.0 */ protected abstract void leaveGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException; @@ -224,9 +202,8 @@ public abstract class DatagramSocketImpl implements SocketOptions { * @param sender * the origin address of a packet. * @return the address of {@code sender} as an integer value. - * @exception IOException + * @throws IOException * if an error or a timeout occurs while reading the address. - * @since Android 1.0 */ protected abstract int peek(InetAddress sender) throws IOException; @@ -238,9 +215,8 @@ public abstract class DatagramSocketImpl implements SocketOptions { * * @param pack * the datagram packet container to fill in the received data. - * @exception IOException + * @throws IOException * if an error or timeout occurs while receiving data. - * @since Android 1.0 */ protected abstract void receive(DatagramPacket pack) throws IOException; @@ -250,9 +226,8 @@ public abstract class DatagramSocketImpl implements SocketOptions { * * @param pack * the datagram packet to be sent. - * @exception IOException + * @throws IOException * if an error occurs while sending the packet. - * @since Android 1.0 */ protected abstract void send(DatagramPacket pack) throws IOException; @@ -263,9 +238,8 @@ public abstract class DatagramSocketImpl implements SocketOptions { * the ID of the socket option to be set. * @param val * the value of the option. - * @exception SocketException + * @throws SocketException * if an error occurs while setting the option. - * @since Android 1.0 */ public abstract void setOption(int optID, Object val) throws SocketException; @@ -279,7 +253,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * <= 255. * @throws IOException * if an error occurs while setting the option. - * @since Android 1.0 */ protected abstract void setTimeToLive(int ttl) throws IOException; @@ -294,7 +267,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { * if an error occurs while setting the option. * @deprecated Replaced by {@link #setTimeToLive} * @see #setTimeToLive(int) - * @since Android 1.0 */ @Deprecated protected abstract void setTTL(byte ttl) throws IOException; @@ -306,10 +278,9 @@ public abstract class DatagramSocketImpl implements SocketOptions { * the address of the target host which has to be connected. * @param port * the port on the target host which has to be connected. - * @exception SocketException + * @throws SocketException * if the datagram socket cannot be connected to the * specified remote address and port. - * @since Android 1.0 */ protected void connect(InetAddress inetAddr, int port) throws SocketException { @@ -318,8 +289,6 @@ public abstract class DatagramSocketImpl implements SocketOptions { /** * Disconnects this socket from the remote host. - * - * @since Android 1.0 */ protected void disconnect() { // do nothing @@ -335,9 +304,8 @@ public abstract class DatagramSocketImpl implements SocketOptions { * @param pack * the datagram packet used to store the data. * @return the port the packet was received from. - * @exception IOException + * @throws IOException * if an error occurs while peeking at the data. - * @since Android 1.0 */ protected abstract int peekData(DatagramPacket pack) throws IOException; } diff --git a/luni/src/main/java/java/net/DatagramSocketImplFactory.java b/luni/src/main/java/java/net/DatagramSocketImplFactory.java index b97146e..ce91738 100644 --- a/luni/src/main/java/java/net/DatagramSocketImplFactory.java +++ b/luni/src/main/java/java/net/DatagramSocketImplFactory.java @@ -23,7 +23,6 @@ package java.net; * implementation. * * @see DatagramSocket - * @since Android 1.0 */ public interface DatagramSocketImplFactory { @@ -31,7 +30,6 @@ public interface DatagramSocketImplFactory { * Creates a new {@code DatagramSocketImpl} instance. * * @return the new datagram socket implementation. - * @since Android 1.0 */ DatagramSocketImpl createDatagramSocketImpl(); } diff --git a/luni/src/main/java/java/net/FileNameMap.java b/luni/src/main/java/java/net/FileNameMap.java index e8ac35f..16fa0e0 100644 --- a/luni/src/main/java/java/net/FileNameMap.java +++ b/luni/src/main/java/java/net/FileNameMap.java @@ -26,7 +26,6 @@ package java.net; * @see URLConnection#getFileNameMap() * @see URLConnection#guessContentTypeFromName(String) * @see URLStreamHandler - * @since Android 1.0 */ public interface FileNameMap { @@ -36,7 +35,6 @@ public interface FileNameMap { * @param fileName * the name of the file to consider. * @return the appropriate MIME type of the given file. - * @since Android 1.0 */ public String getContentTypeFor(String fileName); } diff --git a/luni/src/main/java/java/net/HttpRetryException.java b/luni/src/main/java/java/net/HttpRetryException.java index 5f613ab..4ad14bd 100644 --- a/luni/src/main/java/java/net/HttpRetryException.java +++ b/luni/src/main/java/java/net/HttpRetryException.java @@ -21,8 +21,6 @@ import java.io.IOException; /** * If a HTTP request has to be retried, this exception will be thrown if the * request cannot be retried automatically. - * - * @since Android 1.0 */ public class HttpRetryException extends IOException { @@ -40,7 +38,6 @@ public class HttpRetryException extends IOException { * the detail message for this exception. * @param code * the HTTP response code from target host. - * @since Android 1.0 */ public HttpRetryException(String detail, int code) { super(detail); @@ -58,7 +55,6 @@ public class HttpRetryException extends IOException { * the HTTP response code from target host. * @param location * the destination URL of the redirection. - * @since Android 1.0 */ public HttpRetryException(String detail, int code, String location) { super(detail); @@ -68,9 +64,8 @@ public class HttpRetryException extends IOException { /** * Gets the location value. - * + * * @return the stored location from the HTTP header. - * @since Android 1.0 */ public String getLocation() { return location; @@ -78,9 +73,8 @@ public class HttpRetryException extends IOException { /** * Gets the detail message. - * + * * @return the detail message. - * @since Android 1.0 */ public String getReason() { return getMessage(); @@ -88,9 +82,8 @@ public class HttpRetryException extends IOException { /** * Gets the response code. - * + * * @return the HTTP response code. - * @since Android 1.0 */ public int responseCode() { return responseCode; diff --git a/luni/src/main/java/java/net/HttpURLConnection.java b/luni/src/main/java/java/net/HttpURLConnection.java index 55cc363..6be891f 100644 --- a/luni/src/main/java/java/net/HttpURLConnection.java +++ b/luni/src/main/java/java/net/HttpURLConnection.java @@ -29,7 +29,6 @@ import org.apache.harmony.luni.util.Msg; * @see URL * @see URLConnection * @see URLStreamHandler - * @since Android 1.0 */ public abstract class HttpURLConnection extends URLConnection { @SuppressWarnings("nls") @@ -39,8 +38,6 @@ public abstract class HttpURLConnection extends URLConnection { /** * The HTTP request method of this {@code HttpURLConnection}. The default * value is {@code "GET"}. - * - * @since Android 1.0 */ protected String method = "GET"; //$NON-NLS-1$ @@ -53,24 +50,17 @@ public abstract class HttpURLConnection extends URLConnection { * <li>3xx: Relocation/Redirection</li> * <li>4xx: Client Error</li> * <li>5xx: Server Error</li> - * </p> - * - * @since Android 1.0 */ protected int responseCode = -1; /** * The HTTP response message which corresponds to the response code. - * - * @since Android 1.0 */ protected String responseMessage; /** * Flag to define whether the protocol will automatically follow redirects * or not. The default value is {@code true}. - * - * @since Android 1.0 */ protected boolean instanceFollowRedirects = followRedirects; @@ -80,8 +70,6 @@ public abstract class HttpURLConnection extends URLConnection { * If the HTTP chunked encoding is enabled this parameter defines the * chunk-length. Default value is {@code -1} that means the chunked encoding * mode is disabled. - * - * @since Android 1.0 */ protected int chunkLength = -1; @@ -89,8 +77,6 @@ public abstract class HttpURLConnection extends URLConnection { * If using HTTP fixed-length streaming mode this parameter defines the * fixed length of content. Default value is {@code -1} that means the * fixed-length streaming mode is disabled. - * - * @since Android 1.0 */ protected int fixedContentLength = -1; @@ -102,255 +88,184 @@ public abstract class HttpURLConnection extends URLConnection { // 5XX: server error /** * Numeric status code, 202: Accepted - * - * @since Android 1.0 */ public final static int HTTP_ACCEPTED = 202; /** * Numeric status code, 502: Bad Gateway - * - * @since Android 1.0 */ public final static int HTTP_BAD_GATEWAY = 502; /** * Numeric status code, 405: Bad Method - * - * @since Android 1.0 */ public final static int HTTP_BAD_METHOD = 405; /** * Numeric status code, 400: Bad Request - * - * @since Android 1.0 */ public final static int HTTP_BAD_REQUEST = 400; /** * Numeric status code, 408: Client Timeout - * - * @since Android 1.0 */ public final static int HTTP_CLIENT_TIMEOUT = 408; /** * Numeric status code, 409: Conflict - * - * @since Android 1.0 */ public final static int HTTP_CONFLICT = 409; /** * Numeric status code, 201: Created - * - * @since Android 1.0 */ public final static int HTTP_CREATED = 201; /** * Numeric status code, 413: Entity too large - * - * @since Android 1.0 */ public final static int HTTP_ENTITY_TOO_LARGE = 413; /** * Numeric status code, 403: Forbidden - * - * @since Android 1.0 */ public final static int HTTP_FORBIDDEN = 403; /** * Numeric status code, 504: Gateway timeout - * - * @since Android 1.0 */ public final static int HTTP_GATEWAY_TIMEOUT = 504; /** * Numeric status code, 410: Gone - * - * @since Android 1.0 */ public final static int HTTP_GONE = 410; /** * Numeric status code, 500: Internal error - * - * @since Android 1.0 */ public final static int HTTP_INTERNAL_ERROR = 500; /** * Numeric status code, 411: Length required - * - * @since Android 1.0 */ public final static int HTTP_LENGTH_REQUIRED = 411; /** * Numeric status code, 301 Moved permanently - * - * @since Android 1.0 */ public final static int HTTP_MOVED_PERM = 301; /** * Numeric status code, 302: Moved temporarily - * - * @since Android 1.0 */ public final static int HTTP_MOVED_TEMP = 302; /** * Numeric status code, 300: Multiple choices - * - * @since Android 1.0 */ public final static int HTTP_MULT_CHOICE = 300; /** * Numeric status code, 204: No content - * - * @since Android 1.0 */ public final static int HTTP_NO_CONTENT = 204; /** * Numeric status code, 406: Not acceptable - * - * @since Android 1.0 */ public final static int HTTP_NOT_ACCEPTABLE = 406; /** * Numeric status code, 203: Not authoritative - * - * @since Android 1.0 */ public final static int HTTP_NOT_AUTHORITATIVE = 203; /** * Numeric status code, 404: Not found - * - * @since Android 1.0 */ public final static int HTTP_NOT_FOUND = 404; /** * Numeric status code, 501: Not implemented - * - * @since Android 1.0 */ public final static int HTTP_NOT_IMPLEMENTED = 501; /** * Numeric status code, 304: Not modified - * - * @since Android 1.0 */ public final static int HTTP_NOT_MODIFIED = 304; /** * Numeric status code, 200: OK - * - * @since Android 1.0 */ public final static int HTTP_OK = 200; /** * Numeric status code, 206: Partial - * - * @since Android 1.0 */ public final static int HTTP_PARTIAL = 206; /** * Numeric status code, 402: Payment required - * - * @since Android 1.0 */ public final static int HTTP_PAYMENT_REQUIRED = 402; /** * Numeric status code, 412: Precondition failed - * - * @since Android 1.0 */ public final static int HTTP_PRECON_FAILED = 412; /** * Numeric status code, 407: Proxy authentication required - * - * @since Android 1.0 */ public final static int HTTP_PROXY_AUTH = 407; /** * Numeric status code, 414: Request too long - * - * @since Android 1.0 */ public final static int HTTP_REQ_TOO_LONG = 414; /** * Numeric status code, 205: Reset - * - * @since Android 1.0 */ public final static int HTTP_RESET = 205; /** * Numeric status code, 303: See other - * - * @since Android 1.0 */ public final static int HTTP_SEE_OTHER = 303; /** * Numeric status code, 500: Internal error - * + * * @deprecated Use {@link #HTTP_INTERNAL_ERROR} - * @since Android 1.0 */ @Deprecated public final static int HTTP_SERVER_ERROR = 500; /** * Numeric status code, 305: Use proxy - * - * @since Android 1.0 */ public final static int HTTP_USE_PROXY = 305; /** * Numeric status code, 401: Unauthorized - * - * @since Android 1.0 */ public final static int HTTP_UNAUTHORIZED = 401; /** * Numeric status code, 415: Unsupported type - * - * @since Android 1.0 */ public final static int HTTP_UNSUPPORTED_TYPE = 415; /** * Numeric status code, 503: Unavailable - * - * @since Android 1.0 */ public final static int HTTP_UNAVAILABLE = 503; /** * Numeric status code, 505: Version not supported - * - * @since Android 1.0 */ public final static int HTTP_VERSION = 505; @@ -362,7 +277,6 @@ public abstract class HttpURLConnection extends URLConnection { * the URL of this connection. * @see URL * @see URLConnection - * @since Android 1.0 */ protected HttpURLConnection(URL url) { super(url); @@ -373,7 +287,6 @@ public abstract class HttpURLConnection extends URLConnection { * * @see URLConnection#connect() * @see URLConnection#connected - * @since Android 1.0 */ public abstract void disconnect(); @@ -383,7 +296,6 @@ public abstract class HttpURLConnection extends URLConnection { * can be used to read the data the server will send back. * * @return the error input stream returned by the server. - * @since Android 1.0 */ public java.io.InputStream getErrorStream() { return null; @@ -396,7 +308,6 @@ public abstract class HttpURLConnection extends URLConnection { * * @return the value of the flag. * @see #setFollowRedirects - * @since Android 1.0 */ public static boolean getFollowRedirects() { return followRedirects; @@ -412,7 +323,6 @@ public abstract class HttpURLConnection extends URLConnection { * @throws IOException * if an IO exception occurs during the creation of the * permission object. - * @since Android 1.0 */ @Override public java.security.Permission getPermission() throws IOException { @@ -432,7 +342,6 @@ public abstract class HttpURLConnection extends URLConnection { * @return the request method string. * @see #method * @see #setRequestMethod - * @since Android 1.0 */ public String getRequestMethod() { return method; @@ -445,7 +354,6 @@ public abstract class HttpURLConnection extends URLConnection { * @throws IOException * if there is an IO error during the retrieval. * @see #getResponseMessage - * @since Android 1.0 */ public int getResponseCode() throws IOException { // Call getInputStream() first since getHeaderField() doesn't return @@ -478,7 +386,6 @@ public abstract class HttpURLConnection extends URLConnection { * @throws IOException * if there is an error during the retrieval. * @see #getResponseCode() - * @since Android 1.0 */ public String getResponseMessage() throws IOException { if (responseMessage != null) { @@ -496,7 +403,6 @@ public abstract class HttpURLConnection extends URLConnection { * @param auto * the value to enable or disable this option. * @see SecurityManager#checkSetFactory() - * @since Android 1.0 */ public static void setFollowRedirects(boolean auto) { SecurityManager security = System.getSecurityManager(); @@ -517,7 +423,6 @@ public abstract class HttpURLConnection extends URLConnection { * supported by this HTTP implementation. * @see #getRequestMethod() * @see #method - * @since Android 1.0 */ public void setRequestMethod(String method) throws ProtocolException { if (connected) { @@ -540,7 +445,6 @@ public abstract class HttpURLConnection extends URLConnection { * * @return {@code true} if this connection passes a proxy server, false * otherwise. - * @since Android 1.0 */ public abstract boolean usingProxy(); @@ -549,7 +453,6 @@ public abstract class HttpURLConnection extends URLConnection { * * @return {@code true} if this connection follows redirects, false * otherwise. - * @since Android 1.0 */ public boolean getInstanceFollowRedirects() { return instanceFollowRedirects; @@ -561,7 +464,6 @@ public abstract class HttpURLConnection extends URLConnection { * @param followRedirects * {@code true} if this connection will follows redirects, false * otherwise. - * @since Android 1.0 */ public void setInstanceFollowRedirects(boolean followRedirects) { instanceFollowRedirects = followRedirects; @@ -579,7 +481,6 @@ public abstract class HttpURLConnection extends URLConnection { * found. * @return the header field represented in milliseconds since January 1, * 1970 GMT. - * @since Android 1.0 */ @Override public long getHeaderFieldDate(String field, long defaultValue) { @@ -598,7 +499,6 @@ public abstract class HttpURLConnection extends URLConnection { * if already connected or an other mode already set. * @throws IllegalArgumentException * if {@code contentLength} is less than zero. - * @since Android 1.0 */ public void setFixedLengthStreamingMode(int contentLength) { if (super.connected) { @@ -624,7 +524,6 @@ public abstract class HttpURLConnection extends URLConnection { * the length of a chunk. * @throws IllegalStateException * if already connected or an other mode already set. - * @since Android 1.0 */ public void setChunkedStreamingMode(int chunklen) { if (super.connected) { diff --git a/luni/src/main/java/java/net/Inet4Address.java b/luni/src/main/java/java/net/Inet4Address.java index dd6b088..23efa5e 100644 --- a/luni/src/main/java/java/net/Inet4Address.java +++ b/luni/src/main/java/java/net/Inet4Address.java @@ -28,8 +28,6 @@ import java.io.ObjectStreamException; * address ({@code b.bbb} ) allows to represent a class A network address as * <i>net.host</i>. If there is only one part ({@code bbbb} ) the address is * represented without any byte rearrangement. - * - * @since Android 1.0 */ public final class Inet4Address extends InetAddress { @@ -50,7 +48,6 @@ public final class Inet4Address extends InetAddress { * * @return {@code true} if this instance represents a multicast address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMulticastAddress() { @@ -63,7 +60,6 @@ public final class Inet4Address extends InetAddress { * * @return {@code true} if this instance represents the wildcard ANY * address, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isAnyLocalAddress() { @@ -81,7 +77,6 @@ public final class Inet4Address extends InetAddress { * * @return {@code true} if this instance represents a lookback address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isLoopbackAddress() { @@ -95,11 +90,9 @@ public final class Inet4Address extends InetAddress { * Default Address Selection for Internet Protocol Version 6 (IPv6) states * IPv4 auto-configuration addresses, prefix 169.254/16, IPv4 loopback * addresses, prefix 127/8, are assigned link-local scope. - * </p> - * + * * @return {@code true} if this instance represents a link-local address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isLinkLocalAddress() { @@ -115,11 +108,9 @@ public final class Inet4Address extends InetAddress { * Default Address Selection for Internet Protocol Version 6 (IPv6) states * IPv4 private addresses, prefixes 10/8, 172.16/12, and 192.168/16, are * assigned site-local scope. - * </p> * * @return {@code true} if this instance represents a site-local address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isSiteLocalAddress() { @@ -135,7 +126,6 @@ public final class Inet4Address extends InetAddress { * * @return {@code true} if the address is in the global multicast group, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCGlobal() { @@ -174,7 +164,6 @@ public final class Inet4Address extends InetAddress { * addresses. * * @return {@code false} for all IPv4 addresses. - * @since Android 1.0 */ @Override public boolean isMCNodeLocal() { @@ -188,7 +177,6 @@ public final class Inet4Address extends InetAddress { * * @return {@code true} if this instance represents a link-local address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCLinkLocal() { @@ -202,7 +190,6 @@ public final class Inet4Address extends InetAddress { * * @return {@code true} if this instance represents a site-local address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCSiteLocal() { @@ -217,7 +204,6 @@ public final class Inet4Address extends InetAddress { * * @return {@code true} if this instance represents a organization-local * address, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCOrgLocal() { @@ -229,7 +215,6 @@ public final class Inet4Address extends InetAddress { * Returns a textual representation of this IP address. * * @return the textual representation of this host address. - * @since Android 1.0 */ @Override public String getHostAddress() { @@ -247,7 +232,6 @@ public final class Inet4Address extends InetAddress { * Gets the hashcode of the represented IP address. * * @return the appropriate hashcode value. - * @since Android 1.0 */ @Override public int hashCode() { @@ -262,7 +246,6 @@ public final class Inet4Address extends InetAddress { * @param obj * the object to be tested for equality. * @return {@code true} if the addresses are equal, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object obj) { diff --git a/luni/src/main/java/java/net/Inet6Address.java b/luni/src/main/java/java/net/Inet6Address.java index 4c10faa..0569829 100644 --- a/luni/src/main/java/java/net/Inet6Address.java +++ b/luni/src/main/java/java/net/Inet6Address.java @@ -28,8 +28,6 @@ import org.apache.harmony.luni.util.Msg; /** * This class represents a 128 bit long IPv6 address. - * - * @since Android 1.0 */ public final class Inet6Address extends InetAddress { @@ -80,7 +78,6 @@ public final class Inet6Address extends InetAddress { * the name associated with the address. * @param scope_id * the scope id for link- or site-local addresses. - * @since Android 1.0 */ Inet6Address(byte address[], String name, int scope_id) { hostName = name; @@ -104,7 +101,6 @@ public final class Inet6Address extends InetAddress { * @return the Inet6Address instance representing the IP address. * @throws UnknownHostException * if the address is null or has an invalid length. - * @since Android 1.0 */ public static Inet6Address getByAddress(String host, byte[] addr, int scope_id) throws UnknownHostException { @@ -135,7 +131,6 @@ public final class Inet6Address extends InetAddress { * if the address is {@code null} or has an invalid length or * the interface doesn't have a numeric scope id for the given * address type. - * @since Android 1.0 */ public static Inet6Address getByAddress(String host, byte[] addr, NetworkInterface nif) throws UnknownHostException { @@ -177,10 +172,11 @@ public final class Inet6Address extends InetAddress { /** * Returns {@code true} if one of following cases applies: * <p> - * <li>1. both addresses are site local</li> - * <li>2. both addresses are link local</li> - * <li>3. {@code ia} is neither site local nor link local</li> - * </p> + * <ol> + * <li>both addresses are site local</li> + * <li>both addresses are link local</li> + * <li>{@code ia} is neither site local nor link local</li> + * </ol> */ private boolean compareLocalType(Inet6Address ia) { if (ia.isSiteLocalAddress() && isSiteLocalAddress()) { @@ -203,7 +199,6 @@ public final class Inet6Address extends InetAddress { * the network address. * @param scope_id * the scope id for link- or site-local addresses. - * @since Android 1.0 */ Inet6Address(byte address[], int scope_id) { ipaddress = address; @@ -219,7 +214,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this address is in the multicast group, {@code * false} otherwise. - * @since Android 1.0 */ @Override public boolean isMulticastAddress() { @@ -233,7 +227,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents a wildcard address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isAnyLocalAddress() { @@ -251,7 +244,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents the loopback address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isLoopbackAddress() { @@ -277,7 +269,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents a link-local address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isLinkLocalAddress() { @@ -292,7 +283,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents a site-local address, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isSiteLocalAddress() { @@ -307,7 +297,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents a global multicast * address, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCGlobal() { @@ -323,7 +312,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents a node-local multicast * address, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCNodeLocal() { @@ -339,7 +327,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents a link-local multicast * address, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCLinkLocal() { @@ -355,7 +342,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents a site-local multicast * address, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCSiteLocal() { @@ -371,7 +357,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents a org-local multicast * address, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean isMCOrgLocal() { @@ -384,7 +369,6 @@ public final class Inet6Address extends InetAddress { * Gets the textual representation of this IP address. * * @return the as a dotted string formatted IP address. - * @since Android 1.0 */ @Override public String getHostAddress() { @@ -397,7 +381,6 @@ public final class Inet6Address extends InetAddress { * * @return the scope_id of this address or 0 when not linked with an * interface. - * @since Android 1.0 */ public int getScopeId() { if (scope_id_set) { @@ -411,7 +394,6 @@ public final class Inet6Address extends InetAddress { * network interface. Otherwise returns {@code null}. * * @return the scoped network interface of this address. - * @since Android 1.0 */ public NetworkInterface getScopedInterface() { if (scope_ifname_set) { @@ -424,7 +406,6 @@ public final class Inet6Address extends InetAddress { * Gets the hashcode of the represented IP address. * * @return the appropriate hashcode value. - * @since Android 1.0 */ @Override public int hashCode() { @@ -441,7 +422,6 @@ public final class Inet6Address extends InetAddress { * @param obj * the object to be tested for equality. * @return {@code true} if the addresses are equal, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object obj) { @@ -455,7 +435,6 @@ public final class Inet6Address extends InetAddress { * * @return {@code true} if this instance represents an IPv4 compatible * address, {@code false} otherwise. - * @since Android 1.0 */ public boolean isIPv4CompatibleAddress() { for (int i = 0; i < 12; i++) { @@ -506,7 +485,6 @@ public final class Inet6Address extends InetAddress { * IP address. * * @return the description, as host/address. - * @since Android 1.0 */ @Override public String toString() { diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java index 72c7669..fa3859b 100644 --- a/luni/src/main/java/java/net/InetAddress.java +++ b/luni/src/main/java/java/net/InetAddress.java @@ -41,8 +41,6 @@ import org.apache.harmony.luni.util.PriviAction; * encapsulates an IP address and provides name and reverse name resolution * functions. The address is stored in network order, but as a signed (rather * than unsigned) integer. - * - * @since Android 1.0 */ public class InetAddress extends Object implements Serializable { @@ -59,7 +57,7 @@ public class InetAddress extends Object implements Serializable { private static final String ERRMSG_CONNECTION_REFUSED = "Connection refused"; //$NON-NLS-1$ - private static final long serialVersionUID = 3286316764910316507L; + private static final long serialVersionUID = 3286316764910316507L; // BEGIN android-added /** @@ -86,7 +84,7 @@ public class InetAddress extends Object implements Serializable { // BEGIN android-removed // // Fill in the JNI id caches // private static native void oneTimeInitialization(boolean supportsIPv6); - // + // // static { // oneTimeInitialization(true); // } @@ -102,7 +100,7 @@ public class InetAddress extends Object implements Serializable { /** * Constructs an {@code InetAddress}, representing the {@code address} and * {@code hostName}. - * + * * @param address * the network address. */ @@ -114,7 +112,7 @@ public class InetAddress extends Object implements Serializable { /** * Constructs an {@code InetAddress}, representing the {@code address} and * {@code hostName}. - * + * * @param address * the network address. */ @@ -124,26 +122,6 @@ public class InetAddress extends Object implements Serializable { this.hostName = hostName; } - // BEGIN android-removed - // Removed in newer version of harmony - // /** - // * Returns the IP address of the argument {@code addr} as a byte array. The - // * elements are in network order (the highest order address byte is in the - // * zeroth element). - // * - // * @return the network address as a byte array. - // */ - // static byte[] addressOf(int addr) { - // int temp = addr; - // byte array[] = new byte[4]; - // array[3] = (byte) (temp & 0xFF); - // array[2] = (byte) ((temp >>>= 8) & 0xFF); - // array[1] = (byte) ((temp >>>= 8) & 0xFF); - // array[0] = (byte) ((temp >>>= 8) & 0xFF); - // return array; - // } - // BEGIN android-removed - CacheElement cacheElement() { return new CacheElement(); } @@ -152,11 +130,10 @@ public class InetAddress extends Object implements Serializable { * Compares this {@code InetAddress} instance against the specified address * in {@code obj}. Two addresses are equal if their address byte arrays have * the same length and if the bytes in the arrays are equal. - * + * * @param obj * the object to be tested for equality. * @return {@code true} if both objects are equal, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object obj) { @@ -185,9 +162,8 @@ public class InetAddress extends Object implements Serializable { * Returns the IP address represented by this {@code InetAddress} instance * as a byte array. The elements are in network order (the highest order * address byte is in the zeroth element). - * + * * @return the address in form of a byte array. - * @since Android 1.0 */ public byte[] getAddress() { return ipaddress.clone(); @@ -200,25 +176,21 @@ public class InetAddress extends Object implements Serializable { * {@code UnknownHostException} is thrown. If the host name is a dotted IP * address string an array with the corresponding single {@code InetAddress} * is returned. - * + * * @param host * the host's name or IP to be resolved to an address. * @return the array of addresses associated with the specified host. * @throws UnknownHostException * if the address lookup fails. - * @since Android 1.0 */ public static InetAddress[] getAllByName(String host) throws UnknownHostException { // BEGIN android-changed - // Added change taken from newer harmony concerning zero length hostname. - // Added special handling for localhost, since it doesn't work properly. + // Added special handling for "localhost", since it doesn't work properly. // TODO Get rid of this later... - if (host == null || 0 == host.length() || - "localhost".equalsIgnoreCase(host)) { - return new InetAddress[] { preferIPv6Addresses() - ? Inet6Address.LOOPBACK - : LOOPBACK }; + if (host == null || 0 == host.length() || "localhost".equalsIgnoreCase(host)) { + return new InetAddress[] { preferIPv6Addresses() ? Inet6Address.LOOPBACK + : LOOPBACK }; } // END android-changed @@ -241,7 +213,7 @@ public class InetAddress extends Object implements Serializable { } else { // Cannot happen, because the underlying code only returns // addresses that are 4 or 16 bytes long. - throw new AssertionError("Impossible address length " + + throw new AssertionError("Impossible address length " + rawAddress.length); } } @@ -289,14 +261,12 @@ public class InetAddress extends Object implements Serializable { } byte[] hBytes = Inet6Util.createByteArrayFromIPAddressString(host); - // BEGIN android-added - // Copied from a newer version of harmony if (hBytes.length == 4) { return (new InetAddress[] { new Inet4Address(hBytes) }); } else if (hBytes.length == 16) { return (new InetAddress[] { new Inet6Address(hBytes) }); } - // END android-added + return (new InetAddress[] { new InetAddress(hBytes) }); } @@ -306,20 +276,19 @@ public class InetAddress extends Object implements Serializable { * string IP address. If the latter, the {@code hostName} field is * determined upon demand. {@code host} can be {@code null} which means that * an address of the loopback interface is returned. - * + * * @param host * the hostName to be resolved to an address or {@code null}. * @return the {@code InetAddress} instance representing the host. * @throws UnknownHostException * if the address lookup fails. - * @since Android 1.0 */ public static InetAddress getByName(String host) throws UnknownHostException { // BEGIN android-changed // Added special handling for localhost, since it doesn't work properly. // TODO Get rid of this later... - if (host == null || 0 == host.length() || + if (host == null || 0 == host.length() || "localhost".equalsIgnoreCase(host)) { return InetAddress.LOOPBACK; } @@ -341,10 +310,9 @@ public class InetAddress extends Object implements Serializable { /** * Gets the textual representation of this IP address. - * + * * @return the textual representation of this host address in form of a * dotted string. - * @since Android 1.0 */ public String getHostAddress() { return inetNtoaImpl(bytesToInt(ipaddress, 0)); @@ -354,9 +322,8 @@ public class InetAddress extends Object implements Serializable { * Gets the host name of this IP address. If the IP address could not be * resolved, the textual representation in a dotted-quad-notation is * returned. - * + * * @return the corresponding string name of this IP address. - * @since Android 1.0 */ public String getHostName() { try { @@ -395,9 +362,8 @@ public class InetAddress extends Object implements Serializable { * address. If a security manager is set, it is checked if the method caller * is allowed to get the hostname. Otherwise, the textual representation in * a dotted-quad-notation is returned. - * + * * @return the fully qualified domain name of this IP address. - * @since Android 1.0 */ public String getCanonicalHostName() { String canonicalName; @@ -429,14 +395,10 @@ public class InetAddress extends Object implements Serializable { * Gets the local host address if the security policy allows this. * Otherwise, gets the loopback address which allows this machine to be * contacted. - * <p> - * The current implementation returns always the loopback address. - * </p> - * + * * @return the {@code InetAddress} representing the local host. * @throws UnknownHostException * if the address lookup fails. - * @since Android 1.0 */ public static InetAddress getLocalHost() throws UnknownHostException { String host = getHostNameImpl(); @@ -453,9 +415,8 @@ public class InetAddress extends Object implements Serializable { /** * Gets the hashcode of the represented IP address. - * + * * @return the appropriate hashcode value. - * @since Android 1.0 */ @Override public int hashCode() { @@ -464,10 +425,9 @@ public class InetAddress extends Object implements Serializable { /** * Returns whether this address is an IP multicast address or not. - * + * * @return {@code true} if this address is in the multicast group, {@code * false} otherwise. - * @since Android 1.0 */ public boolean isMulticastAddress() { return ((ipaddress[0] & 255) >>> 4) == 0xE; @@ -507,10 +467,12 @@ public class InetAddress extends Object implements Serializable { return element.inetAddress(); } + // TODO Clean up NegativeCache; there's no need to maintain the failure message + // now try the negative cache String failedMessage = NegativeCache.getFailedMessage(host); if (failedMessage != null) { - throw new UnknownHostException(host + " - " + failedMessage); //$NON-NLS-1$ + throw new UnknownHostException(host); } InetAddress anInetAddress; @@ -519,7 +481,8 @@ public class InetAddress extends Object implements Serializable { } catch (UnknownHostException e) { // put the entry in the negative cache NegativeCache.put(host, e.getMessage()); - throw new UnknownHostException(host + " - " + e.getMessage()); //$NON-NLS-1$ + // use host for message to match RI, save the cause for giggles + throw (UnknownHostException)new UnknownHostException(host).initCause(e); } Cache.add(anInetAddress); @@ -540,17 +503,17 @@ public class InetAddress extends Object implements Serializable { // throws UnknownHostException; // END android-deleted - // BEGIN android-changed + // BEGIN android-added /** * Resolves a host name to its IP addresses. Thread safe. */ private static native byte[][] getallbyname(String name, boolean preferIPv4Stack); - // END android-changed + // END android-added /** * Query the IP stack for the host address. The host is in address form. - * + * * @param addr * the host address to lookup. * @throws UnknownHostException @@ -587,12 +550,12 @@ public class InetAddress extends Object implements Serializable { // TODO Probably not exactly what we want, and also inefficient. Provide native later. try { String[] args = host.split("\\."); - + int a = Integer.parseInt(args[0]) << 24; int b = Integer.parseInt(args[1]) << 16; int c = Integer.parseInt(args[2]) << 8; int d = Integer.parseInt(args[3]) ; - + return a | b | c | d; } catch (Exception ex) { throw new UnknownHostException(host); @@ -612,17 +575,17 @@ public class InetAddress extends Object implements Serializable { int b = (hipAddr >> 16) & 0xFF; int c = (hipAddr >> 8) & 0xFF; int d = (hipAddr ) & 0xFF; - + return "" + a + "." + b + "." + c + "." + d; } // END android-changed /** * Query the IP stack for the host address. The host is in string name form. - * + * * @param name * the host name to lookup - * @param preferIPv6Addresses + * @param preferIPv6Address * address preference if underlying platform is V4/V6 * @return InetAddress the host address * @throws UnknownHostException @@ -640,7 +603,7 @@ public class InetAddress extends Object implements Serializable { /** * Gets the host name of the system. - * + * * @return String the system hostname */ // BEGIN android-changed @@ -665,9 +628,8 @@ public class InetAddress extends Object implements Serializable { /** * Returns a string containing a concise, human-readable description of this * IP address. - * + * * @return the description, as host/address. - * @since Android 1.0 */ @Override public String toString() { @@ -695,8 +657,6 @@ public class InetAddress extends Object implements Serializable { } } - // BEGIN android-changed - // Copied from a newer version of harmony static class Cache { private static int maxSize = 5; @@ -764,7 +724,6 @@ public class InetAddress extends Object implements Serializable { } } } - // END android-changed /** * Returns true if the string is a host name, false if it is an IP Address. @@ -778,10 +737,9 @@ public class InetAddress extends Object implements Serializable { * Returns whether this address is a loopback address or not. This * implementation returns always {@code false}. Valid IPv4 loopback * addresses are 127.d.d.d The only valid IPv6 loopback address is ::1. - * + * * @return {@code true} if this instance represents a loopback address, * {@code false} otherwise. - * @since Android 1.0 */ public boolean isLoopbackAddress() { return false; @@ -793,14 +751,11 @@ public class InetAddress extends Object implements Serializable { * <p> * Valid IPv6 link-local addresses are FE80::0 through to * FEBF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF. - * </p> * <p> * There are no valid IPv4 link-local addresses. - * </p> - * + * * @return {@code true} if this instance represents a link-local address, * {@code false} otherwise. - * @since Android 1.0 */ public boolean isLinkLocalAddress() { return false; @@ -812,14 +767,11 @@ public class InetAddress extends Object implements Serializable { * <p> * Valid IPv6 site-local addresses are FEC0::0 through to * FEFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF. - * </p> * <p> * There are no valid IPv4 site-local addresses. - * </p> - * + * * @return {@code true} if this instance represents a site-local address, * {@code false} otherwise. - * @since Android 1.0 */ public boolean isSiteLocalAddress() { return false; @@ -832,15 +784,12 @@ public class InetAddress extends Object implements Serializable { * Valid IPv6 link-global multicast addresses are FFxE:/112 where x is a set * of flags, and the additional 112 bits make up the global multicast * address space. - * </p> * <p> * Valid IPv4 global multicast addresses are between: 224.0.1.0 to * 238.255.255.255. - * </p> - * + * * @return {@code true} if this instance represents a global multicast * address, {@code false} otherwise. - * @since Android 1.0 */ public boolean isMCGlobal() { return false; @@ -853,14 +802,11 @@ public class InetAddress extends Object implements Serializable { * Valid IPv6 node-local multicast addresses are FFx1:/112 where x is a set * of flags, and the additional 112 bits make up the node-local multicast * address space. - * </p> * <p> * There are no valid IPv4 node-local multicast addresses. - * </p> - * + * * @return {@code true} if this instance represents a node-local multicast * address, {@code false} otherwise. - * @since Android 1.0 */ public boolean isMCNodeLocal() { return false; @@ -873,14 +819,11 @@ public class InetAddress extends Object implements Serializable { * Valid IPv6 link-local multicast addresses are FFx2:/112 where x is a set * of flags, and the additional 112 bits make up the link-local multicast * address space. - * </p> * <p> * Valid IPv4 link-local addresses are between: 224.0.0.0 to 224.0.0.255 - * </p> - * + * * @return {@code true} if this instance represents a link-local multicast * address, {@code false} otherwise. - * @since Android 1.0 */ public boolean isMCLinkLocal() { return false; @@ -893,15 +836,12 @@ public class InetAddress extends Object implements Serializable { * Valid IPv6 site-local multicast addresses are FFx5:/112 where x is a set * of flags, and the additional 112 bits make up the site-local multicast * address space. - * </p> * <p> * Valid IPv4 site-local addresses are between: 239.252.0.0 to * 239.255.255.255 - * </p> - * + * * @return {@code true} if this instance represents a site-local multicast * address, {@code false} otherwise. - * @since Android 1.0 */ public boolean isMCSiteLocal() { return false; @@ -914,15 +854,12 @@ public class InetAddress extends Object implements Serializable { * Valid IPv6 organization-local multicast addresses are FFx8:/112 where x * is a set of flags, and the additional 112 bits make up the * organization-local multicast address space. - * </p> * <p> * Valid IPv4 organization-local addresses are between: 239.192.0.0 to * 239.251.255.255 - * </p> - * + * * @return {@code true} if this instance represents a organization-local * multicast address, {@code false} otherwise. - * @since Android 1.0 */ public boolean isMCOrgLocal() { return false; @@ -931,10 +868,9 @@ public class InetAddress extends Object implements Serializable { /** * Returns whether this is a wildcard address or not. This implementation * returns always {@code false}. - * + * * @return {@code true} if this instance represents a wildcard address, * {@code false} otherwise. - * @since Android 1.0 */ public boolean isAnyLocalAddress() { return false; @@ -944,7 +880,7 @@ public class InetAddress extends Object implements Serializable { * Tries to reach this {@code InetAddress}. This method first tries to use * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection * on port 7 (Echo) of the remote host is established. - * + * * @param timeout * timeout in milliseconds before the test fails if no connection * could be established. @@ -954,7 +890,6 @@ public class InetAddress extends Object implements Serializable { * if an error occurs during an I/O operation. * @throws IllegalArgumentException * if timeout is less than zero. - * @since Android 1.0 */ public boolean isReachable(int timeout) throws IOException { return isReachable(null, 0, timeout); @@ -964,7 +899,7 @@ public class InetAddress extends Object implements Serializable { * Tries to reach this {@code InetAddress}. This method first tries to use * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection * on port 7 (Echo) of the remote host is established. - * + * * @param netif * the network interface on which to connection should be * established. @@ -979,7 +914,6 @@ public class InetAddress extends Object implements Serializable { * if an error occurs during an I/O operation. * @throws IllegalArgumentException * if ttl or timeout is less than zero. - * @since Android 1.0 */ public boolean isReachable(NetworkInterface netif, final int ttl, final int timeout) throws IOException { @@ -1073,8 +1007,8 @@ public class InetAddress extends Object implements Serializable { // InetAddress.this, addr, ttl, timeout); // } else { try { - threadReached = isReachableByTCP(InetAddress.this, - addr, timeout); + threadReached = isReachableByTCP(addr, + InetAddress.this, timeout); } catch (IOException e) { // do nothing } @@ -1122,7 +1056,7 @@ public class InetAddress extends Object implements Serializable { // int ttl, int timeout) throws IOException { // return isReachableByMultiThread(netif, ttl, timeout, true); // } - // + // // private boolean isReachableByTCPUseMultiThread(NetworkInterface netif, // int ttl, int timeout) throws IOException { // return isReachableByMultiThread(netif, ttl, timeout, false); @@ -1135,10 +1069,10 @@ public class InetAddress extends Object implements Serializable { // define traffic only for parameter int traffic = 0; boolean reached = false; - NETIMPL.createSocket(fd, NetUtil.preferIPv4Stack()); + NETIMPL.createStreamSocket(fd, NetUtil.preferIPv4Stack()); try { if (null != source) { - NETIMPL.bind(fd, 0, source); + NETIMPL.bind(fd, source, 0); } NETIMPL.connectStreamWithTimeoutSocket(fd, 7, timeout, traffic, dest); @@ -1161,18 +1095,15 @@ public class InetAddress extends Object implements Serializable { * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown. * <p> * The IP address is not validated by a name service. - * </p> * <p> * The high order byte is {@code ipAddress[0]}. - * </p> - * + * * @param ipAddress * is either a 4 (IPv4) or 16 (IPv6) byte long array. * @return an {@code InetAddress} instance representing the given IP address * {@code ipAddress}. * @throws UnknownHostException * if the given byte array has no valid length. - * @since Android 1.0 */ public static InetAddress getByAddress(byte[] ipAddress) throws UnknownHostException { @@ -1187,7 +1118,7 @@ public class InetAddress extends Object implements Serializable { * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown. The * IP address is not validated by a name service. The high order byte is * {@code ipAddress[0]}. - * + * * @param ipAddress * either a 4 (IPv4) or 16 (IPv6) byte array. * @param scope_id @@ -1204,10 +1135,7 @@ public class InetAddress extends Object implements Serializable { for (int i = 0; i < 4; i++) { copy_address[i] = ipAddress[i]; } - // BEGIN adnroid-changed - // Copied from a newer version of harmony return new Inet4Address(copy_address); - // END android-changed } if (ipAddress != null && ipAddress.length == 16) { @@ -1224,6 +1152,8 @@ public class InetAddress extends Object implements Serializable { copy_address = ipAddress.clone(); return new Inet6Address(copy_address, scope_id); } + + // K0339=Invalid IP Address is neither 4 or 16 bytes throw new UnknownHostException(Msg.getString("K0339")); //$NON-NLS-1$ } @@ -1251,15 +1181,12 @@ public class InetAddress extends Object implements Serializable { * UnknownHostException} will be thrown. * <p> * The host name and IP address are not validated. - * </p> * <p> * The hostname either be a machine alias or a valid IPv6 or IPv4 address * format. - * </p> * <p> * The high order byte is {@code ipAddress[0]}. - * </p> - * + * * @param hostName * the string representation of hostname or IP address. * @param ipAddress @@ -1268,7 +1195,6 @@ public class InetAddress extends Object implements Serializable { * and hostname. * @throws UnknownHostException * if the given byte array has no valid length. - * @since Android 1.0 */ public static InetAddress getByAddress(String hostName, byte[] ipAddress) throws UnknownHostException { @@ -1284,7 +1210,7 @@ public class InetAddress extends Object implements Serializable { * UnknownHostException} is thrown. The host name and IP address are not * validated. The hostname either be a machine alias or a valid IPv6 or IPv4 * address format. The high order byte is {@code ipAddress[0]}. - * + * * @param hostName * string representation of hostname or IP address. * @param ipAddress diff --git a/luni/src/main/java/java/net/InetSocketAddress.java b/luni/src/main/java/java/net/InetSocketAddress.java index 6901053..13c10f2 100644 --- a/luni/src/main/java/java/net/InetSocketAddress.java +++ b/luni/src/main/java/java/net/InetSocketAddress.java @@ -23,8 +23,6 @@ import java.io.ObjectInputStream; /** * This class represents a socket endpoint described by a IP address and a port * number. It is a concrete implementation of {@code SocketAddress} for IP. - * - * @since Android 1.0 */ public class InetSocketAddress extends SocketAddress { @@ -40,10 +38,9 @@ public class InetSocketAddress extends SocketAddress { * Creates a socket endpoint with the given port number {@code port} and the * wildcard address {@code InetAddress.ANY}. The range for valid port numbers * is between 0 and 65535 inclusive. - * + * * @param port * the specified port number to which this socket is bound. - * @since Android 1.0 */ public InetSocketAddress(int port) { this((InetAddress) null, port); @@ -54,12 +51,11 @@ public class InetSocketAddress extends SocketAddress { * {@code address}. The range for valid port numbers is between 0 and 65535 * inclusive. If {@code address} is {@code null} this socket is bound to the * wildcard address {@code InetAddress.ANY}. - * + * * @param port * the specified port number to which this socket is bound. * @param address * the specified address to which this socket is bound. - * @since Android 1.0 */ public InetSocketAddress(InetAddress address, int port) { if (port < 0 || port > 65535) { @@ -79,7 +75,7 @@ public class InetSocketAddress extends SocketAddress { * hostname {@code host}. The hostname is tried to be resolved and cannot be * {@code null}. The range for valid port numbers is between 0 and 65535 * inclusive. - * + * * @param port * the specified port number to which this socket is bound. * @param host @@ -88,14 +84,13 @@ public class InetSocketAddress extends SocketAddress { * if a {@link SecurityManager} is installed and its {@code * checkConnect()} method does not allow the resolving of the * host name. - * @since Android 1.0 */ public InetSocketAddress(String host, int port) { this(host, port, true); } /* - * Internal contructor for InetSocketAddress(String, int) and + * Internal constructor for InetSocketAddress(String, int) and * createUnresolved(String, int); */ InetSocketAddress(String host, int port, boolean needResolved) { @@ -126,7 +121,7 @@ public class InetSocketAddress extends SocketAddress { * Creates an {@code InetSocketAddress} without trying to resolve the * hostname into an {@code InetAddress}. The address field is marked as * unresolved. - * + * * @param host * the specified hostname to which this socket is bound. * @param port @@ -135,7 +130,6 @@ public class InetSocketAddress extends SocketAddress { * @throws IllegalArgumentException * if the hostname {@code host} is {@code null} or the port is * not in the range between 0 and 65535. - * @since Android 1.0 */ public static InetSocketAddress createUnresolved(String host, int port) { return new InetSocketAddress(host, port, false); @@ -143,9 +137,8 @@ public class InetSocketAddress extends SocketAddress { /** * Gets the port number of this socket. - * + * * @return the socket endpoint port number. - * @since Android 1.0 */ public final int getPort() { return port; @@ -153,9 +146,8 @@ public class InetSocketAddress extends SocketAddress { /** * Gets the address of this socket. - * + * * @return the socket endpoint address. - * @since Android 1.0 */ public final InetAddress getAddress() { return addr; @@ -163,9 +155,8 @@ public class InetSocketAddress extends SocketAddress { /** * Gets the hostname of this socket. - * + * * @return the socket endpoint hostname. - * @since Android 1.0 */ public final String getHostName() { return (null != addr) ? addr.getHostName() : hostname; @@ -173,10 +164,9 @@ public class InetSocketAddress extends SocketAddress { /** * Returns whether this socket address is unresolved or not. - * + * * @return {@code true} if this socket address is unresolved, {@code false} * otherwise. - * @since Android 1.0 */ public final boolean isUnresolved() { return addr == null; @@ -185,9 +175,8 @@ public class InetSocketAddress extends SocketAddress { /** * Gets a string representation of this socket included the address and the * port number. - * + * * @return the address and port number as a textual representation. - * @since Android 1.0 */ @Override public String toString() { @@ -204,12 +193,11 @@ public class InetSocketAddress extends SocketAddress { * Compares two socket endpoints and returns true if they are equal. Two * socket endpoints are equal if the IP address or the hostname of both are * equal and they are bound to the same port. - * + * * @param socketAddr * the object to be tested for equality. * @return {@code true} if this socket and the given socket object {@code * socketAddr} are equal, {@code false} otherwise. - * @since Android 1.0 */ @Override public final boolean equals(Object socketAddr) { @@ -243,9 +231,8 @@ public class InetSocketAddress extends SocketAddress { /** * Gets the hashcode of this socket. - * + * * @return the appropriate hashcode. - * @since Android 1.0 */ @Override public final int hashCode() { diff --git a/luni/src/main/java/java/net/JarURLConnection.java b/luni/src/main/java/java/net/JarURLConnection.java index 11545fa..da39d9c 100644 --- a/luni/src/main/java/java/net/JarURLConnection.java +++ b/luni/src/main/java/java/net/JarURLConnection.java @@ -38,15 +38,11 @@ import java.util.jar.Manifest; * jar:http://www.example.com/applets/archive.jar!/test.class}</li> * <li>Directory Entry: {@code * jar:http://www.example.com/applets/archive.jar!/applets/}</li> - * - * @since Android 1.0 */ public abstract class JarURLConnection extends URLConnection { /** * The location part of the represented URL. - * - * @since Android 1.0 */ protected URLConnection jarFileURLConnection; @@ -60,12 +56,11 @@ public abstract class JarURLConnection extends URLConnection { /** * Constructs an instance of {@code JarURLConnection} that refers to the * specified URL. - * + * * @param url * the URL that contains the location to connect to. * @throws MalformedURLException * if an invalid URL has been entered. - * @since Android 1.0 */ protected JarURLConnection(URL url) throws MalformedURLException { super(url); @@ -74,10 +69,12 @@ public abstract class JarURLConnection extends URLConnection { if ((sepIdx = file.indexOf("!/")) < 0) { //$NON-NLS-1$ throw new MalformedURLException(); } - if (file.length() == sepIdx + 2) { + fileURL = new URL(url.getFile().substring(0,sepIdx)); //$NON-NLS-1$ + sepIdx += 2; + if (file.length() == sepIdx) { return; } - entryName = file.substring(sepIdx + 2, file.length()); + entryName = file.substring(sepIdx, file.length()); if (null != url.getRef()) { entryName += "#" + url.getRef(); //$NON-NLS-1$ } @@ -86,12 +83,11 @@ public abstract class JarURLConnection extends URLConnection { /** * Returns all attributes of the {@code JarEntry} referenced by this {@code * JarURLConnection}. - * + * * @return the attributes of the referenced {@code JarEntry}. - * @exception IOException + * @throws IOException * if an I/O exception occurs while retrieving the * JAR-entries. - * @since Android 1.0 */ public Attributes getAttributes() throws java.io.IOException { JarEntry jEntry = getJarEntry(); @@ -102,12 +98,11 @@ public abstract class JarURLConnection extends URLConnection { * Returns all certificates of the {@code JarEntry} referenced by this * {@code JarURLConnection} instance. This method will return {@code null} * until the {@code InputStream} has been completely verified. - * + * * @return the certificates of the {@code JarEntry} as an array. - * @exception IOException + * @throws IOException * if there is an I/O exception occurs while getting the * {@code JarEntry}. - * @since Android 1.0 */ public Certificate[] getCertificates() throws java.io.IOException { JarEntry jEntry = getJarEntry(); @@ -122,9 +117,8 @@ public abstract class JarURLConnection extends URLConnection { * Gets the name of the entry referenced by this {@code JarURLConnection}. * The return value will be {@code null} if this instance refers to a JAR * file rather than an JAR file entry. - * + * * @return the {@code JarEntry} name this instance refers to. - * @since Android 1.0 */ public String getEntryName() { return entryName; @@ -133,12 +127,11 @@ public abstract class JarURLConnection extends URLConnection { /** * Gets the {@code JarEntry} object of the entry referenced by this {@code * JarURLConnection}. - * + * * @return the referenced {@code JarEntry} object or {@code null} if no * entry name is specified. * @throws IOException * if an error occurs while getting the file or file-entry. - * @since Android 1.0 */ public JarEntry getJarEntry() throws IOException { if (!connected) { @@ -153,56 +146,44 @@ public abstract class JarURLConnection extends URLConnection { /** * Gets the manifest file associated with this JAR-URL. - * + * * @return the manifest of the referenced JAR-file. * @throws IOException * if an error occurs while getting the manifest file. - * @since Android 1.0 */ public Manifest getManifest() throws java.io.IOException { - return getJarFile().getManifest(); + return (Manifest)getJarFile().getManifest().clone(); } /** * Gets the {@code JarFile} object referenced by this {@code * JarURLConnection}. - * + * * @return the referenced JarFile object. - * @exception IOException + * @throws IOException * if an I/O exception occurs while retrieving the JAR-file. - * @since Android 1.0 */ public abstract JarFile getJarFile() throws java.io.IOException; /** * Gets the URL to the JAR-file referenced by this {@code JarURLConnection}. - * + * * @return the URL to the JAR-file or {@code null} if there was an error * retrieving the URL. - * @since Android 1.0 */ public URL getJarFileURL() { - if (fileURL != null) { - return fileURL; - } - try { - return fileURL = new URL(url.getFile().substring(0, - url.getFile().indexOf("!/"))); //$NON-NLS-1$ - } catch (MalformedURLException e) { - return null; - } + return fileURL; } /** * Gets all attributes of the manifest file referenced by this {@code * JarURLConnection}. If this instance refers to a JAR-file rather than a * JAR-file entry, {@code null} will be returned. - * + * * @return the attributes of the manifest file or {@code null}. - * @exception IOException + * @throws IOException * if an I/O exception occurs while retrieving the {@code * JarFile}. - * @since Android 1.0 */ public Attributes getMainAttributes() throws java.io.IOException { Manifest m = getJarFile().getManifest(); diff --git a/luni/src/main/java/java/net/MalformedURLException.java b/luni/src/main/java/java/net/MalformedURLException.java index 386228b..cf8aa46 100644 --- a/luni/src/main/java/java/net/MalformedURLException.java +++ b/luni/src/main/java/java/net/MalformedURLException.java @@ -24,7 +24,6 @@ import java.io.IOException; * incorrect specification. * * @see URL - * @since Android 1.0 */ public class MalformedURLException extends IOException { @@ -32,8 +31,6 @@ public class MalformedURLException extends IOException { /** * Constructs a new instance of this class with its walkback filled in. - * - * @since Android 1.0 */ public MalformedURLException() { super(); @@ -45,7 +42,6 @@ public class MalformedURLException extends IOException { * * @param detailMessage * the detail message for this exception instance. - * @since Android 1.0 */ public MalformedURLException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/MulticastSocket.java b/luni/src/main/java/java/net/MulticastSocket.java index cf20890..0b1c99b 100644 --- a/luni/src/main/java/java/net/MulticastSocket.java +++ b/luni/src/main/java/java/net/MulticastSocket.java @@ -20,15 +20,14 @@ package java.net; import java.io.IOException; import java.util.Enumeration; -import org.apache.harmony.luni.net.SocketImplProvider; +import org.apache.harmony.luni.net.PlainDatagramSocketImpl; import org.apache.harmony.luni.util.Msg; /** * This class implements a multicast socket for sending and receiving IP * multicast datagram packets. - * + * * @see DatagramSocket - * @since Android 1.0 */ public class MulticastSocket extends DatagramSocket { @@ -39,10 +38,9 @@ public class MulticastSocket extends DatagramSocket { /** * Constructs a multicast socket, bound to any available port on the * localhost. - * + * * @throws IOException * if an error occurs creating or binding the socket. - * @since Android 1.0 */ public MulticastSocket() throws IOException { super(); @@ -52,12 +50,11 @@ public class MulticastSocket extends DatagramSocket { /** * Constructs a multicast socket, bound to the specified port on the * localhost. - * + * * @param aPort * the port to bind on the localhost. * @throws IOException * if an error occurs creating or binding the socket. - * @since Android 1.0 */ public MulticastSocket(int aPort) throws IOException { super(aPort); @@ -67,12 +64,11 @@ public class MulticastSocket extends DatagramSocket { /** * Gets the network address used by this socket. This is useful on * multihomed machines. - * + * * @return the address of the network interface through which the datagram * packets are sent or received. - * @exception SocketException + * @throws SocketException * if an error occurs while getting the interface address. - * @since Android 1.0 */ public InetAddress getInterface() throws SocketException { checkClosedAndBind(false); @@ -104,12 +100,12 @@ public class MulticastSocket extends DatagramSocket { /** * Gets the network interface used by this socket. This is useful on * multihomed machines. - * + * * @return the network interface used by this socket or {@code null} if no * interface is set. - * @exception SocketException + * @throws SocketException * if an error occurs while getting the interface. - * @since Android 1.0 + * @since 1.4 */ public NetworkInterface getNetworkInterface() throws SocketException { checkClosedAndBind(false); @@ -162,11 +158,10 @@ public class MulticastSocket extends DatagramSocket { /** * Gets the time-to-live (TTL) for multicast packets sent on this socket. - * + * * @return the default value for the time-to-life field. - * @exception IOException + * @throws IOException * if an error occurs reading the default value. - * @since Android 1.0 */ public int getTimeToLive() throws IOException { checkClosedAndBind(false); @@ -175,13 +170,12 @@ public class MulticastSocket extends DatagramSocket { /** * Gets the time-to-live (TTL) for multicast packets sent on this socket. - * + * * @return the default value for the time-to-life field. - * @exception IOException + * @throws IOException * if an error occurs reading the default value. * @deprecated Replaced by {@link #getTimeToLive} * @see #getTimeToLive() - * @since Android 1.0 */ @Deprecated public byte getTTL() throws IOException { @@ -189,21 +183,15 @@ public class MulticastSocket extends DatagramSocket { return impl.getTTL(); } - @Override - boolean isMulticastSocket() { - return true; - } - /** * Adds this socket to the specified multicast group. A socket must join a * group before data may be received. A socket may be a member of multiple * groups but may join any group only once. - * + * * @param groupAddr * the multicast group to be joined. - * @exception IOException + * @throws IOException * if an error occurs while joining a group. - * @since Android 1.0 */ public void joinGroup(InetAddress groupAddr) throws IOException { checkClosedAndBind(false); @@ -221,19 +209,19 @@ public class MulticastSocket extends DatagramSocket { * Adds this socket to the specified multicast group. A socket must join a * group before data may be received. A socket may be a member of multiple * groups but may join any group only once. - * + * * @param groupAddress * the multicast group to be joined. * @param netInterface * the network interface on which the datagram packets will be * received. - * @exception IOException + * @throws IOException * if the specified address is not a multicast address. - * @exception SecurityException + * @throws SecurityException * if the caller is not authorized to join the group. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if no multicast group is specified. - * @since Android 1.0 + * @since 1.4 */ public void joinGroup(SocketAddress groupAddress, NetworkInterface netInterface) throws IOException { @@ -271,14 +259,15 @@ public class MulticastSocket extends DatagramSocket { /** * Removes this socket from the specified multicast group. - * + * * @param groupAddr * the multicast group to be left. - * @exception IOException + * @throws NullPointerException + * if {@code groupAddr} is {@code null}. + * @throws IOException * if the specified group address is not a multicast address. - * @exception SecurityException + * @throws SecurityException * if the caller is not authorized to leave the group. - * @since Android 1.0 */ public void leaveGroup(InetAddress groupAddr) throws IOException { checkClosedAndBind(false); @@ -294,19 +283,19 @@ public class MulticastSocket extends DatagramSocket { /** * Removes this socket from the specified multicast group. - * + * * @param groupAddress * the multicast group to be left. * @param netInterface * the network interface on which the addresses should be * dropped. - * @exception IOException + * @throws IOException * if the specified group address is not a multicast address. - * @exception SecurityException + * @throws SecurityException * if the caller is not authorized to leave the group. - * @exception IllegalArgumentException - * if no multicast group is specified. - * @since Android 1.0 + * @throws IllegalArgumentException + * if {@code groupAddress} is {@code null}. + * @since 1.4 */ public void leaveGroup(SocketAddress groupAddress, NetworkInterface netInterface) throws IOException { @@ -344,16 +333,15 @@ public class MulticastSocket extends DatagramSocket { /** * Send the packet on this socket. The packet must satisfy the security * policy before it may be sent. - * + * * @param pack * the {@code DatagramPacket} to send * @param ttl * the TTL setting for this transmission, overriding the socket * default - * @exception IOException + * @throws IOException * if an error occurs while sending data or setting options. * @deprecated use {@link #setTimeToLive}. - * @since Android 1.0 */ @Deprecated public void send(DatagramPacket pack, byte ttl) throws IOException { @@ -384,13 +372,12 @@ public class MulticastSocket extends DatagramSocket { * Sets the interface address used by this socket. This allows to send * multicast packets on a different interface than the default interface of * the local system. This is useful on multihomed machines. - * + * * @param addr * the multicast interface network address to set. - * @exception SocketException + * @throws SocketException * if an error occurs while setting the network interface * address option. - * @since Android 1.0 */ public void setInterface(InetAddress addr) throws SocketException { checkClosedAndBind(false); @@ -435,13 +422,13 @@ public class MulticastSocket extends DatagramSocket { /** * Sets the network interface used by this socket. This is useful for * multihomed machines. - * + * * @param netInterface * the multicast network interface to set. - * @exception SocketException + * @throws SocketException * if an error occurs while setting the network interface * option. - * @since Android 1.0 + * @since 1.4 */ public void setNetworkInterface(NetworkInterface netInterface) throws SocketException { @@ -529,13 +516,12 @@ public class MulticastSocket extends DatagramSocket { /** * Sets the time-to-live (TTL) for multicast packets sent on this socket. * Valid TTL values are between 0 and 255 inclusive. - * + * * @param ttl * the default time-to-live field value for packets sent on this * socket. {@code 0 <= ttl <= 255}. - * @exception IOException + * @throws IOException * if an error occurs while setting the TTL option value. - * @since Android 1.0 */ public void setTimeToLive(int ttl) throws IOException { checkClosedAndBind(false); @@ -548,15 +534,14 @@ public class MulticastSocket extends DatagramSocket { /** * Sets the time-to-live (TTL) for multicast packets sent on this socket. * Valid TTL values are between 0 and 255 inclusive. - * + * * @param ttl * the default time-to-live field value for packets sent on this * socket: {@code 0 <= ttl <= 255}. - * @exception IOException + * @throws IOException * if an error occurs while setting the TTL option value. * @deprecated Replaced by {@link #setTimeToLive} * @see #setTimeToLive(int) - * @since Android 1.0 */ @Deprecated public void setTTL(byte ttl) throws IOException { @@ -568,11 +553,10 @@ public class MulticastSocket extends DatagramSocket { synchronized void createSocket(int aPort, InetAddress addr) throws SocketException { impl = factory != null ? factory.createDatagramSocketImpl() - : SocketImplProvider.getMulticastSocketImpl(); + : new PlainDatagramSocketImpl(); impl.create(); try { - // the required default options are now set in the VM where they - // should be + impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.TRUE); impl.bind(aPort, addr); isBound = true; } catch (SocketException e) { @@ -585,14 +569,14 @@ public class MulticastSocket extends DatagramSocket { * Constructs a {@code MulticastSocket} bound to the host/port specified by * the {@code SocketAddress}, or an unbound {@code DatagramSocket} if the * {@code SocketAddress} is {@code null}. - * + * * @param localAddr * the local machine address and port to bind to. * @throws IllegalArgumentException * if the {@code SocketAddress} is not supported. * @throws IOException * if an error occurs creating or binding the socket. - * @since Android 1.0 + * @since 1.4 */ public MulticastSocket(SocketAddress localAddr) throws IOException { super(localAddr); @@ -601,12 +585,12 @@ public class MulticastSocket extends DatagramSocket { /** * Gets the state of the {@code SocketOptions.IP_MULTICAST_LOOP}. - * + * * @return {@code true} if the IP multicast loop is enabled, {@code false} * otherwise. * @throws SocketException * if the socket is closed or the option is invalid. - * @since Android 1.0 + * @since 1.4 */ public boolean getLoopbackMode() throws SocketException { checkClosedAndBind(false); @@ -616,13 +600,13 @@ public class MulticastSocket extends DatagramSocket { /** * Sets the {@code SocketOptions.IP_MULTICAST_LOOP}. - * + * * @param loop * the value for the socket option socket {@code * SocketOptions.IP_MULTICAST_LOOP}. * @throws SocketException * if the socket is closed or the option is invalid. - * @since Android 1.0 + * @since 1.4 */ public void setLoopbackMode(boolean loop) throws SocketException { checkClosedAndBind(false); diff --git a/luni/src/main/java/java/net/NegCacheElement.java b/luni/src/main/java/java/net/NegCacheElement.java index 7285a14..e166db4 100644 --- a/luni/src/main/java/java/net/NegCacheElement.java +++ b/luni/src/main/java/java/net/NegCacheElement.java @@ -18,28 +18,27 @@ package java.net; /** * This class is used to hold information about failed host name lookups. - * + * * @see NegativeCache - * @since Android 1.0 */ class NegCacheElement { // we need the time to figure out when the entry is stale // BEGIN android-changed final long nanoTimeAdded = System.nanoTime(); + // END android-changed // holds the name of the host for which the lookup failed final String hostName; - + /** * Constructor used to set the hostname for the entry for which the lookup * failed. - * + * * @param hostName * name of the host for which the lookup failed. */ NegCacheElement(String hostName) { this.hostName = hostName; } - // END android-changed } diff --git a/luni/src/main/java/java/net/NegativeCache.java b/luni/src/main/java/java/net/NegativeCache.java index 58078fc..e66d3f3 100644 --- a/luni/src/main/java/java/net/NegativeCache.java +++ b/luni/src/main/java/java/net/NegativeCache.java @@ -25,16 +25,13 @@ import org.apache.harmony.luni.util.PriviAction; /** * This class is used to maintain the negative name lookup cache, which caches * host names which could not be resolved, as a security feature. - * + * * @see NegCacheElement - * @since Android 1.0 */ class NegativeCache<K, V> extends LinkedHashMap<K, V> { private static final long serialVersionUID = 1L; - // BEGIN android-changed - // Copied from a newer version of harmony private static NegativeCache<String, NegCacheElement> negCache; // maximum number of entries in the cache @@ -42,13 +39,17 @@ class NegativeCache<K, V> extends LinkedHashMap<K, V> { // the loading for the cache private static final float LOADING = 0.75F; - // END android-changed /** - * Returns the hostname for the cache element. - * - * @return hostName name of the host for which the lookup failed. - * @since Android 1.0 + * Constructs a negative cache for name lookups. + * + * @param initialCapacity + * the initial size of the cache. + * @param loadFactor + * the load factor of the backing map. + * @param accessOrder + * if {@code true} indicates that traversal order should begin + * with most recently accessed element. */ NegativeCache(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor, accessOrder); @@ -59,10 +60,9 @@ class NegativeCache<K, V> extends LinkedHashMap<K, V> { * size has grown beyond the maximum size allowed for the cache. A {@code * LinkedHashMap} is created such that the least recently used entry is * deleted. - * + * * @param eldest * the map entry which will be deleted if we return {@code true}. - * @since Android 1.0 */ @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { @@ -72,17 +72,13 @@ class NegativeCache<K, V> extends LinkedHashMap<K, V> { /** * Adds the host name and the corresponding name lookup fail message to the * cache. - * + * * @param hostName * the name of the host for which the lookup failed. * @param failedMessage * the message returned when the lookup fails. - * @since Android 1.0 */ static synchronized void put(String hostName, String failedMessage) { - // BEGIN android-note - // Made synchronized. copied from a newer version of harmony - // END android-note checkCacheExists(); negCache.put(hostName, new NegCacheElement(failedMessage)); } @@ -90,17 +86,13 @@ class NegativeCache<K, V> extends LinkedHashMap<K, V> { /** * Returns the message of the negative cache if the entry has not yet * expired. - * + * * @param hostName * the name of the host for which we look up the entry. * @return the message which was returned when the host lookup failed if the * entry has not yet expired. - * @since Android 1.0 */ static synchronized String getFailedMessage(String hostName) { - // BEGIN android-note - // Made synchronized. copied from a newer version of harmony - // END android-note checkCacheExists(); NegCacheElement element = negCache.get(hostName); if (element != null) { @@ -130,10 +122,7 @@ class NegativeCache<K, V> extends LinkedHashMap<K, V> { } } if (element != null) { - // BEGIN android-changed - // Copied from a newer version of harmony return element.hostName; - // END android-changed } return null; } @@ -148,13 +137,9 @@ class NegativeCache<K, V> extends LinkedHashMap<K, V> { // END android-added /** - * This method checks whether the cache was already created and if not - * creates it. + * This method checks if we have created the cache and if not creates it */ static synchronized void checkCacheExists() { - // BEGIN android-note - // Made synchronized. copied from a newer version of harmony - // END android-note if (negCache == null) { /* * Create with the access order set so ordering is based on when the diff --git a/luni/src/main/java/java/net/NetPermission.java b/luni/src/main/java/java/net/NetPermission.java index e7cca8b..bac9d89 100644 --- a/luni/src/main/java/java/net/NetPermission.java +++ b/luni/src/main/java/java/net/NetPermission.java @@ -31,11 +31,9 @@ package java.net; * <dd>Allows a stream (protocol) handler to be set when constructing an URL * object</dd> * </dl> - * </p> * * @see java.security.BasicPermission * @see SecurityManager - * @since Android 1.0 */ public final class NetPermission extends java.security.BasicPermission { @@ -46,7 +44,6 @@ public final class NetPermission extends java.security.BasicPermission { * * @param name * the name of the new NetPermission instance. - * @since Android 1.0 */ public NetPermission(String name) { super(name); @@ -60,7 +57,6 @@ public final class NetPermission extends java.security.BasicPermission { * the name of the new {@code NetPermission} instance. * @param actions * the ignored action string. - * @since Android 1.0 */ public NetPermission(String name, String actions) { super(name, actions); diff --git a/luni/src/main/java/java/net/NetworkInterface.java b/luni/src/main/java/java/net/NetworkInterface.java index 68452e6b..091eb9f 100644 --- a/luni/src/main/java/java/net/NetworkInterface.java +++ b/luni/src/main/java/java/net/NetworkInterface.java @@ -28,8 +28,6 @@ import org.apache.harmony.luni.util.Msg; * interface is defined by its address and a platform dependent name. The class * provides methods to get all information about the available interfaces of the * system or to identify the local interface of a joined multicast group. - * - * @since Android 1.0 */ public final class NetworkInterface extends Object { @@ -115,7 +113,6 @@ public final class NetworkInterface extends Object { * Gets the name associated with this network interface. * * @return the name of this {@code NetworkInterface} instance. - * @since Android 1.0 */ public String getName() { return name; @@ -125,7 +122,6 @@ public final class NetworkInterface extends Object { * Gets a list of addresses bound to this network interface. * * @return the address list of the represented network interface. - * @since Android 1.0 */ public Enumeration<InetAddress> getInetAddresses() { /* @@ -192,7 +188,6 @@ public final class NetworkInterface extends Object { * * @return the display name of this network interface or the name if the * display name is not available. - * @since Android 1.0 */ public String getDisplayName() { /* @@ -217,7 +212,6 @@ public final class NetworkInterface extends Object { * information. * @throws NullPointerException * if the given interface's name is {@code null}. - * @since Android 1.0 */ public static NetworkInterface getByName(String interfaceName) throws SocketException { @@ -244,7 +238,7 @@ public final class NetworkInterface extends Object { /** * Gets the specific network interface according to the given address. - * + * * @param address * the address to identify the searched network interface. * @return the network interface with the specified address if one exists or @@ -254,7 +248,6 @@ public final class NetworkInterface extends Object { * information. * @throws NullPointerException * if the given interface address is invalid. - * @since Android 1.0 */ public static NetworkInterface getByInetAddress(InetAddress address) throws SocketException { @@ -302,7 +295,6 @@ public final class NetworkInterface extends Object { * @throws SocketException * if an error occurs while getting the network interface * information. - * @since Android 1.0 */ public static Enumeration<NetworkInterface> getNetworkInterfaces() throws SocketException { @@ -343,7 +335,6 @@ public final class NetworkInterface extends Object { * @return {@code true} if the specified object is equal to this {@code * NetworkInterface}, {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object obj) { @@ -412,7 +403,6 @@ public final class NetworkInterface extends Object { * generated using this name. * * @return the hashcode value for this {@code NetworkInterface} instance. - * @since Android 1.0 */ @Override public int hashCode() { @@ -427,7 +417,6 @@ public final class NetworkInterface extends Object { * network interface. * * @return the textual representation for this network interface. - * @since Android 1.0 */ @Override public String toString() { diff --git a/luni/src/main/java/java/net/NoRouteToHostException.java b/luni/src/main/java/java/net/NoRouteToHostException.java index 042ccd4..f2e2c36 100644 --- a/luni/src/main/java/java/net/NoRouteToHostException.java +++ b/luni/src/main/java/java/net/NoRouteToHostException.java @@ -21,8 +21,6 @@ package java.net; * The {@code NoRouteToHostException} will be thrown while attempting to connect * to a remote host but the host cannot be reached for instance because of a * badly configured router or a blocking firewall. - * - * @since Android 1.0 */ public class NoRouteToHostException extends SocketException { @@ -30,8 +28,6 @@ public class NoRouteToHostException extends SocketException { /** * Constructs a new instance of this exception with its walkback filled in. - * - * @since Android 1.0 */ public NoRouteToHostException() { super(); @@ -43,7 +39,6 @@ public class NoRouteToHostException extends SocketException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public NoRouteToHostException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/PasswordAuthentication.java b/luni/src/main/java/java/net/PasswordAuthentication.java index 324f878..735810d 100644 --- a/luni/src/main/java/java/net/PasswordAuthentication.java +++ b/luni/src/main/java/java/net/PasswordAuthentication.java @@ -20,9 +20,8 @@ package java.net; /** * This immutable class is a data structure that encapsulates username and * password which is used by the {@code Authenticator} class. - * + * * @see Authenticator - * @since Android 1.0 */ public final class PasswordAuthentication { @@ -38,7 +37,6 @@ public final class PasswordAuthentication { * the username to store. * @param password * the associated password to store. - * @since Android 1.0 */ public PasswordAuthentication(String userName, char[] password) { this.userName = userName; @@ -51,7 +49,6 @@ public final class PasswordAuthentication { * longer needed. * * @return the copied password. - * @since Android 1.0 */ public char[] getPassword() { return password.clone(); @@ -61,7 +58,6 @@ public final class PasswordAuthentication { * Gets the username stored by this instance. * * @return the stored username. - * @since Android 1.0 */ public String getUserName() { return userName; diff --git a/luni/src/main/java/java/net/PortUnreachableException.java b/luni/src/main/java/java/net/PortUnreachableException.java index 973a978..2b5b25b 100644 --- a/luni/src/main/java/java/net/PortUnreachableException.java +++ b/luni/src/main/java/java/net/PortUnreachableException.java @@ -27,8 +27,6 @@ public class PortUnreachableException extends SocketException { /** * Constructs a new instance of this class with its walkback filled in. - * - * @since Android 1.0 */ public PortUnreachableException() { } @@ -39,7 +37,6 @@ public class PortUnreachableException extends SocketException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public PortUnreachableException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/ProtocolException.java b/luni/src/main/java/java/net/ProtocolException.java index f32dedc..ebbdc44 100644 --- a/luni/src/main/java/java/net/ProtocolException.java +++ b/luni/src/main/java/java/net/ProtocolException.java @@ -21,8 +21,6 @@ package java.net; * Signals that either a connection attempt to a socket of the wrong type, the * application of an unsupported operation or that a general error in the * underlying protocol has occurred. - * - * @since Android 1.0 */ public class ProtocolException extends java.io.IOException { @@ -30,8 +28,6 @@ public class ProtocolException extends java.io.IOException { /** * Constructs a new instance of this class with its walkback filled in. - * - * @since Android 1.0 */ public ProtocolException() { super(); @@ -43,7 +39,6 @@ public class ProtocolException extends java.io.IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public ProtocolException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/Proxy.java b/luni/src/main/java/java/net/Proxy.java index df0383d..3442339 100644 --- a/luni/src/main/java/java/net/Proxy.java +++ b/luni/src/main/java/java/net/Proxy.java @@ -25,8 +25,6 @@ import org.apache.harmony.luni.util.Msg; * <li>DIRECT</li> * <li>HTTP</li> * <li>SOCKS</li></ul - * - * @since Android 1.0 */ public class Proxy { @@ -34,8 +32,6 @@ public class Proxy { * Represents the proxy type setting {@code Proxy.Type.DIRECT}. It tells * protocol handlers that there is no proxy to be used. The address is set * to {@code null}. - * - * @since Android 1.0 */ public static final Proxy NO_PROXY = new Proxy(); @@ -58,7 +54,6 @@ public class Proxy { * if the parameter {@code type} is set to {@code * Proxy.Type.DIRECT} or the value for {@code SocketAddress} is * {@code null}. - * @since Android 1.0 */ public Proxy(Proxy.Type type, SocketAddress sa) { /* @@ -86,7 +81,6 @@ public class Proxy { * Gets the type of this {@code Proxy} instance. * * @return the stored proxy type. - * @since Android 1.0 */ public Proxy.Type type() { return type; @@ -97,7 +91,6 @@ public class Proxy { * * @return the stored proxy address or {@code null} if the proxy type is * {@code DIRECT}. - * @since Android 1.0 */ public SocketAddress address() { return address; @@ -107,9 +100,8 @@ public class Proxy { * Gets a textual representation of this {@code Proxy} instance. The string * includes the two parts {@code type.toString()} and {@code * address.toString()} if {@code address} is not {@code null}. - * + * * @return the representing string of this proxy. - * @since Android 1.0 */ @Override public String toString() { @@ -131,7 +123,6 @@ public class Proxy { * @return {@code true} if the given object represents the same {@code * Proxy} as this instance, {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public final boolean equals(Object obj) { @@ -150,7 +141,6 @@ public class Proxy { * Gets the hashcode for this {@code Proxy} instance. * * @return the hashcode value for this Proxy instance. - * @since Android 1.0 */ @Override public final int hashCode() { @@ -165,8 +155,6 @@ public class Proxy { /** * {@code Enum} class for the proxy type. Possible options are {@code * DIRECT}, {@code HTTP} and {@code SOCKS}. - * - * @since Android 1.0 */ public enum Type { /** diff --git a/luni/src/main/java/java/net/ProxySelector.java b/luni/src/main/java/java/net/ProxySelector.java index aad4bcc..334ea1e 100644 --- a/luni/src/main/java/java/net/ProxySelector.java +++ b/luni/src/main/java/java/net/ProxySelector.java @@ -24,8 +24,6 @@ import java.util.List; * can be set as default by calling the {@code setDefault()} method. If a * connection can't be established, the caller should notify the proxy selector * by invoking the {@code connectFailed()} method. - * - * @since Android 1.0 */ public abstract class ProxySelector { @@ -47,8 +45,6 @@ public abstract class ProxySelector { /** * Creates a new {@code ProxySelector} instance. - * - * @since Android 1.0 */ public ProxySelector() { super(); @@ -61,7 +57,6 @@ public abstract class ProxySelector { * @throws SecurityException * if a security manager is installed but it doesn't have the * NetPermission("getProxySelector"). - * @since Android 1.0 */ public static ProxySelector getDefault() { SecurityManager sm = System.getSecurityManager(); @@ -83,7 +78,6 @@ public abstract class ProxySelector { * @throws SecurityException * if a security manager is installed but it doesn't have the * NetPermission("setProxySelector"). - * @since Android 1.0 */ public static void setDefault(ProxySelector selector) { SecurityManager sm = System.getSecurityManager(); @@ -101,14 +95,14 @@ public abstract class ProxySelector { * <li>https URI stands for https connection.</li> * <li>ftp URI stands for ftp connection.</li> * <li>socket:://ip:port URI stands for tcp client sockets connection.</li> - * </p> - * + * * @param uri * the target URI object. * @return a list containing all applicable proxies. If no proxy is * available, the list contains only the {@code Proxy.NO_PROXY} * element. - * @since Android 1.0 + * @throws IllegalArgumentException + * if {@code uri} is {@code null}. */ public abstract List<Proxy> select(URI uri); @@ -125,8 +119,9 @@ public abstract class ProxySelector { * @param ioe * the exception which was thrown during connection * establishment. + * @throws IllegalArgumentException + * if any argument is {@code null}. * @see #select(URI) - * @since Android 1.0 */ public abstract void connectFailed(URI uri, SocketAddress sa, IOException ioe); diff --git a/luni/src/main/java/java/net/ProxySelectorImpl.java b/luni/src/main/java/java/net/ProxySelectorImpl.java index 79ce0cf..fa8d049 100644 --- a/luni/src/main/java/java/net/ProxySelectorImpl.java +++ b/luni/src/main/java/java/net/ProxySelectorImpl.java @@ -30,9 +30,8 @@ import org.apache.harmony.luni.util.PriviAction; /** * Default implementation for {@code ProxySelector}. - * - * @since Android 1.0 */ +@SuppressWarnings("unchecked") class ProxySelectorImpl extends ProxySelector { private static final int HTTP_PROXY_PORT = 80; @@ -239,7 +238,7 @@ class ProxySelectorImpl extends ProxySelector { */ private boolean isNonProxyHost(String host, String nonProxyHosts) { // nonProxyHosts is not set - if (null == nonProxyHosts) { + if (null == host || null == nonProxyHosts) { return false; } // Construct regex expression of nonProxyHosts diff --git a/luni/src/main/java/java/net/ResponseCache.java b/luni/src/main/java/java/net/ResponseCache.java index e7a0aca..427b63d 100644 --- a/luni/src/main/java/java/net/ResponseCache.java +++ b/luni/src/main/java/java/net/ResponseCache.java @@ -28,24 +28,20 @@ import java.util.Map; * getDefault()}. If {@code URLConnection#useCaches} is set, {@code * URLConnection} class will use {@code ResponseCache} to store and get * resources. - * </p> * <p> * Whether the resource is cached depends on the implementation of {@code * ResponseCache}. If so, a {@code CacheResponse} is returned from which the * stream handler reads. If the stream handler fails to get a resource from the * cache, it must get the resource from its original location. - * </p> * <p> * To write to the cache, the protocol handlers call {@code put()}, upon which a * {@code CacheRequest} is supplied to which the resources are written. - * </p> - * + * * @see #put(URI, URLConnection) * @see CacheRequest * @see CacheResponse * @see URLConnection * @see URLStreamHandler - * @since Android 1.0 */ public abstract class ResponseCache { @@ -92,8 +88,6 @@ public abstract class ResponseCache { /** * Creates a new instance of this class. - * - * @since Android 1.0 */ public ResponseCache() { super(); @@ -106,7 +100,6 @@ public abstract class ResponseCache { * @throws SecurityException * if a security manager is installed but it doesn't have the * {@code NetPermission("getResponseCache")}. - * @since Android 1.0 */ public static ResponseCache getDefault() { checkGetResponseCachePermission(); @@ -126,7 +119,6 @@ public abstract class ResponseCache { * @throws SecurityException * if a security manager is installed but it doesn't have the * {@code NetPermission("setResponseCache")}. - * @since Android 1.0 */ public static void setDefault(ResponseCache responseCache) { checkSetResponseCachePermission(); @@ -149,7 +141,6 @@ public abstract class ResponseCache { * if an I/O error occurs while getting the cached data. * @throws IllegalArgumentException * if any one of the parameters is set to {@code null}. - * @since Android 1.0 */ public abstract CacheResponse get(URI uri, String rqstMethod, Map<String, List<String>> rqstHeaders) throws IOException; @@ -171,7 +162,6 @@ public abstract class ResponseCache { * if an I/O error occurs while adding the resource. * @throws IllegalArgumentException * if any one of the parameters is set to {@code null}. - * @since Android 1.0 */ public abstract CacheRequest put(URI uri, URLConnection conn) throws IOException; diff --git a/luni/src/main/java/java/net/SecureCacheResponse.java b/luni/src/main/java/java/net/SecureCacheResponse.java index fff6b82..0031b3a 100644 --- a/luni/src/main/java/java/net/SecureCacheResponse.java +++ b/luni/src/main/java/java/net/SecureCacheResponse.java @@ -27,14 +27,11 @@ import javax.net.ssl.SSLPeerUnverifiedException; * protocol like TLS or SSL. * * @see ResponseCache - * @since Android 1.0 */ public abstract class SecureCacheResponse extends CacheResponse { /** * Creates a new instance of this class. - * - * @since Android 1.0 */ public SecureCacheResponse() { super(); @@ -45,7 +42,6 @@ public abstract class SecureCacheResponse extends CacheResponse { * to retrieve the network resource. * * @return the cipher suite string. - * @since Android 1.0 */ public abstract String getCipherSuite(); @@ -57,7 +53,6 @@ public abstract class SecureCacheResponse extends CacheResponse { * * @return the certificate chain that was sent to the server. If no * certificate chain was sent, the method returns {@code null}. - * @since Android 1.0 */ public abstract List<Certificate> getLocalCertificateChain(); @@ -71,7 +66,6 @@ public abstract class SecureCacheResponse extends CacheResponse { * @return the server's certificate chain. * @throws SSLPeerUnverifiedException * if the peer is unverified. - * @since Android 1.0 */ public abstract List<Certificate> getServerCertificateChain() throws SSLPeerUnverifiedException; @@ -84,7 +78,6 @@ public abstract class SecureCacheResponse extends CacheResponse { * @return a principal object representing the server's principal. * @throws SSLPeerUnverifiedException * if the peer is unverified. - * @since Android 1.0 */ public abstract Principal getPeerPrincipal() throws SSLPeerUnverifiedException; @@ -97,7 +90,6 @@ public abstract class SecureCacheResponse extends CacheResponse { * @return the local principal object being sent to the server. Returns an * {@code X500Principal} object for X509-based cipher suites. If no * principal was sent, it returns {@code null}. - * @since Android 1.0 */ public abstract Principal getLocalPrincipal(); } diff --git a/luni/src/main/java/java/net/ServerSocket.java b/luni/src/main/java/java/net/ServerSocket.java index 5f7e079..fc3ad10 100644 --- a/luni/src/main/java/java/net/ServerSocket.java +++ b/luni/src/main/java/java/net/ServerSocket.java @@ -20,9 +20,8 @@ package java.net; import java.io.IOException; import java.nio.channels.ServerSocketChannel; -import org.apache.harmony.luni.net.SocketImplProvider; +import org.apache.harmony.luni.net.PlainServerSocketImpl; import org.apache.harmony.luni.platform.Platform; - import org.apache.harmony.luni.util.Msg; /** @@ -30,8 +29,6 @@ import org.apache.harmony.luni.util.Msg; * connections. A {@code ServerSocket} handles the requests and sends back an * appropriate reply. The actual tasks that a server socket must accomplish are * implemented by an internal {@code SocketImpl} instance. - * - * @since Android 1.0 */ public class ServerSocket { @@ -44,7 +41,7 @@ public class ServerSocket { private boolean isBound; private boolean isClosed; - + static { Platform.getNetworkSystem().oneTimeInitialization(true); } @@ -52,14 +49,13 @@ public class ServerSocket { /** * Constructs a new {@code ServerSocket} instance which is not bound to any * port. The default number of pending connections may be backlogged. - * + * * @throws IOException * if an error occurs while creating the server socket. - * @since Android 1.0 */ public ServerSocket() throws IOException { impl = factory != null ? factory.createSocketImpl() - : SocketImplProvider.getServerSocketImpl(); + : new PlainServerSocketImpl(); } /** @@ -81,12 +77,11 @@ public class ServerSocket { * Constructs a new {@code ServerSocket} instance bound to the nominated * port on the localhost. The default number of pending connections may be * backlogged. If {@code aport} is 0 a free port is assigned to the socket. - * + * * @param aport * the port number to listen for connection requests on. * @throws IOException * if an error occurs while creating the server socket. - * @since Android 1.0 */ public ServerSocket(int aport) throws IOException { this(aport, defaultBacklog(), InetAddress.ANY); @@ -97,7 +92,7 @@ public class ServerSocket { * port on the localhost. The number of pending connections that may be * backlogged is specified by {@code backlog}. If {@code aport} is 0 a free * port is assigned to the socket. - * + * * @param aport * the port number to listen for connection requests on. * @param backlog @@ -105,7 +100,6 @@ public class ServerSocket { * will be rejected. * @throws IOException * if an error occurs while creating the server socket. - * @since Android 1.0 */ public ServerSocket(int aport, int backlog) throws IOException { this(aport, backlog, InetAddress.ANY); @@ -116,7 +110,7 @@ public class ServerSocket { * local host address and port. The number of pending connections that may * be backlogged is specified by {@code backlog}. If {@code aport} is 0 a * free port is assigned to the socket. - * + * * @param aport * the port number to listen for connection requests on. * @param localAddr @@ -126,14 +120,13 @@ public class ServerSocket { * will be rejected. * @throws IOException * if an error occurs while creating the server socket. - * @since Android 1.0 */ public ServerSocket(int aport, int backlog, InetAddress localAddr) throws IOException { super(); checkListen(aport); impl = factory != null ? factory.createSocketImpl() - : SocketImplProvider.getServerSocketImpl(); + : new PlainServerSocketImpl(); InetAddress addr = localAddr == null ? InetAddress.ANY : localAddr; synchronized (this) { @@ -154,11 +147,10 @@ public class ServerSocket { * Waits for an incoming request and blocks until the connection is opened. * This method returns a socket object representing the just opened * connection. - * + * * @return the connection representing socket. * @throws IOException * if an error occurs while accepting a new connection. - * @since Android 1.0 */ public Socket accept() throws IOException { checkClosedAndCreate(false); @@ -190,10 +182,9 @@ public class ServerSocket { * Checks whether the server may listen for connection requests on {@code * aport}. Throws an exception if the port is outside the valid range * {@code 0 <= aport <= 65535 }or does not satisfy the security policy. - * + * * @param aPort * the candidate port to listen on. - * @since Android 1.0 */ void checkListen(int aPort) { if (aPort < 0 || aPort > 65535) { @@ -208,10 +199,9 @@ public class ServerSocket { /** * Closes this server socket and its implementation. Any attempt to connect * to this socket thereafter will fail. - * + * * @throws IOException * if an error occurs while closing this socket. - * @since Android 1.0 */ public void close() throws IOException { isClosed = true; @@ -222,7 +212,7 @@ public class ServerSocket { * Answer the default number of pending connections on a server socket. If * the backlog value maximum is reached, any subsequent incoming request is * rejected. - * + * * @return int the default number of pending connection requests */ static int defaultBacklog() { @@ -232,9 +222,8 @@ public class ServerSocket { /** * Gets the local IP address of this server socket or {@code null} if the * socket is unbound. This is useful for multihomed hosts. - * + * * @return the local address of this server socket. - * @since Android 1.0 */ public InetAddress getInetAddress() { if (!isBound()) { @@ -246,9 +235,8 @@ public class ServerSocket { /** * Gets the local port of this server socket or {@code -1} if the socket is * unbound. - * + * * @return the local port this server is listening on. - * @since Android 1.0 */ public int getLocalPort() { if (!isBound()) { @@ -260,11 +248,10 @@ public class ServerSocket { /** * Gets the timeout period of this server socket. This is the time the * server will wait listening for accepted connections before exiting. - * + * * @return the listening timeout value of this server socket. * @throws IOException * if the option cannot be retrieved. - * @since Android 1.0 */ public synchronized int getSoTimeout() throws IOException { if (!isCreated) { @@ -287,13 +274,12 @@ public class ServerSocket { /** * Invokes the server socket implementation to accept a connection on the * given socket {@code aSocket}. - * + * * @param aSocket * the concrete {@code SocketImpl} to accept the connection * request on. * @throws IOException * if the connection cannot be accepted. - * @since Android 1.0 */ protected final void implAccept(Socket aSocket) throws IOException { impl.accept(aSocket.impl); @@ -304,13 +290,12 @@ public class ServerSocket { * Sets the server socket implementation factory of this instance. This * method may only be invoked with sufficient security privilege and only * once during the application lifetime. - * + * * @param aFactory * the streaming socket factory to be used for further socket * instantiations. * @throws IOException * if the factory could not be set or is already set. - * @since Android 1.0 */ public static synchronized void setSocketFactory(SocketImplFactory aFactory) throws IOException { @@ -328,12 +313,11 @@ public class ServerSocket { * Sets the timeout period of this server socket. This is the time the * server will wait listening for accepted connections before exiting. This * value must be a positive number. - * + * * @param timeout * the listening timeout value of this server socket. * @throws SocketException * if an error occurs while setting the option. - * @since Android 1.0 */ public synchronized void setSoTimeout(int timeout) throws SocketException { checkClosedAndCreate(true); @@ -347,9 +331,8 @@ public class ServerSocket { * Returns a textual representation of this server socket including the * address, port and the state. The port field is set to {@code 0} if there * is no connection to the server socket. - * + * * @return the textual socket representation. - * @since Android 1.0 */ @Override public String toString() { @@ -371,7 +354,7 @@ public class ServerSocket { * number of pending connections may be backlogged. If the {@code localAddr} * is set to {@code null} the socket will be bound to an available local * address on any free port of the system. - * + * * @param localAddr * the local address and port to bind on. * @throws IllegalArgumentException @@ -379,7 +362,6 @@ public class ServerSocket { * @throws IOException * if the socket is already bound or a problem occurs during * binding. - * @since Android 1.0 */ public void bind(SocketAddress localAddr) throws IOException { bind(localAddr, defaultBacklog()); @@ -391,7 +373,7 @@ public class ServerSocket { * available local address on any free port of the system. The value for * {@code backlog} must e greater than {@code 0} otherwise the default value * will be used. - * + * * @param localAddr * the local machine address and port to bind on. * @param backlog @@ -402,7 +384,6 @@ public class ServerSocket { * @throws IOException * if the socket is already bound or a problem occurs during * binding. - * @since Android 1.0 */ public void bind(SocketAddress localAddr, int backlog) throws IOException { checkClosedAndCreate(true); @@ -443,9 +424,8 @@ public class ServerSocket { /** * Gets the local socket address of this server socket or {@code null} if * the socket is unbound. This is useful on multihomed hosts. - * + * * @return the local socket address and port this socket is bound to. - * @since Android 1.0 */ public SocketAddress getLocalSocketAddress() { if (!isBound()) { @@ -457,9 +437,8 @@ public class ServerSocket { /** * Returns whether this server socket is bound to a local address and port * or not. - * + * * @return {@code true} if this socket is bound, {@code false} otherwise. - * @since Android 1.0 */ public boolean isBound() { return isBound; @@ -467,9 +446,8 @@ public class ServerSocket { /** * Returns whether this server socket is closed or not. - * + * * @return {@code true} if this socket is closed, {@code false} otherwise. - * @since Android 1.0 */ public boolean isClosed() { return isClosed; @@ -504,12 +482,11 @@ public class ServerSocket { /** * Sets the value for the socket option {@code SocketOptions.SO_REUSEADDR}. - * + * * @param reuse * the socket option setting. * @throws SocketException * if an error occurs while setting the option value. - * @since Android 1.0 */ public void setReuseAddress(boolean reuse) throws SocketException { checkClosedAndCreate(true); @@ -519,11 +496,10 @@ public class ServerSocket { /** * Gets the value of the socket option {@code SocketOptions.SO_REUSEADDR}. - * + * * @return {@code true} if the option is enabled, {@code false} otherwise. * @throws SocketException * if an error occurs while reading the option value. - * @since Android 1.0 */ public boolean getReuseAddress() throws SocketException { checkClosedAndCreate(true); @@ -534,13 +510,12 @@ public class ServerSocket { /** * Sets the server socket receive buffer size {@code * SocketOptions.SO_RCVBUF}. - * + * * @param size * the buffer size in bytes. * @throws SocketException * if an error occurs while setting the size or the size is * invalid. - * @since Android 1.0 */ public void setReceiveBufferSize(int size) throws SocketException { checkClosedAndCreate(true); @@ -553,11 +528,10 @@ public class ServerSocket { /** * Gets the value for the receive buffer size socket option {@code * SocketOptions.SO_RCVBUF}. - * + * * @return the receive buffer size of this socket. * @throws SocketException * if an error occurs while reading the option value. - * @since Android 1.0 */ public int getReceiveBufferSize() throws SocketException { checkClosedAndCreate(true); @@ -568,9 +542,8 @@ public class ServerSocket { * Gets the related channel if this instance was created by a * {@code ServerSocketChannel}. The current implementation returns always {@code * null}. - * + * * @return the related {@code ServerSocketChannel} if any. - * @since Android 1.0 */ public ServerSocketChannel getChannel() { return null; @@ -580,8 +553,7 @@ public class ServerSocket { * Sets performance preferences for connection time, latency and bandwidth. * <p> * This method does currently nothing. - * </p> - * + * * @param connectionTime * the value representing the importance of a short connecting * time. @@ -589,7 +561,6 @@ public class ServerSocket { * the value representing the importance of low latency. * @param bandwidth * the value representing the importance of high bandwidth. - * @since Android 1.0 */ public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { diff --git a/luni/src/main/java/java/net/Socket.java b/luni/src/main/java/java/net/Socket.java index b29b965..97bfc2e 100644 --- a/luni/src/main/java/java/net/Socket.java +++ b/luni/src/main/java/java/net/Socket.java @@ -24,15 +24,13 @@ import java.nio.channels.SocketChannel; import java.security.AccessController; import org.apache.harmony.luni.net.NetUtil; -import org.apache.harmony.luni.net.SocketImplProvider; +import org.apache.harmony.luni.net.PlainSocketImpl; import org.apache.harmony.luni.platform.Platform; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; /** * Provides a client-side TCP socket. - * - * @since Android 1.0 */ public class Socket { @@ -66,7 +64,7 @@ public class Socket { static final int TCP_NODELAY = 4; static final int FLAG_SHUTDOWN = 8; - + static { Platform.getNetworkSystem().oneTimeInitialization(true); } @@ -75,14 +73,13 @@ public class Socket { * Creates a new unconnected socket. When a SocketImplFactory is defined it * creates the internal socket implementation, otherwise the default socket * implementation will be used for this socket. - * + * * @see SocketImplFactory * @see SocketImpl - * @since Android 1.0 */ public Socket() { impl = factory != null ? factory.createSocketImpl() - : SocketImplProvider.getSocketImpl(); + : new PlainSocketImpl(); } /** @@ -95,8 +92,7 @@ public class Socket { * proxy server: <br> * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new * InetSocketAddress("test.domain.org", 2130)));} - * </p> - * + * * @param proxy * the specified proxy for this socket. * @throws IllegalArgumentException @@ -107,7 +103,6 @@ public class Socket { * connect to the given proxy. * @see SocketImplFactory * @see SocketImpl - * @since Android 1.0 */ public Socket(Proxy proxy) { if (null == proxy || Proxy.Type.HTTP == proxy.type()) { @@ -127,7 +122,7 @@ public class Socket { checkConnectPermission(host, port); } impl = factory != null ? factory.createSocketImpl() - : SocketImplProvider.getSocketImpl(proxy); + : new PlainSocketImpl(proxy); this.proxy = proxy; } @@ -135,7 +130,7 @@ public class Socket { * Creates a new streaming socket connected to the target host specified by * the parameters {@code dstName} and {@code dstPort}. The socket is bound * to any available port on the local host. - * + * * @param dstName * the target host name or IP address to connect to. * @param dstPort @@ -147,7 +142,6 @@ public class Socket { * @throws SecurityException * if a security manager exists and it denies the permission to * connect to the given address and port. - * @since Android 1.0 */ public Socket(String dstName, int dstPort) throws UnknownHostException, IOException { @@ -162,9 +156,9 @@ public class Socket { * the parameters {@code dstName} and {@code dstPort}. On the local endpoint * the socket is bound to the given address {@code localAddress} on port * {@code localPort}. - * + * * If {@code host} is {@code null} a loopback address is used to connect to. - * + * * @param dstName * the target host name or IP address to connect to. * @param dstPort @@ -180,7 +174,6 @@ public class Socket { * @throws SecurityException * if a security manager exists and it denies the permission to * connect to the given address and port. - * @since Android 1.0 */ public Socket(String dstName, int dstPort, InetAddress localAddress, int localPort) throws IOException { @@ -194,7 +187,7 @@ public class Socket { * Creates a new streaming or datagram socket connected to the target host * specified by the parameters {@code hostName} and {@code port}. The socket * is bound to any available port on the local host. - * + * * @param hostName * the target host name or IP address to connect to. * @param port @@ -212,7 +205,6 @@ public class Socket { * @deprecated Use {@code Socket(String, int)} instead of this for streaming * sockets or an appropriate constructor of {@code * DatagramSocket} for UDP transport. - * @since Android 1.0 */ @Deprecated public Socket(String hostName, int port, boolean streaming) @@ -227,7 +219,7 @@ public class Socket { * Creates a new streaming socket connected to the target host specified by * the parameters {@code dstAddress} and {@code dstPort}. The socket is * bound to any available port on the local host. - * + * * @param dstAddress * the target host address to connect to. * @param dstPort @@ -237,7 +229,6 @@ public class Socket { * @throws SecurityException * if a security manager exists and it denies the permission to * connect to the given address and port. - * @since Android 1.0 */ public Socket(InetAddress dstAddress, int dstPort) throws IOException { this(); @@ -250,7 +241,7 @@ public class Socket { * the parameters {@code dstAddress} and {@code dstPort}. On the local * endpoint the socket is bound to the given address {@code localAddress} on * port {@code localPort}. - * + * * @param dstAddress * the target host address to connect to. * @param dstPort @@ -264,7 +255,6 @@ public class Socket { * @throws SecurityException * if a security manager exists and it denies the permission to * connect to the given address and port. - * @since Android 1.0 */ public Socket(InetAddress dstAddress, int dstPort, InetAddress localAddress, int localPort) throws IOException { @@ -277,7 +267,7 @@ public class Socket { * Creates a new streaming or datagram socket connected to the target host * specified by the parameters {@code addr} and {@code port}. The socket is * bound to any available port on the local host. - * + * * @param addr * the Internet address to connect to. * @param port @@ -293,7 +283,6 @@ public class Socket { * @deprecated Use {@code Socket(InetAddress, int)} instead of this for * streaming sockets or an appropriate constructor of {@code * DatagramSocket} for UDP transport. - * @since Android 1.0 */ @Deprecated public Socket(InetAddress addr, int port, boolean streaming) @@ -305,12 +294,11 @@ public class Socket { /** * Creates an unconnected socket with the given socket implementation. - * + * * @param anImpl * the socket implementation to be used. * @throws SocketException * if an error occurs while creating the socket. - * @since Android 1.0 */ protected Socket(SocketImpl anImpl) throws SocketException { impl = anImpl; @@ -319,7 +307,7 @@ public class Socket { /** * Checks whether the connection destination satisfies the security policy * and the validity of the port range. - * + * * @param destAddr * the destination host address. * @param dstPort @@ -336,7 +324,7 @@ public class Socket { /** * Checks whether the connection destination satisfies the security policy. - * + * * @param hostname * the destination hostname. * @param dstPort @@ -352,10 +340,9 @@ public class Socket { /** * Closes the socket. It is not possible to reconnect or rebind to this * socket thereafter which means a new socket instance has to be created. - * + * * @throws IOException * if an error occurs while closing the socket. - * @since Android 1.0 */ public synchronized void close() throws IOException { isClosed = true; @@ -364,10 +351,9 @@ public class Socket { /** * Gets the IP address of the target host this socket is connected to. - * + * * @return the IP address of the connected target host or {@code null} if * this socket is not yet connected. - * @since Android 1.0 */ public InetAddress getInetAddress() { if (!isConnected()) { @@ -378,12 +364,11 @@ public class Socket { /** * Gets an input stream to read data from this socket. - * + * * @return the byte-oriented input stream. * @throws IOException * if an error occurs while creating the input stream or the * socket is in an invalid state. - * @since Android 1.0 */ public InputStream getInputStream() throws IOException { checkClosedAndCreate(false); @@ -395,13 +380,12 @@ public class Socket { /** * Gets the setting of the socket option {@code SocketOptions.SO_KEEPALIVE}. - * + * * @return {@code true} if the {@code SocketOptions.SO_KEEPALIVE} is * enabled, {@code false} otherwise. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#SO_KEEPALIVE - * @since Android 1.0 */ public boolean getKeepAlive() throws SocketException { checkClosedAndCreate(true); @@ -411,10 +395,9 @@ public class Socket { /** * Gets the local IP address this socket is bound to. - * + * * @return the local IP address of this socket or {@code InetAddress.ANY} if * the socket is unbound. - * @since Android 1.0 */ public InetAddress getLocalAddress() { if (!isBound()) { @@ -426,10 +409,9 @@ public class Socket { /** * Gets the local port this socket is bound to. - * + * * @return the local port of this socket or {@code -1} if the socket is * unbound. - * @since Android 1.0 */ public int getLocalPort() { if (!isBound()) { @@ -440,12 +422,11 @@ public class Socket { /** * Gets an output stream to write data into this socket. - * + * * @return the byte-oriented output stream. * @throws IOException * if an error occurs while creating the output stream or the * socket is in an invalid state. - * @since Android 1.0 */ public OutputStream getOutputStream() throws IOException { checkClosedAndCreate(false); @@ -457,10 +438,9 @@ public class Socket { /** * Gets the port number of the target host this socket is connected to. - * + * * @return the port number of the connected target host or {@code 0} if this * socket is not yet connected. - * @since Android 1.0 */ public int getPort() { if (!isConnected()) { @@ -471,13 +451,12 @@ public class Socket { /** * Gets the value of the socket option {@code SocketOptions.SO_LINGER}. - * + * * @return the current value of the option {@code SocketOptions.SO_LINGER} * or {@code -1} if this option is disabled. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#SO_LINGER - * @since Android 1.0 */ public int getSoLinger() throws SocketException { checkClosedAndCreate(true); @@ -486,12 +465,11 @@ public class Socket { /** * Gets the receive buffer size of this socket. - * + * * @return the current value of the option {@code SocketOptions.SO_RCVBUF}. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#SO_RCVBUF - * @since Android 1.0 */ public synchronized int getReceiveBufferSize() throws SocketException { checkClosedAndCreate(true); @@ -500,12 +478,11 @@ public class Socket { /** * Gets the send buffer size of this socket. - * + * * @return the current value of the option {@code SocketOptions.SO_SNDBUF}. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#SO_SNDBUF - * @since Android 1.0 */ public synchronized int getSendBufferSize() throws SocketException { checkClosedAndCreate(true); @@ -515,13 +492,12 @@ public class Socket { /** * Gets the timeout for this socket during which a reading operation shall * block while waiting for data. - * + * * @return the current value of the option {@code SocketOptions.SO_TIMEOUT} * or {@code 0} which represents an infinite timeout. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#SO_TIMEOUT - * @since Android 1.0 */ public synchronized int getSoTimeout() throws SocketException { checkClosedAndCreate(true); @@ -530,13 +506,12 @@ public class Socket { /** * Gets the setting of the socket option {@code SocketOptions.TCP_NODELAY}. - * + * * @return {@code true} if the {@code SocketOptions.TCP_NODELAY} is enabled, * {@code false} otherwise. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#TCP_NODELAY - * @since Android 1.0 */ public boolean getTcpNoDelay() throws SocketException { checkClosedAndCreate(true); @@ -546,13 +521,12 @@ public class Socket { /** * Sets the state of the {@code SocketOptions.SO_KEEPALIVE} for this socket. - * + * * @param value * the state whether this option is enabled or not. * @throws SocketException * if an error occurs while setting the option. * @see SocketOptions#SO_KEEPALIVE - * @since Android 1.0 */ public void setKeepAlive(boolean value) throws SocketException { if (impl != null) { @@ -565,12 +539,11 @@ public class Socket { /** * Sets the internal factory for creating socket implementations. This may * only be executed once during the lifetime of the application. - * + * * @param fac * the socket implementation factory to be set. * @throws IOException * if the factory has been already set. - * @since Android 1.0 */ public static synchronized void setSocketImplFactory(SocketImplFactory fac) throws IOException { @@ -586,7 +559,7 @@ public class Socket { /** * Sets the send buffer size of this socket. - * + * * @param size * the buffer size in bytes. This value must be a positive number * greater than {@code 0}. @@ -594,7 +567,6 @@ public class Socket { * if an error occurs while setting the size or the given value * is an invalid size. * @see SocketOptions#SO_SNDBUF - * @since Android 1.0 */ public synchronized void setSendBufferSize(int size) throws SocketException { checkClosedAndCreate(true); @@ -606,7 +578,7 @@ public class Socket { /** * Sets the receive buffer size of this socket. - * + * * @param size * the buffer size in bytes. This value must be a positive number * greater than {@code 0}. @@ -614,7 +586,6 @@ public class Socket { * if an error occurs while setting the size or the given value * is an invalid size. * @see SocketOptions#SO_RCVBUF - * @since Android 1.0 */ public synchronized void setReceiveBufferSize(int size) throws SocketException { @@ -629,7 +600,7 @@ public class Socket { * Sets the state of the {@code SocketOptions.SO_LINGER} with the given * timeout in seconds. The timeout value for this option is silently limited * to the maximum of {@code 65535}. - * + * * @param on * the state whether this option is enabled or not. * @param timeout @@ -637,7 +608,6 @@ public class Socket { * @throws SocketException * if an error occurs while setting the option. * @see SocketOptions#SO_LINGER - * @since Android 1.0 */ public void setSoLinger(boolean on, int timeout) throws SocketException { checkClosedAndCreate(true); @@ -665,14 +635,13 @@ public class Socket { * operation will block indefinitely if this option value is set to {@code * 0}. The timeout must be set before calling the read operation. A * {@code SocketTimeoutException} is thrown when this timeout expires. - * + * * @param timeout * the reading timeout value as number greater than {@code 0} or * {@code 0} for an infinite timeout. * @throws SocketException * if an error occurs while setting the option. * @see SocketOptions#SO_TIMEOUT - * @since Android 1.0 */ public synchronized void setSoTimeout(int timeout) throws SocketException { checkClosedAndCreate(true); @@ -684,13 +653,12 @@ public class Socket { /** * Sets the state of the {@code SocketOptions.TCP_NODELAY} for this socket. - * + * * @param on * the state whether this option is enabled or not. * @throws SocketException * if an error occurs while setting the option. * @see SocketOptions#TCP_NODELAY - * @since Android 1.0 */ public void setTcpNoDelay(boolean on) throws SocketException { checkClosedAndCreate(true); @@ -700,7 +668,7 @@ public class Socket { /** * Creates a stream socket, binds it to the nominated local address/port, * then connects it to the nominated destination address/port. - * + * * @param dstAddress * the destination host address. * @param dstPort @@ -743,9 +711,8 @@ public class Socket { /** * Returns a {@code String} containing a concise, human-readable description of the * socket. - * + * * @return the textual representation of this socket. - * @since Android 1.0 */ @Override public String toString() { @@ -759,12 +726,11 @@ public class Socket { * Closes the input stream of this socket. Any further data sent to this * socket will be discarded. Reading from this socket after this method has * been called will return the value {@code EOF}. - * + * * @throws IOException * if an error occurs while closing the socket input stream. * @throws SocketException * if the input stream is already closed. - * @since Android 1.0 */ public void shutdownInput() throws IOException { if (isInputShutdown()) { @@ -779,12 +745,11 @@ public class Socket { * Closes the output stream of this socket. All buffered data will be sent * followed by the termination sequence. Writing to the closed output stream * will cause an {@code IOException}. - * + * * @throws IOException * if an error occurs while closing the socket output stream. * @throws SocketException * if the output stream is already closed. - * @since Android 1.0 */ public void shutdownOutput() throws IOException { if (isOutputShutdown()) { @@ -798,7 +763,7 @@ public class Socket { /** * Checks whether the socket is closed, and throws an exception. Otherwise * creates the underlying SocketImpl. - * + * * @throws SocketException * if the socket is closed. */ @@ -840,9 +805,8 @@ public class Socket { * Gets the local address and port of this socket as a SocketAddress or * {@code null} if the socket is unbound. This is useful on multihomed * hosts. - * + * * @return the bound local socket address and port. - * @since Android 1.0 */ public SocketAddress getLocalSocketAddress() { if (!isBound()) { @@ -854,9 +818,8 @@ public class Socket { /** * Gets the remote address and port of this socket as a {@code * SocketAddress} or {@code null} if the socket is not connected. - * + * * @return the remote socket address and port. - * @since Android 1.0 */ public SocketAddress getRemoteSocketAddress() { if (!isConnected()) { @@ -867,10 +830,9 @@ public class Socket { /** * Returns whether this socket is bound to a local address and port. - * + * * @return {@code true} if the socket is bound to a local address, {@code * false} otherwise. - * @since Android 1.0 */ public boolean isBound() { return isBound; @@ -878,9 +840,8 @@ public class Socket { /** * Returns whether this socket is connected to a remote host. - * + * * @return {@code true} if the socket is connected, {@code false} otherwise. - * @since Android 1.0 */ public boolean isConnected() { return isConnected; @@ -888,9 +849,8 @@ public class Socket { /** * Returns whether this socket is closed. - * + * * @return {@code true} if the socket is closed, {@code false} otherwise. - * @since Android 1.0 */ public boolean isClosed() { return isClosed; @@ -901,7 +861,7 @@ public class Socket { * the SocketAddress {@code localAddr}. If {@code localAddr} is set to * {@code null}, this socket will be bound to an available local address on * any free port. - * + * * @param localAddr * the specific address and port on the local machine to bind to. * @throws IllegalArgumentException @@ -909,7 +869,6 @@ public class Socket { * @throws IOException * if the socket is already bound or an error occurs while * binding. - * @since Android 1.0 */ public void bind(SocketAddress localAddr) throws IOException { checkClosedAndCreate(true); @@ -946,7 +905,7 @@ public class Socket { /** * Connects this socket to the given remote host address and port specified * by the SocketAddress {@code remoteAddr}. - * + * * @param remoteAddr * the address and port of the remote host to connect to. * @throws IllegalArgumentException @@ -954,7 +913,6 @@ public class Socket { * @throws IOException * if the socket is already connected or an error occurs while * connecting. - * @since Android 1.0 */ public void connect(SocketAddress remoteAddr) throws IOException { connect(remoteAddr, 0); @@ -965,7 +923,7 @@ public class Socket { * by the SocketAddress {@code remoteAddr} with the specified timeout. The * connecting method will block until the connection is established or an * error occurred. - * + * * @param remoteAddr * the address and port of the remote host to connect to. * @param timeout @@ -977,7 +935,6 @@ public class Socket { * @throws IOException * if the socket is already connected or an error occurs while * connecting. - * @since Android 1.0 */ public void connect(SocketAddress remoteAddr, int timeout) throws IOException { @@ -1028,22 +985,20 @@ public class Socket { /** * Returns whether the incoming channel of the socket has already been * closed. - * + * * @return {@code true} if reading from this socket is not possible anymore, * {@code false} otherwise. - * @since Android 1.0 */ public boolean isInputShutdown() { return isInputShutdown; } /** - * Returns whether the outgoing channel of the socket has already been + * Returns whether the outgoing channel of the socket has already been * closed. - * + * * @return {@code true} if writing to this socket is not possible anymore, * {@code false} otherwise. - * @since Android 1.0 */ public boolean isOutputShutdown() { return isOutputShutdown; @@ -1051,13 +1006,12 @@ public class Socket { /** * Sets the state of the {@code SocketOptions.SO_REUSEADDR} for this socket. - * + * * @param reuse * the state whether this option is enabled or not. * @throws SocketException * if an error occurs while setting the option. * @see SocketOptions#SO_REUSEADDR - * @since Android 1.0 */ public void setReuseAddress(boolean reuse) throws SocketException { checkClosedAndCreate(true); @@ -1067,13 +1021,12 @@ public class Socket { /** * Gets the setting of the socket option {@code SocketOptions.SO_REUSEADDR}. - * + * * @return {@code true} if the {@code SocketOptions.SO_REUSEADDR} is * enabled, {@code false} otherwise. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#SO_REUSEADDR - * @since Android 1.0 */ public boolean getReuseAddress() throws SocketException { checkClosedAndCreate(true); @@ -1085,13 +1038,12 @@ public class Socket { * Sets the state of the {@code SocketOptions.SO_OOBINLINE} for this socket. * When this option is enabled urgent data can be received in-line with * normal data. - * + * * @param oobinline * whether this option is enabled or not. * @throws SocketException * if an error occurs while setting the option. * @see SocketOptions#SO_OOBINLINE - * @since Android 1.0 */ public void setOOBInline(boolean oobinline) throws SocketException { checkClosedAndCreate(true); @@ -1101,13 +1053,12 @@ public class Socket { /** * Gets the setting of the socket option {@code SocketOptions.SO_OOBINLINE}. - * + * * @return {@code true} if the {@code SocketOptions.SO_OOBINLINE} is * enabled, {@code false} otherwise. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#SO_OOBINLINE - * @since Android 1.0 */ public boolean getOOBInline() throws SocketException { checkClosedAndCreate(true); @@ -1119,14 +1070,13 @@ public class Socket { * Sets the value of the {@code SocketOptions.IP_TOS} for this socket. See * the specification RFC 1349 for more information about the type of service * field. - * + * * @param value * the value to be set for this option with a valid range of * {@code 0-255}. * @throws SocketException * if an error occurs while setting the option. * @see SocketOptions#IP_TOS - * @since Android 1.0 */ public void setTrafficClass(int value) throws SocketException { checkClosedAndCreate(true); @@ -1138,12 +1088,11 @@ public class Socket { /** * Gets the value of the socket option {@code SocketOptions.IP_TOS}. - * + * * @return the value which represents the type of service. * @throws SocketException * if an error occurs while reading the socket option. * @see SocketOptions#IP_TOS - * @since Android 1.0 */ public int getTrafficClass() throws SocketException { checkClosedAndCreate(true); @@ -1153,12 +1102,11 @@ public class Socket { /** * Sends the given single byte data which is represented by the lowest octet * of {@code value} as "TCP urgent data". - * + * * @param value * the byte of urgent data to be sent. * @throws IOException * if an error occurs while sending urgent data. - * @since Android 1.0 */ public void sendUrgentData(int value) throws IOException { if (!impl.supportsUrgentData()) { @@ -1170,7 +1118,7 @@ public class Socket { /** * Set the appropriate flags for a socket created by {@code * ServerSocket.accept()}. - * + * * @see ServerSocket#implAccept */ void accepted() { @@ -1186,9 +1134,8 @@ public class Socket { /** * Gets the SocketChannel of this socket, if one is available. The current * implementation of this method returns always {@code null}. - * + * * @return the related SocketChannel or {@code null} if no channel exists. - * @since Android 1.0 */ public SocketChannel getChannel() { return null; @@ -1198,8 +1145,7 @@ public class Socket { * Sets performance preferences for connectionTime, latency and bandwidth. * <p> * This method does currently nothing. - * </p> - * + * * @param connectionTime * the value representing the importance of a short connecting * time. @@ -1207,7 +1153,6 @@ public class Socket { * the value representing the importance of low latency. * @param bandwidth * the value representing the importance of high bandwidth. - * @since Android 1.0 */ public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { diff --git a/luni/src/main/java/java/net/SocketAddress.java b/luni/src/main/java/java/net/SocketAddress.java index 756b5fd..32a4c36 100644 --- a/luni/src/main/java/java/net/SocketAddress.java +++ b/luni/src/main/java/java/net/SocketAddress.java @@ -23,15 +23,11 @@ import java.io.Serializable; * This abstract class represents a protocol-independent base for * socket-endpoint representing classes. The class has to be implemented * according to a specific protocol. - * - * @since Android 1.0 */ public abstract class SocketAddress implements Serializable { /** * Creates a new {@code SocketAddress} instance. - * - * @since Android 1.0 */ public SocketAddress() { super(); diff --git a/luni/src/main/java/java/net/SocketException.java b/luni/src/main/java/java/net/SocketException.java index b9b3a14..23d3744 100644 --- a/luni/src/main/java/java/net/SocketException.java +++ b/luni/src/main/java/java/net/SocketException.java @@ -22,8 +22,6 @@ import java.io.IOException; /** * This {@code SocketException} may be thrown during socket creation or setting * options, and is the superclass of all other socket related exceptions. - * - * @since Android 1.0 */ public class SocketException extends IOException { @@ -32,8 +30,6 @@ public class SocketException extends IOException { /** * Constructs a new {@code SocketException} instance with its walkback * filled in. - * - * @since Android 1.0 */ public SocketException() { super(); @@ -45,7 +41,6 @@ public class SocketException extends IOException { * * @param detailMessage * the detail message of this exception. - * @since Android 1.0 */ public SocketException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/SocketImpl.java b/luni/src/main/java/java/net/SocketImpl.java index f011e63..be13eca 100644 --- a/luni/src/main/java/java/net/SocketImpl.java +++ b/luni/src/main/java/java/net/SocketImpl.java @@ -20,7 +20,6 @@ package java.net; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; -import java.io.InterruptedIOException; import java.io.OutputStream; import org.apache.harmony.luni.platform.INetworkSystem; @@ -35,36 +34,26 @@ import org.apache.harmony.luni.util.Msg; * ServerSocket} on a well known port (referred to as listener) used to * establish a connection and the resulting {@code Socket} (referred to as * host). - * - * @since Android 1.0 */ public abstract class SocketImpl implements SocketOptions { /** * The remote address this socket is connected to. - * - * @since Android 1.0 */ protected InetAddress address; /** * The remote port this socket is connected to. - * - * @since Android 1.0 */ protected int port; /** * The file descriptor of this socket. - * - * @since Android 1.0 */ protected FileDescriptor fd; /** * The local port this socket is connected to. - * - * @since Android 1.0 */ protected int localport; @@ -80,9 +69,8 @@ public abstract class SocketImpl implements SocketOptions { /** * Creates a new connection-oriented socket implementation. - * + * * @see SocketImplFactory - * @since Android 1.0 */ public SocketImpl() { this.netImpl = Platform.getNetworkSystem(); @@ -91,73 +79,67 @@ public abstract class SocketImpl implements SocketOptions { /** * Waits for an incoming request and blocks until the connection is opened * on the given socket. - * + * * @param newSocket * the socket to accept connections on. * @throws IOException * if an error occurs while accepting a new connection. - * @since Android 1.0 */ protected abstract void accept(SocketImpl newSocket) throws IOException; /** * Returns the available number of bytes which are readable from this socket * without blocking. - * + * * @return the number of bytes that may be read without blocking. * @throws IOException * if an error occurs while reading the number of bytes. - * @since Android 1.0 */ protected abstract int available() throws IOException; /** * Binds this socket to the specified local host address and port number. - * + * * @param address * the local machine address to bind this socket to. * @param port * the port on the local machine to bind this socket to. * @throws IOException * if an error occurs while binding this socket. - * @since Android 1.0 */ protected abstract void bind(InetAddress address, int port) throws IOException; /** * Closes this socket. This makes later access invalid. - * + * * @throws IOException * if an error occurs while closing this socket. - * @since Android 1.0 */ protected abstract void close() throws IOException; /** * Connects this socket to the specified remote host and port number. - * + * * @param host * the remote host this socket has to be connected to. * @param port * the remote port on which this socket has to be connected. * @throws IOException * if an error occurs while connecting to the remote host. - * @since Android 1.0 */ protected abstract void connect(String host, int port) throws IOException; /** * Connects this socket to the specified remote host address and port * number. - * + * * @param address * the remote host address this socket has to be connected to. * @param port * the remote port on which this socket has to be connected. * @throws IOException * if an error occurs while connecting to the remote host. - * @since Android 1.0 */ protected abstract void connect(InetAddress address, int port) throws IOException; @@ -165,21 +147,19 @@ public abstract class SocketImpl implements SocketOptions { /** * Creates a new unconnected socket. The argument {@code isStreaming} * defines whether the new socket is a streaming or a datagram socket. - * + * * @param isStreaming * defines whether the type of the new socket is streaming or * datagram. * @throws IOException * if an error occurs while creating the socket. - * @since Android 1.0 */ protected abstract void create(boolean isStreaming) throws IOException; /** * Gets the file descriptor of this socket. - * + * * @return the file descriptor of this socket. - * @since Android 1.0 */ protected FileDescriptor getFileDescriptor() { return fd; @@ -187,9 +167,8 @@ public abstract class SocketImpl implements SocketOptions { /** * Gets the remote address this socket is connected to. - * + * * @return the remote address of this socket. - * @since Android 1.0 */ protected InetAddress getInetAddress() { return address; @@ -197,11 +176,10 @@ public abstract class SocketImpl implements SocketOptions { /** * Gets the input stream of this socket. - * + * * @return the input stream of this socket. * @throws IOException * if an error occurs while accessing the input stream. - * @since Android 1.0 */ protected abstract InputStream getInputStream() throws IOException; @@ -209,9 +187,8 @@ public abstract class SocketImpl implements SocketOptions { * Gets the local port number of this socket. The field is initialized to * {@code -1} and upon demand will go to the IP stack to get the bound * value. See the class comment for the context of the local port. - * + * * @return the local port number this socket is bound to. - * @since Android 1.0 */ protected int getLocalPort() { return localport; @@ -219,32 +196,29 @@ public abstract class SocketImpl implements SocketOptions { /** * Gets the value of the given socket option. - * + * * @param optID * the socket option to retrieve. * @return the option value. * @throws SocketException * if an error occurs while accessing the option. - * @since Android 1.0 */ public abstract Object getOption(int optID) throws SocketException; /** * Gets the output stream of this socket. - * + * * @return the output stream of this socket. * @throws IOException * if an error occurs while accessing the output stream. - * @since Android 1.0 */ protected abstract OutputStream getOutputStream() throws IOException; /** * Gets the remote port number of this socket. This value is not meaningful * when this instance is wrapped by a {@code ServerSocket}. - * + * * @return the remote port this socket is connected to. - * @since Android 1.0 */ protected int getPort() { return port; @@ -255,60 +229,23 @@ public abstract class SocketImpl implements SocketOptions { * connection requests are queued up to the limit specified by {@code * backlog}. Additional requests are rejected. The method {@code listen()} * may only be invoked on streaming sockets. - * + * * @param backlog * the maximum number of outstanding connection requests. * @throws IOException * if an error occurs while listening. - * @since Android 1.0 */ protected abstract void listen(int backlog) throws IOException; /** - * In the IP stack, read at most {@code count} bytes off the socket - * into the {@code buffer}, at the {@code offset}. If the timeout - * is zero, block indefinitely waiting for data, otherwise wait the - * specified period (in milliseconds). - * - * @param buffer - * the buffer to read into - * @param offset - * the offset into the buffer - * @param count - * the max number of bytes to read - * @return int the actual number of bytes read - * @exception IOException - * thrown if an error occurs while reading - */ - int read(byte[] buffer, int offset, int count) throws IOException { - if (shutdownInput) { - return -1; - } - try { - // BEGIN android-added - int receiveTimeout = (Integer)getOption(SocketOptions.SO_TIMEOUT); - // END android-added - int read = this.netImpl.receiveStream(fd, buffer, offset, count, - receiveTimeout); - if (read == -1) { - shutdownInput = true; - } - return read; - } catch (InterruptedIOException e) { - throw new SocketTimeoutException(e.getMessage()); - } - } - - /** * Sets the value for the specified socket option. - * + * * @param optID * the socket option to be set. * @param val * the option value. * @throws SocketException * if an error occurs while setting the option. - * @since Android 1.0 */ public abstract void setOption(int optID, Object val) throws SocketException; @@ -316,9 +253,8 @@ public abstract class SocketImpl implements SocketOptions { /** * Returns a string containing a concise, human-readable description of the * socket. - * + * * @return the textual representation of this socket. - * @since Android 1.0 */ @SuppressWarnings("nls") @Override @@ -331,7 +267,7 @@ public abstract class SocketImpl implements SocketOptions { /** * In the IP stack, write at most {@code count} bytes on the socket * from the {@code buffer}, from the {@code offset}. - * + * * @param buffer * the buffer to read into * @param offset @@ -339,18 +275,15 @@ public abstract class SocketImpl implements SocketOptions { * @param count * the number of bytes to write * @return int the actual number of bytes written - * @exception IOException + * @throws IOException * thrown if an error occurs while writing */ int write(byte[] buffer, int offset, int count) throws IOException { if (!streaming) { - // BEGIN android-changed - // copied from newer harmony version - return this.netImpl - .sendDatagram2(fd, buffer, offset, count, port, address); - // END android-changed + return this.netImpl.sendDatagram2(fd, buffer, offset, count, port, + address); } - return this.netImpl.sendStream(fd, buffer, offset, count); + return this.netImpl.write(fd, buffer, offset, count); } /** @@ -358,11 +291,9 @@ public abstract class SocketImpl implements SocketOptions { * <p> * This default implementation always throws an {@link IOException} to * indicate that the subclass should have overridden this method. - * </p> - * + * * @throws IOException * always because this method should be overridden. - * @since Android 1.0 */ protected void shutdownInput() throws IOException { // KA025=Method has not been implemented @@ -374,11 +305,9 @@ public abstract class SocketImpl implements SocketOptions { * <p> * This default implementation always throws an {@link IOException} to * indicate that the subclass should have overridden this method. - * </p> - * + * * @throws IOException * always because this method should be overridden. - * @since Android 1.0 */ protected void shutdownOutput() throws IOException { // KA025=Method has not been implemented @@ -389,14 +318,13 @@ public abstract class SocketImpl implements SocketOptions { * Connects this socket to the remote host address and port number specified * by the {@code SocketAddress} object with the given timeout. This method * will block indefinitely if the timeout is set to zero. - * + * * @param remoteAddr * the remote host address and port number to connect to. * @param timeout * the timeout value in milliseconds. * @throws IOException * if an error occurs while connecting. - * @since Android 1.0 */ protected abstract void connect(SocketAddress remoteAddr, int timeout) throws IOException; @@ -404,9 +332,8 @@ public abstract class SocketImpl implements SocketOptions { /** * Returns whether the socket supports urgent data or not. Subclasses should * override this method. - * + * * @return {@code false} because subclasses must override this method. - * @since Android 1.0 */ protected boolean supportsUrgentData() { return false; @@ -414,26 +341,24 @@ public abstract class SocketImpl implements SocketOptions { /** * Sends the single byte of urgent data on the socket. - * + * * @param value * the byte of urgent data. * @throws IOException * if an error occurs sending urgent data. - * @since Android 1.0 */ protected abstract void sendUrgentData(int value) throws IOException; /** * Sets performance preference for connection time, latency and bandwidth. * Does nothing by default. - * + * * @param connectionTime * the importance of connect time. * @param latency * the importance of latency. * @param bandwidth * the importance of bandwidth. - * @since Android 1.0 */ protected void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { diff --git a/luni/src/main/java/java/net/SocketImplFactory.java b/luni/src/main/java/java/net/SocketImplFactory.java index 3cc42b0..57b0bc3 100644 --- a/luni/src/main/java/java/net/SocketImplFactory.java +++ b/luni/src/main/java/java/net/SocketImplFactory.java @@ -19,16 +19,13 @@ package java.net; /** * This interface defines a factory for socket implementations. - * - * @since Android 1.0 */ public interface SocketImplFactory { - + /** * Creates a new {@code SocketImpl} instance. * * @return the created {@code SocketImpl} instance. - * @since Android 1.0 */ SocketImpl createSocketImpl(); } diff --git a/luni/src/main/java/java/net/SocketOptions.java b/luni/src/main/java/java/net/SocketOptions.java index 6e1753f..38c9301 100644 --- a/luni/src/main/java/java/net/SocketOptions.java +++ b/luni/src/main/java/java/net/SocketOptions.java @@ -25,7 +25,6 @@ package java.net; * * @see SocketImpl * @see DatagramSocketImpl - * @since Android 1.0 */ public interface SocketOptions { @@ -38,8 +37,6 @@ public interface SocketOptions { * during this timeout the socket is closed normally otherwise forcefully. * Valid values for this option are in the range {@code 0 <= SO_LINGER <= * 65535}. - * - * @since Android 1.0 */ public static final int SO_LINGER = 128; @@ -47,8 +44,6 @@ public interface SocketOptions { * Timeout for blocking operations. The argument value is specified in * milliseconds. An {@code InterruptedIOException} is thrown if this timeout * expires. - * - * @since Android 1.0 */ public static final int SO_TIMEOUT = 4102; @@ -57,8 +52,6 @@ public interface SocketOptions { * a side-effect though, this could lead to a low packet efficiency. The * socket implementation uses the Nagle's algorithm to try to reach a higher * packet efficiency if this option is disabled. - * - * @since Android 1.0 */ public static final int TCP_NODELAY = 1; @@ -69,8 +62,6 @@ public interface SocketOptions { /** * This option specifies the interface which is used to send multicast * packets. It's only available on a {@code MulticastSocket}. - * - * @since Android 1.0 */ public static final int IP_MULTICAST_IF = 16; @@ -78,8 +69,6 @@ public interface SocketOptions { * This option can be used to set one specific interface on a multihomed * host on which incoming connections are accepted. It's only available on * server-side sockets. - * - * @since Android 1.0 */ public static final int SO_BINDADDR = 15; @@ -87,8 +76,6 @@ public interface SocketOptions { * This option specifies whether a reuse of a local address is allowed even * if an other socket is not yet removed by the operating system. It's only * available on a {@code MulticastSocket}. - * - * @since Android 1.0 */ public static final int SO_REUSEADDR = 4; @@ -96,15 +83,11 @@ public interface SocketOptions { /** * Buffer size of the outgoing channel. - * - * @since Android 1.0 */ public static final int SO_SNDBUF = 4097; /** * Buffer size of the incoming channel. - * - * @since Android 1.0 */ public static final int SO_RCVBUF = 4098; @@ -113,16 +96,12 @@ public interface SocketOptions { /** * This option specifies whether socket implementations can send keepalive * messages if no data has been sent for a longer time. - * - * @since Android 1.0 */ public static final int SO_KEEPALIVE = 8; /** * This option specifies the value for the Type-of-Service (TOS) field of * the IP header. - * - * @since Android 1.0 */ public static final int IP_TOS = 3; @@ -130,23 +109,17 @@ public interface SocketOptions { * This option specifies whether the local loopback of multicast packets is * enabled or disabled. This option is enabled by default on multicast * sockets. - * - * @since Android 1.0 */ public static final int IP_MULTICAST_LOOP = 18; /** * This option can be used to enable broadcasting on datagram sockets. - * - * @since Android 1.0 */ public static final int SO_BROADCAST = 32; /** * This option specifies whether sending TCP urgent data is supported on * this socket or not. - * - * @since Android 1.0 */ public static final int SO_OOBINLINE = 4099; @@ -155,8 +128,6 @@ public interface SocketOptions { * host on which incoming connections are accepted. It's only available on * server-side sockets. This option supports setting outgoing interfaces * with either IPv4 or IPv6 addresses. - * - * @since Android 1.0 */ public static final int IP_MULTICAST_IF2 = 31; @@ -168,7 +139,6 @@ public interface SocketOptions { * the option identifier. * @throws SocketException * if an error occurs reading the option value. - * @since Android 1.0 */ public Object getOption(int optID) throws SocketException; @@ -181,7 +151,6 @@ public interface SocketOptions { * the value to be set for the option. * @throws SocketException * if an error occurs setting the option value. - * @since Android 1.0 */ public void setOption(int optID, Object val) throws SocketException; } diff --git a/luni/src/main/java/java/net/SocketPermission.java b/luni/src/main/java/java/net/SocketPermission.java index 72d77e7..25cc43f 100644 --- a/luni/src/main/java/java/net/SocketPermission.java +++ b/luni/src/main/java/java/net/SocketPermission.java @@ -14,9 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// BEGIN andorid-note -// This class was copied from a newer version of harmony -// END andorid-note package java.net; @@ -57,16 +54,13 @@ import org.apache.harmony.luni.util.Msg; * <i>LOW-HIGH</i> where <i>LOW</i> and <i>HIGH</i> are valid port numbers. If * either <i>LOW</i> or <i>HIGH</i> is omitted it is equivalent to entering the * lowest or highest possible value respectively. For example: - * + * * <pre> * {@code SocketPermission("www.company.com:7000-", "connect,accept")} * </pre> - * + * * represents the permission to connect to and accept connections from {@code * www.company.com} on ports in the range {@code 7000} to {@code 65535}. - * </p> - * - * @since Android 1.0 */ public final class SocketPermission extends Permission implements Serializable { @@ -122,13 +116,11 @@ public final class SocketPermission extends Permission implements Serializable { * possible operations {@code "connect"}, {@code "listen"}, {@code "accept"} * , and {@code "resolve"}. They are case-insensitive and can be put * together in any order. {@code "resolve"} is implied per default. - * </p> - * + * * @param host * the hostname this permission is valid for. * @param action * the action string of this permission. - * @since Android 1.0 */ public SocketPermission(String host, String action) { super(host.equals("") ? "localhost" : host); //$NON-NLS-1$ //$NON-NLS-2$ @@ -149,14 +141,13 @@ public final class SocketPermission extends Permission implements Serializable { /** * Compares the argument {@code o} to this instance and returns {@code true} * if they represent the same permission using a class specific comparison. - * + * * @param o * the object to compare with this {@code SocketPermission} * instance. * @return {@code true} if they represent the same permission, {@code false} * otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object o) { @@ -187,10 +178,9 @@ public final class SocketPermission extends Permission implements Serializable { * Returns the hash value for this {@code SocketPermission} instance. Any * two objects which returns {@code true} when passed to {@code equals()} * must return the same value as a result of this method. - * + * * @return the hashcode value for this instance. * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -201,9 +191,8 @@ public final class SocketPermission extends Permission implements Serializable { * Gets a comma-separated list of all actions allowed by this permission. If * more than one action is returned they follow this order: {@code connect}, * {@code listen}, {@code accept}, {@code resolve}. - * + * * @return the comma-separated action list. - * @since Android 1.0 */ @Override public String getActions() { @@ -212,7 +201,7 @@ public final class SocketPermission extends Permission implements Serializable { /** * Stores the actions for this permission as a bit field. - * + * * @param actions * java.lang.String the action list */ @@ -255,13 +244,12 @@ public final class SocketPermission extends Permission implements Serializable { * permission actions, hosts and ports must be implied by this permission * instance in order to return {@code true}. This permission may imply * additional actions not present in the argument permission. - * + * * @param p * the socket permission which has to be implied by this * instance. * @return {@code true} if this permission instance implies all permissions * represented by {@code p}, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean implies(Permission p) { @@ -293,15 +281,14 @@ public final class SocketPermission extends Permission implements Serializable { /** * Creates a new {@code PermissionCollection} to store {@code * SocketPermission} objects. - * + * * @return the new permission collection. - * @since Android 1.0 */ @Override public PermissionCollection newPermissionCollection() { return new SocketPermissionCollection(); } - + /** * Parse the port, including the minPort, maxPort * @param hostPort the host[:port] one @@ -319,14 +306,14 @@ public final class SocketPermission extends Permission implements Serializable { portMax = 80; return; } - + if (":*".equals(port)) { // The port range should be 0-65535 portMin = 0; portMax = 65535; return; } - + // Omit ':' port = port.substring(1); int negIdx = port.indexOf('-'); @@ -349,21 +336,23 @@ public final class SocketPermission extends Permission implements Serializable { try { portMin = Integer.valueOf(strPortMin).intValue(); portMax = Integer.valueOf(strPortMax).intValue(); - + if (portMin > portMax) { - throw new IllegalArgumentException(Msg.getString("K0049") + " " + port); //$NON-NLS-1$ + // K0049=MinPort is greater than MaxPort\: {0} + throw new IllegalArgumentException(Msg.getString("K0049", port)); //$NON-NLS-1$ } } catch (NumberFormatException e) { - throw new IllegalArgumentException(Msg.getString("K004a") + " " + port); //$NON-NLS-1$ + // K004a=Invalid port number specified\: {0} + throw new IllegalArgumentException(Msg.getString("K004a", port)); //$NON-NLS-1$ } } /** * Creates a canonical action list. - * + * * @param action * java.lang.String - * + * * @return java.lang.String */ private String toCanonicalActionString(String action) { @@ -403,15 +392,20 @@ public final class SocketPermission extends Permission implements Serializable { } /** - * Get the host part from the host[:port] one. - * The host should be + * Get the host part from the host[:port] one. The host should be + * + * <pre> * host = (hostname | IPv4address | IPv6reference | IPv6 in full uncompressed form) - * The wildcard "*" may be included once in a DNS name host specification. If it is included, - * it must be in the leftmost position - * + * </pre> + * + * The wildcard "*" may be included once in a DNS name host specification. + * If it is included, it must be in the leftmost position + * * @param host - * @return - * @throws IllegalArgumentException if the host is invalid. + * the {@code host[:port]} string. + * @return the host name. + * @throws IllegalArgumentException + * if the host is invalid. */ private String getHostString(String host) throws IllegalArgumentException { host = host.trim(); @@ -431,7 +425,7 @@ public final class SocketPermission extends Permission implements Serializable { } int lastIdx = host.lastIndexOf(':'); - + if (idx == lastIdx) { if (-1 != idx) { // only one colon, should be port @@ -456,21 +450,22 @@ public final class SocketPermission extends Permission implements Serializable { if (Inet6Util.isIP6AddressInFullForm(host)) { return host.toLowerCase(); } - throw new IllegalArgumentException(Msg.getString("K004a") + " " - + host); + // K004a=Invalid port number specified\: {0} + throw new IllegalArgumentException(Msg.getString("K004a", host)); } // forward bracket found int bbracketIdx = host.indexOf(']'); if (-1 == bbracketIdx) { // no back bracket found, wrong - throw new IllegalArgumentException(Msg.getString("K004a") + " " - + host); + // K004a=Invalid port number specified\: {0} + throw new IllegalArgumentException(Msg.getString("K004a", host)); } host = host.substring(0, bbracketIdx + 1); if (Inet6Util.isValidIP6Address(host)) { return host.toLowerCase(); } - throw new IllegalArgumentException(Msg.getString("K004a") + " " + host); + // K004a=Invalid port number specified\: {0} + throw new IllegalArgumentException(Msg.getString("K004a", host)); } /** diff --git a/luni/src/main/java/java/net/SocketPermissionCollection.java b/luni/src/main/java/java/net/SocketPermissionCollection.java index 777f9a7..60bb831 100644 --- a/luni/src/main/java/java/net/SocketPermissionCollection.java +++ b/luni/src/main/java/java/net/SocketPermissionCollection.java @@ -26,8 +26,6 @@ import java.util.Vector; * This class represents a list of {@code SocketPermission} objects and provides * a method to check whether or not a specific permission is implied by this * {@code SocketPermissionCollection}. - * - * @since Android 1.0 */ final class SocketPermissionCollection extends PermissionCollection { @@ -62,8 +60,6 @@ final class SocketPermissionCollection extends PermissionCollection { * Returns whether this permission collection implies {@code permission}. * Basically it tests whether {@code permission} is the subset of this * collection. - * - * @since Android 1.0 */ @Override public boolean implies(Permission permission) { diff --git a/luni/src/main/java/java/net/SocketTimeoutException.java b/luni/src/main/java/java/net/SocketTimeoutException.java index 32ba183..c1c762e 100644 --- a/luni/src/main/java/java/net/SocketTimeoutException.java +++ b/luni/src/main/java/java/net/SocketTimeoutException.java @@ -22,8 +22,6 @@ import java.io.InterruptedIOException; /** * This exception is thrown when a timeout expired on a socket {@code read} or * {@code accept} operation. - * - * @since Android 1.0 */ public class SocketTimeoutException extends InterruptedIOException { @@ -32,8 +30,6 @@ public class SocketTimeoutException extends InterruptedIOException { /** * Creates a new {@code SocketTimeoutException} instance with its walkback * filled in. - * - * @since Android 1.0 */ public SocketTimeoutException() { super(); @@ -45,7 +41,6 @@ public class SocketTimeoutException extends InterruptedIOException { * * @param detailMessage * the detail message of this exception. - * @since Android 1.0 */ public SocketTimeoutException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/URI.java b/luni/src/main/java/java/net/URI.java index 4b1f4df..7fd08a5 100644 --- a/luni/src/main/java/java/net/URI.java +++ b/luni/src/main/java/java/net/URI.java @@ -28,8 +28,6 @@ import org.apache.harmony.luni.util.Msg; /** * This class represents an instance of a URI as defined by RFC 2396. - * - * @since Android 1.0 */ public final class URI implements Comparable<URI>, Serializable { @@ -78,13 +76,12 @@ public final class URI implements Comparable<URI>, Serializable { /** * Creates a new URI instance according to the given string {@code uri}. - * + * * @param uri * the textual URI representation to be parsed into a URI object. * @throws URISyntaxException * if the given string {@code uri} doesn't fit to the * specification RFC2396 or could not be parsed correctly. - * @since Android 1.0 */ public URI(String uri) throws URISyntaxException { new Helper().parseURI(uri, false); @@ -96,8 +93,7 @@ public final class URI implements Comparable<URI>, Serializable { * string will be parsed later on to create the URI instance. * <p> * {@code [scheme:]scheme-specific-part[#fragment]} - * </p> - * + * * @param scheme * the scheme part of the URI. * @param ssp @@ -107,7 +103,6 @@ public final class URI implements Comparable<URI>, Serializable { * @throws URISyntaxException * if the temporary created string doesn't fit to the * specification RFC2396 or could not be parsed correctly. - * @since Android 1.0 */ public URI(String scheme, String ssp, String frag) throws URISyntaxException { @@ -135,8 +130,7 @@ public final class URI implements Comparable<URI>, Serializable { * string will be parsed later on to create the URI instance. * <p> * {@code [scheme:][user-info@]host[:port][path][?query][#fragment]} - * </p> - * + * * @param scheme * the scheme part of the URI. * @param userinfo @@ -156,7 +150,6 @@ public final class URI implements Comparable<URI>, Serializable { * @throws URISyntaxException * if the temporary created string doesn't fit to the * specification RFC2396 or could not be parsed correctly. - * @since Android 1.0 */ public URI(String scheme, String userinfo, String host, int port, String path, String query, String fragment) @@ -230,8 +223,7 @@ public final class URI implements Comparable<URI>, Serializable { * string will be parsed later on to create the URI instance. * <p> * {@code [scheme:]host[path][#fragment]} - * </p> - * + * * @param scheme * the scheme part of the URI. * @param host @@ -243,7 +235,6 @@ public final class URI implements Comparable<URI>, Serializable { * @throws URISyntaxException * if the temporary created string doesn't fit to the * specification RFC2396 or could not be parsed correctly. - * @since Android 1.0 */ public URI(String scheme, String host, String path, String fragment) throws URISyntaxException { @@ -256,8 +247,7 @@ public final class URI implements Comparable<URI>, Serializable { * string will be parsed later on to create the URI instance. * <p> * {@code [scheme:][//authority][path][?query][#fragment]} - * </p> - * + * * @param scheme * the scheme part of the URI. * @param authority @@ -272,7 +262,6 @@ public final class URI implements Comparable<URI>, Serializable { * @throws URISyntaxException * if the temporary created string doesn't fit to the * specification RFC2396 or could not be parsed correctly. - * @since Android 1.0 */ public URI(String scheme, String authority, String path, String query, String fragment) throws URISyntaxException { @@ -718,7 +707,7 @@ public final class URI implements Comparable<URI>, Serializable { // case for a closed bracket at end of IP [x:x:x:...x] case ']': if (i != length - 1) { - return false; // must be last charcter + return false; // must be last character } if (ipAddress.charAt(0) != '[') { return false; // must have a open [ @@ -856,11 +845,10 @@ public final class URI implements Comparable<URI>, Serializable { * in the natural case-sensitive way. A hierarchical URI is less than an * opaque URI and if one part is {@code null} the URI with the undefined * part is less than the other one. - * + * * @param uri * the URI this instance has to compare with. * @return the value representing the order of the two instances. - * @since Android 1.0 */ public int compareTo(URI uri) { int ret = 0; @@ -969,11 +957,10 @@ public final class URI implements Comparable<URI>, Serializable { /** * Parses the given argument {@code uri} and creates an appropriate URI * instance. - * + * * @param uri * the string which has to be parsed to create the URI instance. * @return the created instance representing the given URI. - * @since Android 1.0 */ public static URI create(String uri) { URI result = null; @@ -1057,12 +1044,11 @@ public final class URI implements Comparable<URI>, Serializable { * Compares this URI instance with the given argument {@code o} and * determines if both are equal. Two URI instances are equal if all single * parts are identical in their meaning. - * + * * @param o * the URI this instance has to be compared with. * @return {@code true} if both URI instances point to the same resource, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object o) { @@ -1147,9 +1133,8 @@ public final class URI implements Comparable<URI>, Serializable { /** * Gets the decoded authority part of this URI. - * + * * @return the decoded authority part or {@code null} if undefined. - * @since Android 1.0 */ public String getAuthority() { return decode(authority); @@ -1159,7 +1144,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the decoded fragment part of this URI. * * @return the decoded fragment part or {@code null} if undefined. - * @since Android 1.0 */ public String getFragment() { return decode(fragment); @@ -1169,7 +1153,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the host part of this URI. * * @return the host part or {@code null} if undefined. - * @since Android 1.0 */ public String getHost() { return host; @@ -1179,7 +1162,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the decoded path part of this URI. * * @return the decoded path part or {@code null} if undefined. - * @since Android 1.0 */ public String getPath() { return decode(path); @@ -1189,7 +1171,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the port number of this URI. * * @return the port number or {@code -1} if undefined. - * @since Android 1.0 */ public int getPort() { return port; @@ -1199,7 +1180,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the decoded query part of this URI. * * @return the decoded query part or {@code null} if undefined. - * @since Android 1.0 */ public String getQuery() { return decode(query); @@ -1209,7 +1189,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the authority part of this URI in raw form. * * @return the encoded authority part or {@code null} if undefined. - * @since Android 1.0 */ public String getRawAuthority() { return authority; @@ -1219,7 +1198,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the fragment part of this URI in raw form. * * @return the encoded fragment part or {@code null} if undefined. - * @since Android 1.0 */ public String getRawFragment() { return fragment; @@ -1229,7 +1207,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the path part of this URI in raw form. * * @return the encoded path part or {@code null} if undefined. - * @since Android 1.0 */ public String getRawPath() { return path; @@ -1239,7 +1216,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the query part of this URI in raw form. * * @return the encoded query part or {@code null} if undefined. - * @since Android 1.0 */ public String getRawQuery() { return query; @@ -1249,17 +1225,15 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the scheme-specific part of this URI in raw form. * * @return the encoded scheme-specific part or {@code null} if undefined. - * @since Android 1.0 */ public String getRawSchemeSpecificPart() { return schemespecificpart; } - + /** * Gets the user-info part of this URI in raw form. * * @return the encoded user-info part or {@code null} if undefined. - * @since Android 1.0 */ public String getRawUserInfo() { return userinfo; @@ -1269,17 +1243,15 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the scheme part of this URI. * * @return the scheme part or {@code null} if undefined. - * @since Android 1.0 */ public String getScheme() { return scheme; } - + /** * Gets the decoded scheme-specific part of this URI. * * @return the decoded scheme-specific part or {@code null} if undefined. - * @since Android 1.0 */ public String getSchemeSpecificPart() { return decode(schemespecificpart); @@ -1289,7 +1261,6 @@ public final class URI implements Comparable<URI>, Serializable { * Gets the decoded user-info part of this URI. * * @return the decoded user-info part or {@code null} if undefined. - * @since Android 1.0 */ public String getUserInfo() { return decode(userinfo); @@ -1297,9 +1268,8 @@ public final class URI implements Comparable<URI>, Serializable { /** * Gets the hashcode value of this URI instance. - * + * * @return the appropriate hashcode value. - * @since Android 1.0 */ @Override public int hashCode() { @@ -1314,7 +1284,6 @@ public final class URI implements Comparable<URI>, Serializable { * defined in this URI. * * @return {@code true} if this URI is absolute, {@code false} otherwise. - * @since Android 1.0 */ public boolean isAbsolute() { return absolute; @@ -1327,7 +1296,6 @@ public final class URI implements Comparable<URI>, Serializable { * undefined. * * @return {@code true} if the URI is opaque, {@code false} otherwise. - * @since Android 1.0 */ public boolean isOpaque() { return opaque; @@ -1424,10 +1392,9 @@ public final class URI implements Comparable<URI>, Serializable { /** * Normalizes the path part of this URI. - * + * * @return an URI object which represents this instance with a normalized * path. - * @since Android 1.0 */ public URI normalize() { if (opaque) { @@ -1450,12 +1417,11 @@ public final class URI implements Comparable<URI>, Serializable { * Tries to parse the authority component of this URI to divide it into the * host, port, and user-info. If this URI is already determined as a * ServerAuthority this instance will be returned without changes. - * + * * @return this instance with the components of the parsed server authority. * @throws URISyntaxException * if the authority part could not be parsed as a server-based * authority. - * @since Android 1.0 */ public URI parseServerAuthority() throws URISyntaxException { if (!serverAuthority) { @@ -1467,11 +1433,10 @@ public final class URI implements Comparable<URI>, Serializable { /** * Makes the given URI {@code relative} to a relative URI against the URI * represented by this instance. - * + * * @param relative * the URI which has to be relativized against this URI. * @return the relative URI. - * @since Android 1.0 */ public URI relativize(URI relative) { if (relative.opaque || opaque) { @@ -1516,17 +1481,17 @@ public final class URI implements Comparable<URI>, Serializable { result.query = relative.query; // the result URI is the remainder of the relative URI's path result.path = relativePath.substring(thisPath.length()); + result.setSchemeSpecificPart(); return result; } /** * Resolves the given URI {@code relative} against the URI represented by * this instance. - * + * * @param relative * the URI which has to be resolved against this URI. * @return the resolved URI. - * @since Android 1.0 */ public URI resolve(URI relative) { if (relative.absolute || opaque) { @@ -1602,12 +1567,11 @@ public final class URI implements Comparable<URI>, Serializable { * Creates a new URI instance by parsing the given string {@code relative} * and resolves the created URI against the URI represented by this * instance. - * + * * @param relative * the given string to create the new URI instance which has to * be resolved later on. * @return the created and resolved URI. - * @since Android 1.0 */ public URI resolve(String relative) { return resolve(create(relative)); @@ -1652,9 +1616,8 @@ public final class URI implements Comparable<URI>, Serializable { /** * Returns the textual string representation of this URI instance using the * US-ASCII encoding. - * + * * @return the US-ASCII string representation of this URI. - * @since Android 1.0 */ public String toASCIIString() { return encodeOthers(toString()); @@ -1662,9 +1625,8 @@ public final class URI implements Comparable<URI>, Serializable { /** * Returns the textual string representation of this URI instance. - * + * * @return the textual string representation of this URI. - * @since Android 1.0 */ @Override public String toString() { @@ -1751,12 +1713,11 @@ public final class URI implements Comparable<URI>, Serializable { /** * Converts this URI instance to a URL. - * + * * @return the created URL representing the same resource as this URI. * @throws MalformedURLException * if an error occurs while creating the URL or no protocol * handler could be found. - * @since Android 1.0 */ public URL toURL() throws MalformedURLException { if (!absolute) { diff --git a/luni/src/main/java/java/net/URIEncoderDecoder.java b/luni/src/main/java/java/net/URIEncoderDecoder.java index a9ef3c1..4bf95ab 100644 --- a/luni/src/main/java/java/net/URIEncoderDecoder.java +++ b/luni/src/main/java/java/net/URIEncoderDecoder.java @@ -27,8 +27,6 @@ import org.apache.harmony.luni.util.Msg; * application/x-www-form-urlencoded} MIME content type. It contains helper * methods used by the URI class, and performs encoding and decoding in a * slightly different way than {@code URLEncoder} and {@code URLDecoder}. - * - * @since Android 1.0 */ class URIEncoderDecoder { @@ -43,8 +41,7 @@ class URIEncoderDecoder { * US-ASCII set, and are not ISO Control or are not ISO Space characters) * <p> * called from {@code URI.Helper.parseURI()} to validate each component - * </p> - * + * * @param s * {@code java.lang.String} the string to be validated * @param legal @@ -100,14 +97,12 @@ class URIEncoderDecoder { * by '%'. * <p> * For example: '#' -> %23 - * </p> * Other characters, which are unicode chars that are not US-ASCII, and are * not ISO Control or are not ISO Space chars, are preserved. * <p> * Called from {@code URI.quoteComponent()} (for multiple argument * constructors) - * </p> - * + * * @param s * java.lang.String the string to be converted * @param legal @@ -145,10 +140,9 @@ class URIEncoderDecoder { * converted into their hexidecimal value prepended by '%'. * <p> * For example: Euro currency symbol -> "%E2%82%AC". - * </p> + * <p> * Called from URI.toASCIIString() - * </p> - * + * * @param s * java.lang.String the string to be converted * @return java.lang.String the converted string @@ -178,11 +172,10 @@ class URIEncoderDecoder { *'%' and two following hex digit characters are converted to the * equivalent byte value. All other characters are passed through * unmodified. - * </p> + * <p> * e.g. "A%20B%20C %24%25" -> "A B C $%" * <p> * Called from URI.getXYZ() methods - * </p> * * @param s * java.lang.String The encoded string. diff --git a/luni/src/main/java/java/net/URISyntaxException.java b/luni/src/main/java/java/net/URISyntaxException.java index e7e332e..2daf35f 100644 --- a/luni/src/main/java/java/net/URISyntaxException.java +++ b/luni/src/main/java/java/net/URISyntaxException.java @@ -22,8 +22,6 @@ import org.apache.harmony.luni.util.Msg; /** * A {@code URISyntaxException} will be thrown if some information could not be parsed * while creating a URI. - * - * @since Android 1.0 */ public class URISyntaxException extends Exception { @@ -49,7 +47,6 @@ public class URISyntaxException extends Exception { * {@code null}. * @throws IllegalArgumentException * if the value for {@code index} is lesser than {@code -1}. - * @since Android 1.0 */ public URISyntaxException(String input, String reason, int index) { super(reason); @@ -77,7 +74,6 @@ public class URISyntaxException extends Exception { * @throws NullPointerException * if one of the arguments {@code input} or {@code reason} is * {@code null}. - * @since Android 1.0 */ public URISyntaxException(String input, String reason) { super(reason); @@ -95,7 +91,6 @@ public class URISyntaxException extends Exception { * index is unknown/unavailable. * * @return the index of the syntax error. - * @since Android 1.0 */ public int getIndex() { return index; @@ -105,7 +100,6 @@ public class URISyntaxException extends Exception { * Gets a description of the syntax error. * * @return the string describing the syntax error. - * @since Android 1.0 */ public String getReason() { return super.getMessage(); @@ -115,7 +109,6 @@ public class URISyntaxException extends Exception { * Gets the initial string that contains an invalid syntax. * * @return the string that caused the exception. - * @since Android 1.0 */ public String getInput() { return input; @@ -128,7 +121,6 @@ public class URISyntaxException extends Exception { * * @return a sting containing information about the exception. * @see java.lang.Throwable#getMessage() - * @since Android 1.0 */ @Override public String getMessage() { diff --git a/luni/src/main/java/java/net/URL.java b/luni/src/main/java/java/net/URL.java index 2bc8c6c..9b0fdc4 100644 --- a/luni/src/main/java/java/net/URL.java +++ b/luni/src/main/java/java/net/URL.java @@ -34,8 +34,6 @@ import org.apache.harmony.luni.util.Util; * which generates the output dynamically. A URL is divided in its parts * protocol, host name, port, path, file, user-info, query, reference and * authority. However, not each of this parts has to be defined. - * - * @since Android 1.0 */ public final class URL implements java.io.Serializable { private static final long serialVersionUID = -7627629688361524110L; @@ -131,11 +129,9 @@ public final class URL implements java.io.Serializable { * <p> * A security check is performed to verify whether the current policy allows * to set the stream handler factory. - * </p> - * + * * @param streamFactory * the factory to be used for creating stream protocol handlers. - * @since Android 1.0 */ public static synchronized void setURLStreamHandlerFactory( URLStreamHandlerFactory streamFactory) { @@ -158,7 +154,6 @@ public final class URL implements java.io.Serializable { * @throws MalformedURLException * if the given string {@code spec} could not be parsed as a * URL. - * @since Android 1.0 */ public URL(String spec) throws MalformedURLException { this((URL) null, spec, (URLStreamHandler) null); @@ -178,7 +173,6 @@ public final class URL implements java.io.Serializable { * @throws MalformedURLException * if the given string {@code spec} could not be parsed as a URL * or an invalid protocol has been found. - * @since Android 1.0 */ public URL(URL context, String spec) throws MalformedURLException { this(context, spec, (URLStreamHandler) null); @@ -202,7 +196,6 @@ public final class URL implements java.io.Serializable { * @throws MalformedURLException * if the given string {@code spec} could not be parsed as a URL * or an invalid protocol has been found. - * @since Android 1.0 */ public URL(URL context, String spec, URLStreamHandler handler) throws MalformedURLException { @@ -235,8 +228,6 @@ public final class URL implements java.io.Serializable { // According to RFC 2396 scheme part should match // the following expression: // alpha *( alpha | digit | "+" | "-" | "." ) - // BEGIN android-changed - // copied from newer version of harmony char c = protocol.charAt(0); boolean valid = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); for (int i = 1; valid && (i < protocol.length()); i++) { @@ -253,10 +244,9 @@ public final class URL implements java.io.Serializable { index = -1; } else { // Ignore case in protocol names. - // Scheme is defined by ASCII characters. + // Scheme is defined by ASCII characters. protocol = Util.toASCIILowerCase(protocol); } - // END android-changed } } @@ -338,7 +328,6 @@ public final class URL implements java.io.Serializable { * @throws MalformedURLException * if the combination of all arguments do not represent a valid * URL or the protocol is invalid. - * @since Android 1.0 */ public URL(String protocol, String host, String file) throws MalformedURLException { @@ -361,7 +350,6 @@ public final class URL implements java.io.Serializable { * @throws MalformedURLException * if the combination of all arguments do not represent a valid * URL or the protocol is invalid. - * @since Android 1.0 */ public URL(String protocol, String host, int port, String file) throws MalformedURLException { @@ -371,7 +359,7 @@ public final class URL implements java.io.Serializable { /** * Creates a new URL instance using the given arguments. The URL uses the * specified port instead of the default port for the given protocol. - * + * * @param protocol * the protocol of the new URL. * @param host @@ -386,25 +374,26 @@ public final class URL implements java.io.Serializable { * @throws MalformedURLException * if the combination of all arguments do not represent a valid * URL or the protocol is invalid. - * @since Android 1.0 + * @throws SecurityException + * if {@code handler} is non-{@code null}, and a security + * manager is installed that disallows user-defined protocol + * handlers. */ public URL(String protocol, String host, int port, String file, URLStreamHandler handler) throws MalformedURLException { if (port < -1) { - throw new MalformedURLException(org.apache.harmony.luni.util.Msg - .getString("K0325", port)); //$NON-NLS-1$ + throw new MalformedURLException(Msg.getString("K0325", port)); //$NON-NLS-1$ } if (host != null && host.indexOf(":") != -1 && host.charAt(0) != '[') { //$NON-NLS-1$ host = "[" + host + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } - if (protocol != null) { - this.protocol = protocol; - } else { - throw new NullPointerException(Msg.getString("K00b3", protocol)); //$NON-NLS-1$ + if (protocol == null) { + throw new NullPointerException(Msg.getString("K00b3", "null")); //$NON-NLS-1$ //$NON-NLS-2$ } + this.protocol = protocol; this.host = host; this.port = port; @@ -427,8 +416,7 @@ public final class URL implements java.io.Serializable { setupStreamHandler(); if (strmHandler == null) { throw new MalformedURLException( - org.apache.harmony.luni.util.Msg.getString( - "K00b3", protocol)); //$NON-NLS-1$ + Msg.getString("K00b3", protocol)); //$NON-NLS-1$ } } else { SecurityManager sm = System.getSecurityManager(); @@ -479,7 +467,6 @@ public final class URL implements java.io.Serializable { * the file to be set. * @param ref * the reference to be set. - * @since Android 1.0 */ protected void set(String protocol, String host, int port, String file, String ref) { @@ -506,8 +493,7 @@ public final class URL implements java.io.Serializable { * the URL this instance has to be compared with. * @return {@code true} if both instances represents the same URL, {@code * false} otherwise. - * @see #hashCode - * @since Android 1.0 + * @see #hashCode() */ @Override public boolean equals(Object o) { @@ -532,7 +518,6 @@ public final class URL implements java.io.Serializable { * the URL to compare against. * @return {@code true} if both instances refer to the same resource, * {@code false} otherwise. - * @since Android 1.0 */ public boolean sameFile(URL otherURL) { return strmHandler.sameFile(this, otherURL); @@ -542,7 +527,6 @@ public final class URL implements java.io.Serializable { * Gets the hashcode value of this URL instance. * * @return the appropriate hashcode value. - * @since Android 1.0 */ @Override public int hashCode() { @@ -560,7 +544,6 @@ public final class URL implements java.io.Serializable { * Note that this will overwrite any existing stream handler with the new * one. Senders must check if the strmHandler is null before calling the * method if they do not want this behavior (a speed optimization). - * </p> */ void setupStreamHandler() { // Check for a cached (previously looked up) handler for @@ -629,12 +612,10 @@ public final class URL implements java.io.Serializable { * <li>Image for pictures</li> * <li>AudioClip for audio sequences</li> * <li>{@link InputStream} for all other data</li> - * </p> * * @return the content of the referred resource. * @throws IOException * if an error occurs obtaining the content. - * @since Android 1.0 */ public final Object getContent() throws IOException { return openConnection().getContent(); @@ -654,7 +635,6 @@ public final class URL implements java.io.Serializable { * type. * @throws IOException * if an error occurs obtaining the content. - * @since Android 1.0 */ // Param not generic in spec @SuppressWarnings("unchecked") @@ -668,7 +648,6 @@ public final class URL implements java.io.Serializable { * @return the stream which allows to read the resource. * @throws IOException * if an error occurs while opening the InputStream. - * @since Android 1.0 */ public final InputStream openStream() throws java.io.IOException { return openConnection().getInputStream(); @@ -681,7 +660,6 @@ public final class URL implements java.io.Serializable { * @return the connection to this URL. * @throws IOException * if an error occurs while opening the connection. - * @since Android 1.0 */ public URLConnection openConnection() throws IOException { return strmHandler.openConnection(this); @@ -693,7 +671,6 @@ public final class URL implements java.io.Serializable { * @return the URI instance that represents this URL. * @throws URISyntaxException * if this URL cannot be converted into a URI. - * @since Android 1.0 */ public URI toURI() throws URISyntaxException { return new URI(toExternalForm()); @@ -718,7 +695,6 @@ public final class URL implements java.io.Serializable { * @throws UnsupportedOperationException * if the protocol handler does not support opening connections * through proxies. - * @since Android 1.0 */ public URLConnection openConnection(Proxy proxy) throws IOException { if (null == proxy) { @@ -733,7 +709,6 @@ public final class URL implements java.io.Serializable { * {@code toExternalForm()}. * * @return the string representation of this URL. - * @since Android 1.0 */ @Override public String toString() { @@ -745,7 +720,6 @@ public final class URL implements java.io.Serializable { * this URL. * * @return the string representation of this URL. - * @since Android 1.0 */ public String toExternalForm() { if (strmHandler == null) { @@ -798,8 +772,7 @@ public final class URL implements java.io.Serializable { * <p> * Note that, we really only need the readObject method but the spec that * says readObject will be ignored if no writeObject is present. - * </p> - * + * * @param s * the stream to write on. * @throws IOException @@ -814,7 +787,6 @@ public final class URL implements java.io.Serializable { * * @return the file name this URL refers to or an empty string if the file * part is not set. - * @since Android 1.0 */ public String getFile() { return file; @@ -824,7 +796,6 @@ public final class URL implements java.io.Serializable { * Gets the value of the host part of this URL. * * @return the host name or IP address of this URL. - * @since Android 1.0 */ public String getHost() { return host; @@ -834,7 +805,6 @@ public final class URL implements java.io.Serializable { * Gets the port number of this URL or {@code -1} if the port is not set. * * @return the port number of this URL. - * @since Android 1.0 */ public int getPort() { return port; @@ -844,7 +814,6 @@ public final class URL implements java.io.Serializable { * Gets the protocol of this URL. * * @return the protocol type of this URL. - * @since Android 1.0 */ public String getProtocol() { return protocol; @@ -854,7 +823,6 @@ public final class URL implements java.io.Serializable { * Gets the value of the reference part of this URL. * * @return the reference part of this URL. - * @since Android 1.0 */ public String getRef() { return ref; @@ -864,7 +832,6 @@ public final class URL implements java.io.Serializable { * Gets the value of the query part of this URL. * * @return the query part of this URL. - * @since Android 1.0 */ public String getQuery() { return query; @@ -874,7 +841,6 @@ public final class URL implements java.io.Serializable { * Gets the value of the path part of this URL. * * @return the path part of this URL. - * @since Android 1.0 */ public String getPath() { return path; @@ -884,7 +850,6 @@ public final class URL implements java.io.Serializable { * Gets the value of the user-info part of this URL. * * @return the user-info part of this URL. - * @since Android 1.0 */ public String getUserInfo() { return userInfo; @@ -894,7 +859,6 @@ public final class URL implements java.io.Serializable { * Gets the value of the authority part of this URL. * * @return the authority part of this URL. - * @since Android 1.0 */ public String getAuthority() { return authority; @@ -921,7 +885,6 @@ public final class URL implements java.io.Serializable { * the query to be set. * @param ref * the reference to be set. - * @since Android 1.0 */ protected void set(String protocol, String host, int port, String authority, String userInfo, String path, String query, @@ -941,21 +904,13 @@ public final class URL implements java.io.Serializable { this.query = query; } - // BEGIN android-removed - // copied from newer version of harmony - // URLStreamHandler getStreamHandler() { - // return strmHandler; - // } - // END android-removed - /** * Gets the default port number of the protocol used by this URL. If no * default port is defined by the protocol or the {@code URLStreamHandler}, * {@code -1} will be returned. - * + * * @return the default port number according to the protocol of this URL. * @see URLStreamHandler#getDefaultPort - * @since Android 1.0 */ public int getDefaultPort() { return strmHandler.getDefaultPort(); diff --git a/luni/src/main/java/java/net/URLClassLoader.java b/luni/src/main/java/java/net/URLClassLoader.java index c70ed45..dd3c9bf 100644 --- a/luni/src/main/java/java/net/URLClassLoader.java +++ b/luni/src/main/java/java/net/URLClassLoader.java @@ -17,12 +17,15 @@ package java.net; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.security.AccessControlContext; import java.security.AccessController; @@ -35,22 +38,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.IdentityHashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; -import java.util.Set; import java.util.StringTokenizer; -import java.util.Vector; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; -import java.util.zip.ZipEntry; -import org.apache.harmony.luni.util.InvalidJarIndexException; import org.apache.harmony.luni.util.Msg; /** @@ -58,33 +53,17 @@ import org.apache.harmony.luni.util.Msg; * list of URLs which can refer to either directories or JAR files. Classes * loaded by this {@code URLClassLoader} are granted permission to access the * URLs contained in the URL search list. - * - * @since Android 1.0 */ public class URLClassLoader extends SecureClassLoader { - private static URL[] NO_PATH = new URL[0]; + ArrayList<URL> originalUrls; - @SuppressWarnings("unchecked") - private static <K, V> Hashtable<K, V>[] newHashtableArray(int size) { - return new Hashtable[size]; - } - - URL[] urls, orgUrls; - - Set<URL> invalidUrls = Collections.synchronizedSet(new HashSet<URL>()); - - private Map<URL, JarFile> resCache = - Collections.synchronizedMap(new IdentityHashMap<URL, JarFile>(32)); - - private Object lock = new Object(); + List<URL> searchList; + ArrayList<URLHandler> handlerList; + Map<URL, URLHandler> handlerMap = new HashMap<URL, URLHandler>(); private URLStreamHandlerFactory factory; - HashMap<URL, URL[]> extensions; - - Hashtable<String, URL[]>[] indexes; - private AccessControlContext currentContext; static class SubURLClassLoader extends URLClassLoader { @@ -103,7 +82,7 @@ public class URLClassLoader extends SecureClassLoader { * Overrides the {@code loadClass()} of {@code ClassLoader}. It calls * the security manager's {@code checkPackageAccess()} before * attempting to load the class. - * + * * @return the Class object. * @param className * String the name of the class to search for. @@ -115,7 +94,7 @@ public class URLClassLoader extends SecureClassLoader { */ @Override protected synchronized Class<?> loadClass(String className, - boolean resolveClass) throws ClassNotFoundException { + boolean resolveClass) throws ClassNotFoundException { SecurityManager sm = System.getSecurityManager(); if (sm != null && !checkingPackageAccess) { int index = className.lastIndexOf('.'); @@ -132,12 +111,503 @@ public class URLClassLoader extends SecureClassLoader { } } + static class IndexFile { + + private HashMap<String, ArrayList<URL>> map; + //private URLClassLoader host; + + + static IndexFile readIndexFile(JarFile jf, JarEntry indexEntry, URL url) { + BufferedReader in = null; + InputStream is = null; + try { + // Add mappings from resource to jar file + String parentURLString = getParentURL(url).toExternalForm(); + String prefix = "jar:" //$NON-NLS-1$ + + parentURLString + "/"; //$NON-NLS-1$ + is = jf.getInputStream(indexEntry); + in = new BufferedReader(new InputStreamReader(is, "UTF8")); + HashMap<String, ArrayList<URL>> pre_map = new HashMap<String, ArrayList<URL>>(); + // Ignore the 2 first lines (index version) + if (in.readLine() == null) return null; + if (in.readLine() == null) return null; + TOP_CYCLE: + while (true) { + String line = in.readLine(); + if (line == null) { + break; + } + URL jar = new URL(prefix + line + "!/"); //$NON-NLS-1$ + while (true) { + line = in.readLine(); + if (line == null) { + break TOP_CYCLE; + } + if ("".equals(line)) { + break; + } + ArrayList<URL> list; + if (pre_map.containsKey(line)) { + list = pre_map.get(line); + } else { + list = new ArrayList<URL>(); + pre_map.put(line, list); + } + list.add(jar); + } + } + if (!pre_map.isEmpty()) { + return new IndexFile(pre_map); + } + } catch (MalformedURLException e) { + // Ignore this jar's index + } catch (IOException e) { + // Ignore this jar's index + } + finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + } + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + } + } + } + return null; + } + + private static URL getParentURL(URL url) throws IOException { + URL fileURL = ((JarURLConnection) url.openConnection()).getJarFileURL(); + String file = fileURL.getFile(); + String parentFile = new File(file).getParent(); + parentFile = parentFile.replace(File.separatorChar, '/'); + if (parentFile.charAt(0) != '/') { + parentFile = "/" + parentFile; //$NON-NLS-1$ + } + URL parentURL = new URL(fileURL.getProtocol(), fileURL + .getHost(), fileURL.getPort(), parentFile); + return parentURL; + } + + public IndexFile(HashMap<String, ArrayList<URL>> map) { + this.map = map; + } + + ArrayList<URL> get(String name) { + return map.get(name); + } + } + + class URLHandler { + URL url; + URL codeSourceUrl; + + public URLHandler(URL url) { + this.url = url; + this.codeSourceUrl = url; + } + + void findResources(String name, ArrayList<URL> resources) { + URL res = findResource(name); + if (res != null && !resources.contains(res)) { + resources.add(res); + } + } + + Class<?> findClass(String packageName, String name, String origName) { + URL resURL = targetURL(url, name); + if (resURL != null) { + try { + InputStream is = resURL.openStream(); + return createClass(is, packageName, origName); + } catch (IOException e) { + } + } + return null; + } + + + Class<?> createClass(InputStream is, String packageName, String origName) { + if (is == null) { + return null; + } + byte[] clBuf = null; + try { + clBuf = getBytes(is); + } catch (IOException e) { + return null; + } finally { + try { + is.close(); + } catch (IOException e) { + } + } + if (packageName != null) { + String packageDotName = packageName.replace('/', '.'); + Package packageObj = getPackage(packageDotName); + if (packageObj == null) { + definePackage(packageDotName, null, null, + null, null, null, null, null); + } else { + if (packageObj.isSealed()) { + throw new SecurityException(Msg + .getString("K004c")); //$NON-NLS-1$ + } + } + } + return defineClass(origName, clBuf, 0, clBuf.length, new CodeSource(codeSourceUrl, (Certificate[]) null)); + } + + URL findResource(String name) { + URL resURL = targetURL(url, name); + if (resURL != null) { + try { + URLConnection uc = resURL.openConnection(); + uc.getInputStream().close(); + // HTTP can return a stream on a non-existent file + // So check for the return code; + if (!resURL.getProtocol().equals("http")) { //$NON-NLS-1$ + return resURL; + } + int code; + if ((code = ((HttpURLConnection) uc).getResponseCode()) >= 200 + && code < 300) { + return resURL; + } + } catch (SecurityException e) { + return null; + } catch (IOException e) { + return null; + } + } + return null; + } + + URL targetURL(URL base, String name) { + try { + String file = base.getFile() + URIEncoderDecoder.quoteIllegal(name, + "/@" + URI.someLegal); + + return new URL(base.getProtocol(), base.getHost(), base.getPort(), + file, null); + } catch (UnsupportedEncodingException e) { + return null; + } catch (MalformedURLException e) { + return null; + } + } + + } + + class URLJarHandler extends URLHandler { + final JarFile jf; + final String prefixName; + final IndexFile index; + final Map<URL, URLHandler> subHandlers = new HashMap<URL, URLHandler>(); + + public URLJarHandler(URL url, URL jarURL, JarFile jf, String prefixName) { + super(url); + this.jf = jf; + this.prefixName = prefixName; + this.codeSourceUrl = jarURL; + final JarEntry je = jf.getJarEntry("META-INF/INDEX.LIST"); //$NON-NLS-1$ + this.index = (je == null ? null : IndexFile.readIndexFile(jf, je, url)); + } + + public URLJarHandler(URL url, URL jarURL, JarFile jf, String prefixName, IndexFile index) { + super(url); + this.jf = jf; + this.prefixName = prefixName; + this.index = index; + this.codeSourceUrl = jarURL; + } + + IndexFile getIndex() { + return index; + } + + @Override + void findResources(String name, ArrayList<URL> resources) { + URL res = findResourceInOwn(name); + if (res != null && !resources.contains(res)) { + resources.add(res); + } + if (index != null) { + int pos = name.lastIndexOf("/"); //$NON-NLS-1$ + // only keep the directory part of the resource + // as index.list only keeps track of directories and root files + String indexedName = (pos > 0) ? name.substring(0, pos) : name; + ArrayList<URL> urls = index.get(indexedName); + if (urls != null) { + urls.remove(url); + for (URL url : urls) { + URLHandler h = getSubHandler(url); + if (h != null) { + h.findResources(name, resources); + } + } + } + } + + } + + @Override + Class<?> findClass(String packageName, String name, String origName) { + String entryName = prefixName + name; + JarEntry entry = jf.getJarEntry(entryName); + if (entry != null) { + /** + * Avoid recursive load class, especially the class + * is an implementation class of security provider + * and the jar is signed. + */ + try { + Manifest manifest = jf.getManifest(); + return createClass(entry, manifest, packageName, origName); + } catch (IOException e) { + } + } + if (index != null) { + ArrayList<URL> urls; + if (packageName == null) { + urls = index.get(name); + } else { + urls = index.get(packageName); + } + if (urls != null) { + urls.remove(url); + for (URL url : urls) { + URLHandler h = getSubHandler(url); + if (h != null) { + Class<?> res = h.findClass(packageName, name, origName); + if (res != null) { + return res; + } + } + } + } + } + return null; + } + + private Class<?> createClass(JarEntry entry, Manifest manifest, String packageName, String origName) { + InputStream is = null; + byte[] clBuf = null; + try { + is = jf.getInputStream(entry); + clBuf = getBytes(is); + } catch (IOException e) { + return null; + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + } + } + } + if (packageName != null) { + String packageDotName = packageName.replace('/', '.'); + Package packageObj = getPackage(packageDotName); + if (packageObj == null) { + if (manifest != null) { + definePackage(packageDotName, manifest, + codeSourceUrl); + } else { + definePackage(packageDotName, null, null, + null, null, null, null, null); + } + } else { + boolean exception = packageObj.isSealed(); + if (manifest != null) { + if (isSealed(manifest, packageName + "/")) { + exception = !packageObj + .isSealed(codeSourceUrl); + } + } + if (exception) { + throw new SecurityException(Msg + .getString("K0352", packageName)); //$NON-NLS-1$ + } + } + } + CodeSource codeS = new CodeSource(codeSourceUrl, entry.getCertificates()); + return defineClass(origName, clBuf, 0, clBuf.length, codeS); + } + + URL findResourceInOwn(String name) { + String entryName = prefixName + name; + if (jf.getEntry(entryName) != null) { + return targetURL(url, name); + } + return null; + } + + @Override + URL findResource(String name) { + URL res = findResourceInOwn(name); + if (res != null) { + return res; + } + if (index != null) { + int pos = name.lastIndexOf("/"); //$NON-NLS-1$ + // only keep the directory part of the resource + // as index.list only keeps track of directories and root files + String indexedName = (pos > 0) ? name.substring(0, pos) : name; + ArrayList<URL> urls = index.get(indexedName); + if (urls != null) { + urls.remove(url); + for (URL url : urls) { + URLHandler h = getSubHandler(url); + if (h != null) { + res = h.findResource(name); + if (res != null) { + return res; + } + } + } + } + } + return null; + } + + private synchronized URLHandler getSubHandler(URL url) { + URLHandler sub = subHandlers.get(url); + if (sub != null) { + return sub; + } + String protocol = url.getProtocol(); + if (protocol.equals("jar")) { //$NON-NLS-1$ + sub = createURLJarHandler(url); + } else if (protocol.equals("file")) { //$NON-NLS-1$ + sub = createURLSubJarHandler(url); + } else { + sub = createURLHandler(url); + } + if (sub != null) { + subHandlers.put(url, sub); + } + return sub; + } + + private URLHandler createURLSubJarHandler(URL url) { + String prefixName; + String file = url.getFile(); + if (url.getFile().endsWith("!/")) { //$NON-NLS-1$ + prefixName = ""; + } else { + int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$ + if (sepIdx == -1) { + // Invalid URL, don't look here again + return null; + } + sepIdx += 2; + prefixName = file.substring(sepIdx); + } + try { + URL jarURL = ((JarURLConnection) url + .openConnection()).getJarFileURL(); + JarURLConnection juc = (JarURLConnection) new URL( + "jar", "", //$NON-NLS-1$ //$NON-NLS-2$ + jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$ + JarFile jf = juc.getJarFile(); + URLJarHandler jarH = new URLJarHandler(url, jarURL, jf, prefixName, null); + // TODO : to think what we should do with indexes & manifest.class file here + return jarH; + } catch (IOException e) { + } + return null; + } + + } + + class URLFileHandler extends URLHandler { + private String prefix; + + public URLFileHandler(URL url) { + super(url); + String baseFile = url.getFile(); + String host = url.getHost(); + int hostLength = 0; + if (host != null) { + hostLength = host.length(); + } + StringBuilder buf = new StringBuilder(2 + hostLength + + baseFile.length()); + if (hostLength > 0) { + buf.append("//").append(host); //$NON-NLS-1$ + } + // baseFile always ends with '/' + buf.append(baseFile); + prefix = buf.toString(); + } + + @Override + Class<?> findClass(String packageName, String name, String origName) { + String filename = prefix + name; + try { + filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$ + } catch (IllegalArgumentException e) { + return null; + } catch (UnsupportedEncodingException e) { + return null; + } + + File file = new File(filename); + if (file.exists()) { + try { + InputStream is = new FileInputStream(file); + return createClass(is, packageName, origName); + } catch (FileNotFoundException e) { + } + } + return null; + } + + @Override + URL findResource(String name) { + int idx = 0; + String filename; + + // Do not create a UNC path, i.e. \\host + while (idx < name.length() && + ((name.charAt(idx) == '/') || (name.charAt(idx) == '\\'))) { + idx++; + } + + if (idx > 0) { + name = name.substring(idx); + } + + try { + filename = URLDecoder.decode(prefix, "UTF-8") + name; //$NON-NLS-1$ + + if (new File(filename).exists()) { + return targetURL(url, name); + } + return null; + } catch (IllegalArgumentException e) { + return null; + } catch (UnsupportedEncodingException e) { + // must not happen + throw new AssertionError(e); + } + } + + } + + /** * Constructs a new {@code URLClassLoader} instance. The newly created * instance will have the system ClassLoader as its parent. URLs that end * with "/" are assumed to be directories, otherwise they are assumed to be * JAR files. - * + * * @param urls * the list of URLs where a specific class or file could be * found. @@ -145,7 +615,6 @@ public class URLClassLoader extends SecureClassLoader { * if a security manager exists and its {@code * checkCreateClassLoader()} method doesn't allow creation of * new ClassLoaders. - * @since Android 1.0 */ public URLClassLoader(URL[] urls) { this(urls, ClassLoader.getSystemClassLoader(), null); @@ -155,7 +624,7 @@ public class URLClassLoader extends SecureClassLoader { * Constructs a new URLClassLoader instance. The newly created instance will * have the system ClassLoader as its parent. URLs that end with "/" are * assumed to be directories, otherwise they are assumed to be JAR files. - * + * * @param urls * the list of URLs where a specific class or file could be * found. @@ -165,7 +634,6 @@ public class URLClassLoader extends SecureClassLoader { * if a security manager exists and its {@code * checkCreateClassLoader()} method doesn't allow creation of * new class loaders. - * @since Android 1.0 */ public URLClassLoader(URL[] urls, ClassLoader parent) { this(urls, parent, null); @@ -173,267 +641,81 @@ public class URLClassLoader extends SecureClassLoader { /** * Adds the specified URL to the search list. - * + * * @param url * the URL which is to add. - * @since Android 1.0 */ protected void addURL(URL url) { try { - URL search = createSearchURL(url); - urls = addURL(urls, search); - orgUrls = addURL(orgUrls, url); - synchronized (extensions) { - extensions.put(search, null); - } + originalUrls.add(url); + searchList.add(createSearchURL(url)); } catch (MalformedURLException e) { } } /** - * Returns an array with the given URL added to the given array. - * - * @param urlArray - * {@code java.net.URL[]} the source array - * @param url - * {@code java.net.URL} the URL to be added - * @return java.net.URL[] an array made of the given array and the new URL - */ - URL[] addURL(URL[] urlArray, URL url) { - URL[] newPath = new URL[urlArray.length + 1]; - System.arraycopy(urlArray, 0, newPath, 0, urlArray.length); - newPath[urlArray.length] = url; - Hashtable<String, URL[]>[] newIndexes = newHashtableArray(indexes.length + 1); - System.arraycopy(indexes, 0, newIndexes, 0, indexes.length); - indexes = newIndexes; - return newPath; - } - - /** * Returns all known URLs which point to the specified resource. - * + * * @param name * the name of the requested resource. * @return the enumeration of URLs which point to the specified resource. * @throws IOException * if an I/O error occurs while attempting to connect. - * @since Android 1.0 */ @Override public Enumeration<URL> findResources(final String name) throws IOException { if (name == null) { return null; } - Vector<URL> result = AccessController.doPrivileged( - new PrivilegedAction<Vector<URL>>() { - public Vector<URL> run() { - return findResources(urls, name, new Vector<URL>()); + ArrayList<URL> result = AccessController.doPrivileged( + new PrivilegedAction<ArrayList<URL>>() { + public ArrayList<URL> run() { + ArrayList<URL> results = new ArrayList<URL>(); + findResourcesImpl(name, results); + return results; } }, currentContext); SecurityManager sm; int length = result.size(); if (length > 0 && (sm = System.getSecurityManager()) != null) { - Vector<URL> reduced = new Vector<URL>(length); + ArrayList<URL> reduced = new ArrayList<URL>(length); for (int i = 0; i < length; i++) { - URL url = result.elementAt(i); + URL url = result.get(i); try { sm.checkPermission(url.openConnection().getPermission()); - reduced.addElement(url); + reduced.add(url); } catch (IOException e) { } catch (SecurityException e) { } } result = reduced; } - return result.elements(); + return Collections.enumeration(result); } - /** - * Returns a Vector of URLs among the given ones that contain the specified - * resource. - * - * @return Vector the enumeration of URLs that contain the specified - * resource. - * @param searchURLs - * {@code java.net.URL[]} the array to be searched. - * @param name - * {@code java.lang.String} the name of the requested resource. - */ - Vector<URL> findResources(URL[] searchURLs, String name, Vector<URL> result) { - boolean findInExtensions = searchURLs == urls; - for (int i = 0; i < searchURLs.length; i++) { - if (!invalidUrls.contains(searchURLs[i])) { - URL[] search = new URL[] { searchURLs[i] }; - URL res = findResourceImpl(search, name); - if (!invalidUrls.contains(search[0])) { - if (res != null && !result.contains(res)) { - result.addElement(res); - } - if (findInExtensions) { - findInExtensions(explore(searchURLs[i], i), name, i, - result, false); - } - } + void findResourcesImpl(String name, ArrayList<URL> result) { + int n = 0; + while (true) { + URLHandler handler = getHandler(n++); + if (handler == null) { + break; } + handler.findResources(name, result); } - return result; } - /** - * Returns an {@code Object[]} containing a class, a URL, and a vector of - * URLs, two of which are {@code null}, according to the caller, which is - * identified by the {@code int} type. - * - * @return Object[] a 3-element array : {Class, URL, Vector}. The non-null - * element contains the resource(s) found, which are searched in in - * {@code indexes[i]}. - * @param i - * the index of 'indexes' array to use. - * @param name - * the resource to look for : either a resource or a class. - * @param resources - * {@code boolean} indicates that a vector of URL should be - * returned as the non {@code null} element in {@code Object[]}. - * @param url - * if {@code true} a URL should be returned as the non-null - * element, if {@code false} a class should be returned. - */ - Object findInIndex(int i, String name, Vector<URL> resources, boolean url) { - Hashtable<String, URL[]> index = indexes[i]; - if (index != null) { - int pos = name.lastIndexOf("/"); //$NON-NLS-1$ - // only keep the directory part of the resource - // as index.list only keeps track of directories and root files - String indexedName = (pos > 0) ? name.substring(0, pos) : name; - URL[] jarURLs; - if (resources != null) { - jarURLs = index.get(indexedName); - if (jarURLs != null) { - findResources(jarURLs, name, resources); - } - } else if (url) { - jarURLs = index.get(indexedName); - if (jarURLs != null) { - return findResourceImpl(jarURLs, name); - } - } else { - String clsName = name; - String partialName = clsName.replace('.', '/'); - int position; - if ((position = partialName.lastIndexOf('/')) != -1) { - String packageName = partialName.substring(0, position); - jarURLs = index.get(packageName); - } else { - String className = partialName.substring(0, partialName - .length()) - + ".class"; //$NON-NLS-1$ - jarURLs = index.get(className); - } - if (jarURLs != null) { - Class<?> c = findClassImpl(jarURLs, clsName); - // InvalidJarException is thrown when a mapping for a class - // is not valid, i.e. we can't find the class by following - // the mapping. - if (c == null) { - throw new InvalidJarIndexException(); - } - return c; - } - } - } - return null; - } - - /** - * Returns an {@code Object[]} containing a Class, a URL, and a Vector of - * URLs, two of which are {@code null}, according to the caller, which is - * identified by the {@code int} type. - * - * @return Object[] a 3-element array : {Class, URL, Vector}. The non-null - * element contains the resource(s) found, which are searched in - * newExtensions. - * @param newExtensions - * URL[] the URLs to look in for. - * @param name - * the resource to look for : either a resource or a class. - * @param i - * the index of 'indexes' array to use. - * @param resources - * indicates that a Vector of URL should be returned as the - * non-null element in {@code Object[]}. - * @param url - * if {@code true} a URL should be returned as the non-null - * element, if {@code false} a class should be returned. - */ - Object findInExtensions(URL[] newExtensions, String name, int i, - Vector<URL> resources, boolean url) { - if (newExtensions != null) { - for (int k = 0; k < newExtensions.length; k++) { - if (newExtensions[k] != null) { - URL[] search = new URL[] { newExtensions[k] }; - if (resources != null) { - URL res = findResourceImpl(search, name); - if (!invalidUrls.contains(search[0])) { // the URL does - // not exist - if (res != null && !resources.contains(res)) { - resources.addElement(res); - } - findInExtensions(explore(newExtensions[k], i), - name, i, resources, url); - } - } else { - Object result; - if (url) { - result = findResourceImpl(search, name); - } else { - result = findClassImpl(search, name); - } - if (result != null) { - return result; - } - if (!invalidUrls.contains(search[0])) { // the URL - // exists - result = findInExtensions(explore(newExtensions[k], - i), name, i, null, url); - if (result != null) { - return result; - } - } - } - } - } - } else { - try { - return findInIndex(i, name, resources, url); - } catch (InvalidJarIndexException ex) { - // Ignore misleading/wrong jar index - return null; - } - } - return null; - } /** * Converts an input stream into a byte array. - * - * @return byte[] the byte array + * * @param is * the input stream + * @return byte[] the byte array */ - private static byte[] getBytes(InputStream is, boolean readAvailable) + private static byte[] getBytes(InputStream is) throws IOException { - if (readAvailable) { - byte[] buf = new byte[is.available()]; - is.read(buf, 0, buf.length); - is.close(); - return buf; - } byte[] buf = new byte[4096]; - int size = is.available(); - if (size < 1024) { - size = 1024; - } - ByteArrayOutputStream bos = new ByteArrayOutputStream(size); + ByteArrayOutputStream bos = new ByteArrayOutputStream(4096); int count; while ((count = is.read(buf)) > 0) { bos.write(buf, 0, count); @@ -448,11 +730,10 @@ public class URLClassLoader extends SecureClassLoader { * read permission to the file is added to the permission collection. * Otherwise, connecting to and accepting connections from the URL is * granted. - * + * * @param codesource * the code source object whose permissions have to be known. * @return the list of permissions according to the code source object. - * @since Android 1.0 */ @Override protected PermissionCollection getPermissions(final CodeSource codesource) { @@ -494,12 +775,11 @@ public class URLClassLoader extends SecureClassLoader { /** * Returns the search list of this {@code URLClassLoader}. - * + * * @return the list of all known URLs of this instance. - * @since Android 1.0 */ public URL[] getURLs() { - return orgUrls.clone(); + return originalUrls.toArray(new URL[originalUrls.size()]); } /** @@ -515,12 +795,11 @@ public class URLClassLoader extends SecureClassLoader { * system {@code ClassLoader} as its parent. The method {@code loadClass()} * of the new instance will call {@code * SecurityManager.checkPackageAccess()} before loading a class. - * + * * @param urls * the list of URLs that is passed to the new {@code * URLClassloader}. * @return the created {@code URLClassLoader} instance. - * @since Android 1.0 */ public static URLClassLoader newInstance(final URL[] urls) { URLClassLoader sub = AccessController @@ -538,17 +817,16 @@ public class URLClassLoader extends SecureClassLoader { * specified {@code ClassLoader} as its parent. The method {@code * loadClass()} of the new instance will call the SecurityManager's {@code * checkPackageAccess()} before loading a class. - * + * * @param urls * the list of URLs that is passed to the new URLClassloader. * @param parentCl * the parent class loader that is passed to the new * URLClassloader. * @return the created {@code URLClassLoader} instance. - * @since Android 1.0 */ public static URLClassLoader newInstance(final URL[] urls, - final ClassLoader parentCl) { + final ClassLoader parentCl) { URLClassLoader sub = AccessController .doPrivileged(new PrivilegedAction<URLClassLoader>() { public URLClassLoader run() { @@ -565,7 +843,7 @@ public class URLClassLoader extends SecureClassLoader { * use the specified factory to create stream handlers. URLs that end with * "/" are assumed to be directories, otherwise they are assumed to be JAR * files. - * + * * @param searchUrls * the list of URLs where a specific class or file could be * found. @@ -578,10 +856,9 @@ public class URLClassLoader extends SecureClassLoader { * if a security manager exists and its {@code * checkCreateClassLoader()} method doesn't allow creation of * new {@code ClassLoader}s. - * @since Android 1.0 */ public URLClassLoader(URL[] searchUrls, ClassLoader parent, - URLStreamHandlerFactory factory) { + URLStreamHandlerFactory factory) { super(parent); // Required for pre-v1.2 security managers to work SecurityManager security = System.getSecurityManager(); @@ -592,33 +869,28 @@ public class URLClassLoader extends SecureClassLoader { // capture the context of the thread that creates this URLClassLoader currentContext = AccessController.getContext(); int nbUrls = searchUrls.length; - urls = new URL[nbUrls]; - orgUrls = new URL[nbUrls]; - // Search each jar for CLASS-PATH attribute in manifest - extensions = new HashMap<URL, URL[]>(nbUrls * 2); + originalUrls = new ArrayList<URL>(nbUrls); + handlerList = new ArrayList<URLHandler>(nbUrls); + searchList = Collections.synchronizedList(new ArrayList<URL>(nbUrls)); for (int i = 0; i < nbUrls; i++) { + originalUrls.add(searchUrls[i]); try { - urls[i] = createSearchURL(searchUrls[i]); - extensions.put(urls[i], null); + searchList.add(createSearchURL(searchUrls[i])); } catch (MalformedURLException e) { } - orgUrls[i] = searchUrls[i]; } - // Search each jar for META-INF/INDEX.LIST - indexes = newHashtableArray(nbUrls); } /** * Tries to locate and load the specified class using the known URLs. If the * class could be found, a class object representing the loaded class will * be returned. - * - * @return the class that has been loaded. + * * @param clsName * the name of the class which has to be found. + * @return the class that has been loaded. * @throws ClassNotFoundException * if the specified class cannot be loaded. - * @since Android 1.0 */ @Override protected Class<?> findClass(final String clsName) @@ -626,7 +898,7 @@ public class URLClassLoader extends SecureClassLoader { Class<?> cls = AccessController.doPrivileged( new PrivilegedAction<Class<?>>() { public Class<?> run() { - return findClassImpl(urls, clsName); + return findClassImpl(clsName); } }, currentContext); if (cls != null) { @@ -639,7 +911,7 @@ public class URLClassLoader extends SecureClassLoader { * Returns an URL that will be checked if it contains the class or resource. * If the file component of the URL is not a directory, a Jar URL will be * created. - * + * * @return java.net.URL a test URL */ private URL createSearchURL(URL url) throws MalformedURLException { @@ -656,19 +928,19 @@ public class URLClassLoader extends SecureClassLoader { return new URL("jar", "", //$NON-NLS-1$ //$NON-NLS-2$ -1, url.toString() + "!/"); //$NON-NLS-1$ } + // use jar protocol as the stream handler protocol return new URL("jar", "", //$NON-NLS-1$ //$NON-NLS-2$ -1, url.toString() + "!/", //$NON-NLS-1$ - factory.createURLStreamHandler(protocol)); + factory.createURLStreamHandler("jar"));//$NON-NLS-1$ } /** * Returns an URL referencing the specified resource or {@code null} if the * resource could not be found. - * + * * @param name * the name of the requested resource. * @return the URL which points to the given resource. - * @since Android 1.0 */ @Override public URL findResource(final String name) { @@ -677,7 +949,7 @@ public class URLClassLoader extends SecureClassLoader { } URL result = AccessController.doPrivileged(new PrivilegedAction<URL>() { public URL run() { - return findResourceImpl(urls, name); + return findResourceImpl(name); } }, currentContext); SecurityManager sm; @@ -696,161 +968,108 @@ public class URLClassLoader extends SecureClassLoader { /** * Returns a URL among the given ones referencing the specified resource or * null if no resource could be found. - * + * + * @param resName java.lang.String the name of the requested resource * @return URL URL for the resource. - * @param searchList - * java.net.URL[] the array to be searched - * @param resName - * java.lang.String the name of the requested resource */ - URL findResourceImpl(URL[] searchList, String resName) { - boolean findInExtensions = searchList == urls; - int i = 0; - while (i < searchList.length) { - if (searchList[i] == null) { - // KA024=One of urls is null + URL findResourceImpl(String resName) { + int n = 0; + + while (true) { + URLHandler handler = getHandler(n++); + if (handler == null) { + break; + } + URL res = handler.findResource(resName); + if (res != null) { + return res; + } + } + return null; + } + + URLHandler getHandler(int num) { + if (num < handlerList.size()) { + return handlerList.get(num); + } + makeNewHandler(); + if (num < handlerList.size()) { + return handlerList.get(num); + } + return null; + } + + private synchronized void makeNewHandler() { + while (!searchList.isEmpty()) { + URL nextCandidate = searchList.remove(0); + if (nextCandidate == null) { // KA024=One of urls is null throw new NullPointerException(Msg.getString("KA024")); //$NON-NLS-1$ - } else if (!invalidUrls.contains(searchList[i])) { - JarFile jf = null; - try { - URL currentUrl = searchList[i]; - String protocol = currentUrl.getProtocol(); - - if (protocol.equals("jar")) { //$NON-NLS-1$ - jf = resCache.get(currentUrl); - if (jf == null) { - if (invalidUrls.contains(currentUrl)) { - continue; - } - // each jf should be found only once - // so we do this job in the synchronized block - synchronized (lock) { - // Check the cache again in case another thread - // updated it while we're waiting on lock - jf = resCache.get(currentUrl); - if (jf == null) { - if (invalidUrls.contains(currentUrl)) { - continue; - } - /* - * If the connection for currentUrl or resURL is - * used, getJarFile() will throw an exception if the - * entry doesn't exist. - */ - URL jarURL = ((JarURLConnection) currentUrl - .openConnection()).getJarFileURL(); - try { - JarURLConnection juc = (JarURLConnection) new URL( - "jar", "", //$NON-NLS-1$ //$NON-NLS-2$ - jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$ - jf = juc.getJarFile(); - resCache.put(currentUrl, jf); - } catch (IOException e) { - // Don't look for this jar file again - invalidUrls.add(searchList[i]); - throw e; - } - } - } - } - String entryName; - if (currentUrl.getFile().endsWith("!/")) { //$NON-NLS-1$ - entryName = resName; - } else { - String file = currentUrl.getFile(); - int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$ - if (sepIdx == -1) { - // Invalid URL, don't look here again - invalidUrls.add(searchList[i]); - continue; - } - sepIdx += 2; - entryName = new StringBuffer(file.length() - sepIdx - + resName.length()).append( - file.substring(sepIdx)).append(resName) - .toString(); - } - if (jf.getEntry(entryName) != null) { - return targetURL(currentUrl, resName); - } - } else if (protocol.equals("file")) { //$NON-NLS-1$ - String baseFile = currentUrl.getFile(); - String host = currentUrl.getHost(); - int hostLength = 0; - if (host != null) { - hostLength = host.length(); - } - StringBuffer buf = new StringBuffer(2 + hostLength - + baseFile.length() + resName.length()); - if (hostLength > 0) { - buf.append("//").append(host); //$NON-NLS-1$ - } - // baseFile always ends with '/' - buf.append(baseFile); - String fixedResName = resName; - // Do not create a UNC path, i.e. \\host - while (fixedResName.startsWith("/") //$NON-NLS-1$ - || fixedResName.startsWith("\\")) { //$NON-NLS-1$ - fixedResName = fixedResName.substring(1); - } - buf.append(fixedResName); - - String filename = buf.toString(); - - try { - filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$ - } catch (IllegalArgumentException e) { - return null; - } + } + if (!handlerMap.containsKey(nextCandidate)) { + URLHandler result; + String protocol = nextCandidate.getProtocol(); + if (protocol.equals("jar")) { //$NON-NLS-1$ + result = createURLJarHandler(nextCandidate); + } else if (protocol.equals("file")) { //$NON-NLS-1$ + result = createURLFileHandler(nextCandidate); + } else { + result = createURLHandler(nextCandidate); + } + if (result != null) { + handlerMap.put(nextCandidate, result); + handlerList.add(result); + return; + } + } + } + } - if (new File(filename).exists()) { - return targetURL(currentUrl, fixedResName); - } - } else { - URL resURL = targetURL(currentUrl, resName); - URLConnection uc = resURL.openConnection(); - try { - uc.getInputStream().close(); - } catch (SecurityException e) { - return null; - } - // HTTP can return a stream on a non-existent file - // So check for the return code; - if (!resURL.getProtocol().equals("http")) { //$NON-NLS-1$ - return resURL; - } - int code; - if ((code = ((HttpURLConnection) uc).getResponseCode()) >= 200 - && code < 300) { - return resURL; + private URLHandler createURLHandler(URL url) { + return new URLHandler(url); + } + + private URLHandler createURLFileHandler(URL url) { + return new URLFileHandler(url); + } + + private URLHandler createURLJarHandler(URL url) { + String prefixName; + String file = url.getFile(); + if (url.getFile().endsWith("!/")) { //$NON-NLS-1$ + prefixName = ""; + } else { + int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$ + if (sepIdx == -1) { + // Invalid URL, don't look here again + return null; + } + sepIdx += 2; + prefixName = file.substring(sepIdx); + } + try { + URL jarURL = ((JarURLConnection) url + .openConnection()).getJarFileURL(); + JarURLConnection juc = (JarURLConnection) new URL( + "jar", "", //$NON-NLS-1$ //$NON-NLS-2$ + jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$ + JarFile jf = juc.getJarFile(); + URLJarHandler jarH = new URLJarHandler(url, jarURL, jf, prefixName); + + if (jarH.getIndex() == null) { + try { + Manifest manifest = jf.getManifest(); + if (manifest != null) { + String classpath = manifest.getMainAttributes().getValue( + Attributes.Name.CLASS_PATH); + if (classpath != null) { + searchList.addAll(0, getInternalURLs(url, classpath)); } } - } catch (MalformedURLException e) { - // Keep iterating through the URL list } catch (IOException e) { - } catch (SecurityException e) { - } - if ((jf != null) && findInExtensions) { - if (indexes[i] != null) { - try { - URL result = (URL) findInIndex(i, resName, null, - true); - if (result != null) { - return result; - } - } catch (InvalidJarIndexException ex) { - // Ignore invalid/misleading JAR index file - } - } else { - URL result = (URL) findInExtensions(explore( - searchList[i], i), resName, i, null, true); - if (result != null) { - return result; - } - } } } - ++i; + return jarH; + } catch (IOException e) { } return null; } @@ -858,7 +1077,7 @@ public class URLClassLoader extends SecureClassLoader { /** * Defines a new package using the information extracted from the specified * manifest. - * + * * @param packageName * the name of the new package. * @param manifest @@ -869,10 +1088,9 @@ public class URLClassLoader extends SecureClassLoader { * @return the created package. * @throws IllegalArgumentException * if a package with the given name already exists. - * @since Android 1.0 */ protected Package definePackage(String packageName, Manifest manifest, - URL url) throws IllegalArgumentException { + URL url) throws IllegalArgumentException { Attributes mainAttributes = manifest.getMainAttributes(); String dirName = packageName.replace('.', '/') + "/"; //$NON-NLS-1$ Attributes packageAttributes = manifest.getAttributes(dirName); @@ -921,7 +1139,7 @@ public class URLClassLoader extends SecureClassLoader { return definePackage(packageName, specificationTitle, specificationVersion, specificationVendor, implementationTitle, implementationVersion, implementationVendor, isSealed(manifest, - dirName) ? url : null); + dirName) ? url : null); } private boolean isSealed(Manifest manifest, String dirName) { @@ -940,19 +1158,18 @@ public class URLClassLoader extends SecureClassLoader { /** * returns URLs referenced in the string classpath. - * + * * @param root * the jar URL that classpath is related to * @param classpath * the relative URLs separated by spaces - * * @return URL[] the URLs contained in the string classpath. */ - private URL[] getInternalURLs(URL root, String classpath) { + private ArrayList<URL> getInternalURLs(URL root, String classpath) { // Class-path attribute is composed of space-separated values. StringTokenizer tokenizer = new java.util.StringTokenizer(classpath); - Vector<URL> addedURLs = new Vector<URL>(); - String file = root.getFile(); + ArrayList<URL> addedURLs = new ArrayList<URL>(); + String file = root.getFile(); int jarIndex = file.lastIndexOf("!/") - 1; //$NON-NLS-1$ int index = file.lastIndexOf("/", jarIndex) + 1; //$NON-NLS-1$ if (index == 0) { @@ -969,381 +1186,40 @@ public class URLClassLoader extends SecureClassLoader { try { URL newURL = new URL(protocol, host, port, file + element + "!/"); //$NON-NLS-1$ - synchronized (extensions) { - if (!extensions.containsKey(newURL)) { - extensions.put(newURL, null); - addedURLs.add(newURL); - } - } + addedURLs.add(newURL); } catch (MalformedURLException e) { // Nothing is added } } } - URL[] newURLs = addedURLs.toArray(new URL[] {}); - return newURLs; + return addedURLs; } - /** - * @param in - * InputStream the stream to read lines from - * @return List a list of String lines - */ - private List<String> readLines(InputStream in) throws IOException { - byte[] buff = new byte[144]; - List<String> lines = new ArrayList<String>(); - int pos = 0; - int next; - while ((next = in.read()) != -1) { - if (next == '\n') { - lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$ - pos = 0; - continue; - } - if (next == '\r') { - lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$ - pos = 0; - if ((next = in.read()) == '\n') { - continue; - } - } - if (pos == buff.length) { - byte[] newBuf = new byte[buff.length * 2]; - System.arraycopy(buff, 0, newBuf, 0, buff.length); - buff = newBuf; - } - buff[pos++] = (byte) next; - } - if (pos > 0) { - lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$ + Class<?> findClassImpl(String className) { + Class<?> loadedClass = findLoadedClass(className); + if (null != loadedClass) { + return loadedClass; } - return lines; - } - - private URL targetURL(URL base, String name) throws MalformedURLException { - try { - String file = base.getFile() + URIEncoderDecoder.quoteIllegal(name, - "/@" + URI.someLegal); - - return new URL(base.getProtocol(), base.getHost(), base.getPort(), - file, null); - } catch (UnsupportedEncodingException e) { - MalformedURLException e2 = new MalformedURLException(e.toString()); - - e2.initCause(e); - throw e2; + String partialName = className.replace('.', '/'); + final String classFileName = new StringBuilder(partialName).append(".class").toString(); //$NON-NLS-1$ + String packageName = null; + int position = partialName.lastIndexOf('/'); + if ((position = partialName.lastIndexOf('/')) != -1) { + packageName = partialName.substring(0, position); } - - } - - /** - * @param searchURLs - * java.net.URL[] the URLs to search in - * @param clsName - * java.lang.String the class name to be found - * @return Class the class found or null if not found - */ - Class<?> findClassImpl(URL[] searchURLs, String clsName) { - boolean readAvailable = false; - boolean findInExtensions = searchURLs == urls; - final String name = new StringBuffer(clsName.replace('.', '/')).append( - ".class").toString(); //$NON-NLS-1$ - for (int i = 0; i < searchURLs.length; i++) { - if (searchURLs[i] == null) { - // KA024=One of urls is null - throw new NullPointerException(Msg.getString("KA024")); //$NON-NLS-1$ - } else if (!invalidUrls.contains(searchURLs[i])) { - Manifest manifest = null; - InputStream is = null; - JarEntry entry = null; - JarFile jf = null; - byte[] clBuf = null; - try { - URL thisURL = searchURLs[i]; - String protocol = thisURL.getProtocol(); - if (protocol.equals("jar")) { //$NON-NLS-1$ - jf = resCache.get(thisURL); - if ((jf == null) && (!invalidUrls.contains(thisURL))) { - synchronized (lock) { - // Check the cache again in case another thread updated it - // updated it while we're waiting on lock - jf = resCache.get(thisURL); - if (jf == null) { - if (invalidUrls.contains(thisURL)) { - continue; - } - // If the connection for testURL or thisURL is used, - // getJarFile() will throw an exception if the entry - // doesn't exist. - URL jarURL = ((JarURLConnection) thisURL - .openConnection()).getJarFileURL(); - try { - JarURLConnection juc = (JarURLConnection) new URL( - "jar", "", jarURL.toExternalForm() + "!/") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - .openConnection(); - jf = juc.getJarFile(); - resCache.put(thisURL, jf); - } catch (IOException e) { - // Don't look for this jar file again - invalidUrls.add(searchURLs[i]); - throw e; - } - } - } - } - if (thisURL.getFile().endsWith("!/")) { //$NON-NLS-1$ - entry = jf.getJarEntry(name); - } else { - String file = thisURL.getFile(); - int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$ - if (sepIdx == -1) { - // Invalid URL, don't look here again - invalidUrls.add(searchURLs[i]); - continue; - } - sepIdx += 2; - String entryName = new StringBuffer(file.length() - - sepIdx + name.length()).append( - file.substring(sepIdx)).append(name) - .toString(); - entry = jf.getJarEntry(entryName); - } - if (entry != null) { - readAvailable = true; - is = jf.getInputStream(entry); - /** - * Avoid recursive load class, especially the class - * is an implementation class of security provider - * and the jar is signed. - */ - Class loadedClass = findLoadedClass(clsName); - if (null != loadedClass) { - is.close(); - return loadedClass; - } - manifest = jf.getManifest(); - } - } else if (protocol.equals("file")) { //$NON-NLS-1$ - String filename = thisURL.getFile(); - String host = thisURL.getHost(); - if (host != null && host.length() > 0) { - filename = new StringBuffer(host.length() - + filename.length() + name.length() + 2) - .append("//").append(host).append(filename) //$NON-NLS-1$ - .append(name).toString(); - } else { - filename = new StringBuffer(filename.length() - + name.length()).append(filename).append( - name).toString(); - } - - // Just return null for caller to throw - // ClassNotFoundException. - try { - filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$ - } catch (IllegalArgumentException e) { - return null; - } - - File file = new File(filename); - // Don't throw exceptions for speed - if (file.exists()) { - is = new FileInputStream(file); - readAvailable = true; - } else { - continue; - } - } else { - is = targetURL(thisURL, name).openStream(); - } - } catch (MalformedURLException e) { - // Keep iterating through the URL list - } catch (IOException e) { - } - if (is != null) { - URL codeSourceURL = null; - Certificate[] certificates = null; - CodeSource codeS = null; - try { - codeSourceURL = findInExtensions ? orgUrls[i] - : ((JarURLConnection) searchURLs[i] - .openConnection()).getJarFileURL(); - } catch (IOException e) { - codeSourceURL = searchURLs[i]; - } - if (is != null) { - try { - clBuf = getBytes(is, readAvailable); - is.close(); - } catch (IOException e) { - return null; - } - } - if (entry != null) { - certificates = entry.getCertificates(); - } - // Use the original URL, not the possible jar URL - codeS = new CodeSource(codeSourceURL, certificates); - int dotIndex = clsName.lastIndexOf("."); //$NON-NLS-1$ - if (dotIndex != -1) { - String packageName = clsName.substring(0, dotIndex); - synchronized (this) { - Package packageObj = getPackage(packageName); - if (packageObj == null) { - if (manifest != null) { - definePackage(packageName, manifest, - codeSourceURL); - } else { - definePackage(packageName, null, null, - null, null, null, null, null); - } - } else { - boolean exception = false; - if (manifest != null) { - String dirName = packageName.replace('.', - '/') - + "/"; //$NON-NLS-1$ - if (isSealed(manifest, dirName)) { - exception = !packageObj - .isSealed(codeSourceURL); - } - } else { - exception = packageObj.isSealed(); - } - if (exception) { - throw new SecurityException(Msg - .getString("K004c")); //$NON-NLS-1$ - } - } - } - } - return defineClass(clsName, clBuf, 0, clBuf.length, codeS); - } - if ((jf != null) && findInExtensions) { - if (indexes[i] != null) { - try { - Class<?> c = (Class<?>) findInIndex(i, clsName, - null, false); - if (c != null) { - return c; - } - } catch (InvalidJarIndexException ex) { - // Ignore misleading/wrong jar index - } - } else { - Class<?> c = (Class<?>) findInExtensions(explore( - searchURLs[i], i), clsName, i, null, false); - if (c != null) { - return c; - } - } - } + int n = 0; + while (true) { + URLHandler handler = getHandler(n++); + if (handler == null) { + break; } - } - return null; - } - - /** - * @param url - * URL the URL to explore - * @param indexNumber - * int the index in extensions to consider - * - * @return URL[] the URLs of bundled extensions that have been found (i.e. - * the URL of jar files in the class-path attribute), or null if - * none. if an INDEX.LIST has been found, an empty array is returned - */ - URL[] explore(URL url, int indexNumber) { - URL[] internal; - synchronized (extensions) { - internal = extensions.get(url); - } - if (internal != null) { - return internal; - } - if (indexes[indexNumber] != null) { - return null; - } - - if (!url.getProtocol().equals("jar")) { //$NON-NLS-1$ - return null; - } - - JarFile jf = resCache.get(url); - // Add mappings from INDEX.LIST - ZipEntry ze = jf.getEntry("META-INF/INDEX.LIST"); //$NON-NLS-1$ - if (ze != null) { - if (url.equals(urls[indexNumber])) { - try { - Hashtable<String, URL[]> index = new Hashtable<String, URL[]>( - 15); - InputStream indexIS = jf.getInputStream(ze); - List<String> lines = readLines(indexIS); - indexIS.close(); - ListIterator<String> iterator = lines.listIterator(); - // Ignore the 2 first lines (index version) - iterator.next(); - iterator.next(); - // Add mappings from resource to jar file - URL fileURL = ((JarURLConnection) url.openConnection()) - .getJarFileURL(); - String file = fileURL.getFile(); - String parentFile = new File(file).getParent(); - parentFile = parentFile.replace(File.separatorChar, '/'); - if (parentFile.charAt(0) != '/') { - parentFile = "/" + parentFile; //$NON-NLS-1$ - } - URL parentURL = new URL(fileURL.getProtocol(), fileURL - .getHost(), fileURL.getPort(), parentFile); - while (iterator.hasNext()) { - URL jar = new URL("jar:" //$NON-NLS-1$ - + parentURL.toExternalForm() + "/" //$NON-NLS-1$ - + iterator.next() + "!/"); //$NON-NLS-1$ - String resource = null; - while (iterator.hasNext() - && !(resource = iterator.next()).equals("")) { //$NON-NLS-1$ - if (index.containsKey(resource)) { - URL[] jars = index.get(resource); - URL[] newJars = new URL[jars.length + 1]; - System.arraycopy(jars, 0, newJars, 0, - jars.length); - newJars[jars.length] = jar; - index.put(resource, newJars); - } else { - URL[] jars = { jar }; - index.put(resource, jars); - } - } - } - indexes[indexNumber] = index; - } catch (MalformedURLException e) { - // Ignore this jar's index - } catch (IOException e) { - // Ignore this jar's index - } + Class<?> res = handler.findClass(packageName, classFileName, className); + if (res != null) { + return res; } - return null; } + return null; - // Returns URLs referenced by the class-path attribute. - Manifest manifest = null; - try { - manifest = jf.getManifest(); - } catch (IOException e) { - } - String classpath = null; - if (manifest != null) { - classpath = manifest.getMainAttributes().getValue( - Attributes.Name.CLASS_PATH); - } - synchronized (extensions) { - internal = extensions.get(url); - if (internal == null) { - internal = classpath != null ? getInternalURLs(url, classpath) - : NO_PATH; - extensions.put(url, internal); - } - } - return internal; } + } diff --git a/luni/src/main/java/java/net/URLConnection.java b/luni/src/main/java/java/net/URLConnection.java index 6c1a192..b87b11a 100644 --- a/luni/src/main/java/java/net/URLConnection.java +++ b/luni/src/main/java/java/net/URLConnection.java @@ -23,6 +23,7 @@ import java.io.OutputStream; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collections; +import java.util.Date; import java.util.Hashtable; import java.util.List; import java.util.Map; @@ -31,22 +32,17 @@ import java.util.StringTokenizer; import org.apache.harmony.luni.internal.net.www.MimeTable; import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.PriviAction; -import org.apache.harmony.luni.util.Util; /** * Concrete implementations of the abstract {@code URLConnection} class provide * a communication link to a URL for exchanging data with a specific protocol * type. A {@code URLConnection} can only be set up after the instantiation but * before connecting to the remote resource. - * - * @since Android 1.0 */ public abstract class URLConnection { /** * The URL which represents the remote target of this {@code URLConnection}. - * - * @since Android 1.0 */ protected URL url; @@ -63,16 +59,12 @@ public abstract class URLConnection { /** * The data must be modified more recently than this time in milliseconds * since January 1, 1970, GMT to be transmitted. - * - * @since Android 1.0 */ protected long ifModifiedSince; /** * Specifies whether the using of caches is enabled or the data has to be * recent for every request. - * - * @since Android 1.0 */ protected boolean useCaches = defaultUseCaches; @@ -80,30 +72,22 @@ public abstract class URLConnection { * Specifies whether this {@code URLConnection} is already connected to the * remote resource. If this field is set to {@code true} the flags for * setting up the connection are not changeable anymore. - * - * @since Android 1.0 */ protected boolean connected; /** * Specifies whether this {@code URLConnection} allows sending data. - * - * @since Android 1.0 */ protected boolean doOutput; /** * Specifies whether this {@code URLConnection} allows receiving data. - * - * @since Android 1.0 */ protected boolean doInput = true; /** * Specifies whether this {@code URLConnection} allows user interaction as * it is needed for authentication purposes. - * - * @since Android 1.0 */ protected boolean allowUserInteraction = defaultAllowUserInteraction; @@ -127,11 +111,10 @@ public abstract class URLConnection { /** * Creates a new {@code URLConnection} instance pointing to the resource * specified by the given URL. - * + * * @param url * the URL which represents the resource this {@code * URLConnection} will point to. - * @since Android 1.0 */ protected URLConnection(URL url) { this.url = url; @@ -140,20 +123,18 @@ public abstract class URLConnection { /** * Establishes the connection to the earlier configured resource. The * connection can only be set up before this method has been called. - * + * * @throws IOException * if an error occurs while connecting to the resource. - * @since Android 1.0 */ public abstract void connect() throws IOException; /** * Gets the option value which indicates whether user interaction is allowed * on this {@code URLConnection}. - * + * * @return the value of the option {@code allowUserInteraction}. * @see #allowUserInteraction - * @since Android 1.0 */ public boolean getAllowUserInteraction() { return allowUserInteraction; @@ -166,11 +147,10 @@ public abstract class URLConnection { * header field "Content-Type". If none is found it will guess the content * type from the filename extension. If that fails the stream itself will be * used to guess the content type. - * + * * @return the content representing object. * @throws IOException * if an error occurs obtaining the content. - * @since Android 1.0 */ public Object getContent() throws java.io.IOException { if (!connected) { @@ -196,14 +176,13 @@ public abstract class URLConnection { * type from the filename extension. If that fails the stream itself will be * used to guess the content type. The content type must match with one of * the list {@code types}. - * + * * @param types * the list of acceptable content types. * @return the content representing object or {@code null} if the content * type does not match with one of the specified types. * @throws IOException * if an error occurs obtaining the content. - * @since Android 1.0 */ // Param is not generic in spec @SuppressWarnings("unchecked") @@ -226,9 +205,8 @@ public abstract class URLConnection { /** * Gets the content encoding type specified by the response header field * {@code content-encoding} or {@code null} if this field is not set. - * + * * @return the value of the response header field {@code content-encoding}. - * @since Android 1.0 */ public String getContentEncoding() { return getHeaderField("Content-Encoding"); //$NON-NLS-1$ @@ -237,7 +215,7 @@ public abstract class URLConnection { /** * Returns the specific ContentHandler that will handle the type {@code * contentType}. - * + * * @param type * The type that needs to be handled * @return An instance of the Content Handler @@ -286,7 +264,8 @@ public abstract class URLConnection { .doPrivileged(new PrivilegedAction<Object>() { public Object run() { try { - String className = "org.apache.harmony.luni.internal.net.www.content." //$NON-NLS-1$ + // Try looking up AWT image content handlers + String className = "org.apache.harmony.awt.www.content." //$NON-NLS-1$ + typeString; return Class.forName(className).newInstance(); } catch (ClassNotFoundException e) { @@ -312,9 +291,8 @@ public abstract class URLConnection { /** * Gets the content length in bytes specified by the response header field * {@code content-length} or {@code -1} if this field is not set. - * + * * @return the value of the response header field {@code content-length}. - * @since Android 1.0 */ public int getContentLength() { return getHeaderFieldInt("Content-Length", -1); //$NON-NLS-1$ @@ -323,9 +301,8 @@ public abstract class URLConnection { /** * Gets the MIME-type of the content specified by the response header field * {@code content-type} or {@code null} if type is unknown. - * + * * @return the value of the response header field {@code content-type}. - * @since Android 1.0 */ public String getContentType() { return getHeaderField("Content-Type"); //$NON-NLS-1$ @@ -335,9 +312,8 @@ public abstract class URLConnection { * Gets the timestamp when this response has been sent as a date in * milliseconds since January 1, 1970 GMT or {@code 0} if this timestamp is * unknown. - * + * * @return the sending timestamp of the current response. - * @since Android 1.0 */ public long getDate() { return getHeaderFieldDate("Date", 0); //$NON-NLS-1$ @@ -345,11 +321,10 @@ public abstract class URLConnection { /** * Gets the default setting whether this connection allows user interaction. - * + * * @return the value of the default setting {@code * defaultAllowUserInteraction}. * @see #allowUserInteraction - * @since Android 1.0 */ public static boolean getDefaultAllowUserInteraction() { return defaultAllowUserInteraction; @@ -359,12 +334,11 @@ public abstract class URLConnection { * Gets the default value for the specified request {@code field} or {@code * null} if the field could not be found. The current implementation of this * method returns always {@code null}. - * + * * @param field * the request field whose default value shall be returned. * @return the default value for the given field. * @deprecated Use {@link #getRequestProperty} - * @since Android 1.0 */ @Deprecated public static String getDefaultRequestProperty(String field) { @@ -373,10 +347,9 @@ public abstract class URLConnection { /** * Gets the default setting whether this connection allows using caches. - * + * * @return the value of the default setting {@code defaultUseCaches}. * @see #useCaches - * @since Android 1.0 */ public boolean getDefaultUseCaches() { return defaultUseCaches; @@ -385,11 +358,10 @@ public abstract class URLConnection { /** * Gets the value of the option {@code doInput} which specifies whether this * connection allows to receive data. - * + * * @return {@code true} if this connection allows input, {@code false} * otherwise. * @see #doInput - * @since Android 1.0 */ public boolean getDoInput() { return doInput; @@ -398,11 +370,10 @@ public abstract class URLConnection { /** * Gets the value of the option {@code doOutput} which specifies whether * this connection allows to send data. - * + * * @return {@code true} if this connection allows output, {@code false} * otherwise. * @see #doOutput - * @since Android 1.0 */ public boolean getDoOutput() { return doOutput; @@ -411,9 +382,8 @@ public abstract class URLConnection { /** * Gets the timestamp when this response will be expired in milliseconds * since January 1, 1970 GMT or {@code 0} if this timestamp is unknown. - * + * * @return the value of the response header field {@code expires}. - * @since Android 1.0 */ public long getExpiration() { return getHeaderFieldDate("Expires", 0); //$NON-NLS-1$ @@ -422,9 +392,8 @@ public abstract class URLConnection { /** * Gets the table which is used by all {@code URLConnection} instances to * determine the MIME-type according to a file extension. - * + * * @return the file name map to determine the MIME-type. - * @since Android 1.0 */ public static FileNameMap getFileNameMap() { // Must use lazy initialization or there is a bootstrap problem @@ -440,11 +409,10 @@ public abstract class URLConnection { * Gets the header value at the field position {@code pos} or {@code null} * if the header has fewer than {@code pos} fields. The current * implementation of this method returns always {@code null}. - * + * * @param pos * the field position of the response header. * @return the value of the field at position {@code pos}. - * @since Android 1.0 */ public String getHeaderField(int pos) { return null; @@ -454,9 +422,9 @@ public abstract class URLConnection { * Gets an unchangeable map of the response-header fields and values. The * response-header field names are the key values of the map. The map values * are lists of header field values associated with a particular key name. - * + * * @return the response-header representing generic map. - * @since Android 1.0 + * @since 1.4 */ public Map<String, List<String>> getHeaderFields() { return Collections.emptyMap(); @@ -466,9 +434,9 @@ public abstract class URLConnection { * Gets an unchangeable map of general request properties used by this * connection. The request property names are the key values of the map. The * map values are lists of property values of the corresponding key name. - * + * * @return the request-property representing generic map. - * @since Android 1.0 + * @since 1.4 */ public Map<String, List<String>> getRequestProperties() { if (connected) { @@ -480,7 +448,7 @@ public abstract class URLConnection { /** * Adds the given property to the request header. Existing properties with * the same name will not be overwritten by this method. - * + * * @param field * the request property field name to add. * @param newValue @@ -489,7 +457,7 @@ public abstract class URLConnection { * if the connection has been already established. * @throws NullPointerException * if the property name is {@code null}. - * @since Android 1.0 + * @since 1.4 */ public void addRequestProperty(String field, String newValue) { if (connected) { @@ -504,11 +472,10 @@ public abstract class URLConnection { * Gets the value of the header field specified by {@code key} or {@code * null} if there is no field with this name. The current implementation of * this method returns always {@code null}. - * + * * @param key * the name of the header field. * @return the value of the header field. - * @since Android 1.0 */ public String getHeaderField(String key) { return null; @@ -518,34 +485,37 @@ public abstract class URLConnection { * Gets the specified header value as a date in milliseconds since January * 1, 1970 GMT. Returns the {@code defaultValue} if no such header field * could be found. - * + * * @param field * the header field name whose value is needed. * @param defaultValue * the default value if no field has been found. * @return the value of the specified header field as a date in * milliseconds. - * @since Android 1.0 */ + @SuppressWarnings("deprecation") public long getHeaderFieldDate(String field, long defaultValue) { String date = getHeaderField(field); if (date == null) { return defaultValue; } - return Util.parseDate(date); + try { + return Date.parse(date); + } catch (Exception e) { + return defaultValue; + } } /** * Gets the specified header value as a number. Returns the {@code * defaultValue} if no such header field could be found or the value could * not be parsed as an {@code Integer}. - * + * * @param field * the header field name whose value is needed. * @param defaultValue * the default value if no field has been found. * @return the value of the specified header field as a number. - * @since Android 1.0 */ public int getHeaderFieldInt(String field, int defaultValue) { try { @@ -559,11 +529,10 @@ public abstract class URLConnection { * Gets the name of the header field at the given position {@code posn} or * {@code null} if there are fewer than {@code posn} fields. The current * implementation of this method returns always {@code null}. - * + * * @param posn * the position of the header field which has to be returned. * @return the header field name at the given position. - * @since Android 1.0 */ public String getHeaderFieldKey(int posn) { return null; @@ -573,10 +542,9 @@ public abstract class URLConnection { * Gets the point of time since when the data must be modified to be * transmitted. Some protocols transmit data only if it has been modified * more recently than a particular time. - * + * * @return the time in milliseconds since January 1, 1970 GMT. * @see #ifModifiedSince - * @since Android 1.0 */ public long getIfModifiedSince() { return ifModifiedSince; @@ -586,11 +554,10 @@ public abstract class URLConnection { * Gets an {@code InputStream} for reading data from the resource pointed by * this {@code URLConnection}. It throws an UnknownServiceException by * default. This method must be overridden by its subclasses. - * + * * @return the InputStream to read data from. * @throws IOException * if no InputStream could be created. - * @since Android 1.0 */ public InputStream getInputStream() throws IOException { throw new UnknownServiceException(Msg.getString("K004d")); //$NON-NLS-1$ @@ -599,9 +566,8 @@ public abstract class URLConnection { /** * Gets the value of the response header field {@code last-modified} or * {@code 0} if this value is not set. - * + * * @return the value of the {@code last-modified} header field. - * @since Android 1.0 */ public long getLastModified() { if (lastModified != -1) { @@ -614,11 +580,10 @@ public abstract class URLConnection { * Gets an {@code OutputStream} for writing data to this {@code * URLConnection}. It throws an {@code UnknownServiceException} by default. * This method must be overridden by its subclasses. - * + * * @return the OutputStream to write data. * @throws IOException * if no OutputStream could be created. - * @since Android 1.0 */ public OutputStream getOutputStream() throws IOException { throw new UnknownServiceException(Msg.getString("K005f")); //$NON-NLS-1$ @@ -631,12 +596,11 @@ public abstract class URLConnection { * necessary. By default, this method returns {@code AllPermission}. * Subclasses should overwrite this method to return an appropriate * permission object. - * + * * @return the permission object representing the needed permissions to open * this connection. * @throws IOException * if an I/O error occurs while creating the permission object. - * @since Android 1.0 */ public java.security.Permission getPermission() throws IOException { return new java.security.AllPermission(); @@ -646,13 +610,12 @@ public abstract class URLConnection { * Gets the value of the request header property specified by {code field} * or {@code null} if there is no field with this name. The current * implementation of this method returns always {@code null}. - * + * * @param field * the name of the request header property. * @return the value of the property. * @throws IllegalStateException * if the connection has been already established. - * @since Android 1.0 */ public String getRequestProperty(String field) { if (connected) { @@ -663,9 +626,8 @@ public abstract class URLConnection { /** * Gets the URL represented by this {@code URLConnection}. - * + * * @return the URL of this connection. - * @since Android 1.0 */ public URL getURL() { return url; @@ -674,9 +636,8 @@ public abstract class URLConnection { /** * Gets the value of the flag which specifies whether this {@code * URLConnection} allows to use caches. - * + * * @return {@code true} if using caches is allowed, {@code false} otherwise. - * @since Android 1.0 */ public boolean getUseCaches() { return useCaches; @@ -686,12 +647,11 @@ public abstract class URLConnection { * Determines the MIME-type of the given resource {@code url} by resolving * the filename extension with the internal FileNameMap. Any fragment * identifier is removed before processing. - * + * * @param url * the URL with the filename to get the MIME type. * @return the guessed content type or {@code null} if the type could not be * determined. - * @since Android 1.0 */ public static String guessContentTypeFromName(String url) { return getFileNameMap().getContentTypeFor(url); @@ -700,7 +660,7 @@ public abstract class URLConnection { /** * Determines the MIME-type of the resource represented by the input stream * {@code is} by reading its first few characters. - * + * * @param is * the resource representing input stream to determine the * content type. @@ -708,35 +668,91 @@ public abstract class URLConnection { * determined. * @throws IOException * if an I/O error occurs while reading from the input stream. - * @since Android 1.0 */ + @SuppressWarnings("nls") public static String guessContentTypeFromStream(InputStream is) throws IOException { + if (!is.markSupported()) { return null; } - is.mark(4); - char[] chars = new char[4]; - for (int i = 0; i < chars.length; i++) { - chars[i] = (char) is.read(); - } + // Look ahead up to 64 bytes for the longest encoded header + is.mark(64); + byte[] bytes = new byte[64]; + int length = is.read(bytes); is.reset(); - if ((chars[0] == 'P') && (chars[1] == 'K')) { - return "application/zip"; //$NON-NLS-1$ + + // Check for Unicode BOM encoding indicators + String encoding = "ASCII"; + int start = 0; + if (length > 1) { + if ((bytes[0] == (byte) 0xFF) && (bytes[1] == (byte) 0xFE)) { + encoding = "UTF-16LE"; + start = 2; + length -= length & 1; + } + if ((bytes[0] == (byte) 0xFE) && (bytes[1] == (byte) 0xFF)) { + encoding = "UTF-16BE"; + start = 2; + length -= length & 1; + } + if (length > 2) { + if ((bytes[0] == (byte) 0xEF) && (bytes[1] == (byte) 0xBB) + && (bytes[2] == (byte) 0xBF)) { + encoding = "UTF-8"; + start = 3; + } + if (length > 3) { + if ((bytes[0] == (byte) 0x00) && (bytes[1] == (byte) 0x00) + && (bytes[2] == (byte) 0xFE) + && (bytes[3] == (byte) 0xFF)) { + encoding = "UTF-32BE"; + start = 4; + length -= length & 3; + } + if ((bytes[0] == (byte) 0xFF) && (bytes[1] == (byte) 0xFE) + && (bytes[2] == (byte) 0x00) + && (bytes[3] == (byte) 0x00)) { + encoding = "UTF-32LE"; + start = 4; + length -= length & 3; + } + } + } } - if ((chars[0] == 'G') && (chars[1] == 'I')) { - return "image/gif"; //$NON-NLS-1$ + + String header = new String(bytes, start, length - start, encoding); + + // Check binary types + if (header.startsWith("PK")) { + return "application/zip"; } - if (new String(chars).trim().startsWith("<")) { //$NON-NLS-1$ - return "text/html"; //$NON-NLS-1$ + if (header.startsWith("GI")) { + return "image/gif"; } + + // Check text types + String textHeader = header.trim().toUpperCase(); + if (textHeader.startsWith("<!DOCTYPE HTML") || + textHeader.startsWith("<HTML") || + textHeader.startsWith("<HEAD") || + textHeader.startsWith("<BODY") || + textHeader.startsWith("<HEAD")) { + return "text/html"; + } + + if (textHeader.startsWith("<?XML")) { + return "application/xml"; + } + + // Give up return null; } /** * Performs any necessary string parsing on the input string such as * converting non-alphanumeric character into underscore. - * + * * @param typeString * the parsed string * @return the string to be parsed @@ -757,14 +773,13 @@ public abstract class URLConnection { * Sets the flag indicating whether this connection allows user interaction * or not. This method can only be called prior to the connection * establishment. - * + * * @param newValue * the value of the flag to be set. * @throws IllegalStateException * if this method attempts to change the flag after the * connection has been established. * @see #allowUserInteraction - * @since Android 1.0 */ public void setAllowUserInteraction(boolean newValue) { if (connected) { @@ -777,13 +792,12 @@ public abstract class URLConnection { * Sets the internally used content handler factory. The content factory can * only be set if it is allowed by the security manager and only once during * the lifetime of the application. - * + * * @param contentFactory * the content factory to be set. * @throws Error * if the security manager does not allow to set the content * factory or it has been already set earlier ago. - * @since Android 1.0 */ public static synchronized void setContentHandlerFactory( ContentHandlerFactory contentFactory) { @@ -801,12 +815,11 @@ public abstract class URLConnection { * Sets the default value for the flag indicating whether this connection * allows user interaction or not. Existing {@code URLConnection}s are * unaffected. - * + * * @param allows * the default value of the flag to be used for new connections. * @see #defaultAllowUserInteraction * @see #allowUserInteraction - * @since Android 1.0 */ public static void setDefaultAllowUserInteraction(boolean allows) { defaultAllowUserInteraction = allows; @@ -816,14 +829,13 @@ public abstract class URLConnection { * Sets the default value of the specified request header field. This value * will be used for the specific field of every newly created connection. * The current implementation of this method does nothing. - * + * * @param field * the request header field to be set. * @param value * the default value to be used. * @deprecated Use {@link #setRequestProperty} of an existing {@code * URLConnection} instance. - * @since Android 1.0 */ @Deprecated public static void setDefaultRequestProperty(String field, String value) { @@ -832,12 +844,11 @@ public abstract class URLConnection { /** * Sets the default value for the flag indicating whether this connection * allows to use caches. Existing {@code URLConnection}s are unaffected. - * + * * @param newValue * the default value of the flag to be used for new connections. * @see #defaultUseCaches * @see #useCaches - * @since Android 1.0 */ public void setDefaultUseCaches(boolean newValue) { // BEGIN android-removed @@ -852,14 +863,13 @@ public abstract class URLConnection { /** * Sets the flag indicating whether this {@code URLConnection} allows input. * It cannot be set after the connection is established. - * + * * @param newValue * the new value for the flag to be set. * @throws IllegalAccessError * if this method attempts to change the value after the * connection has been already established. * @see #doInput - * @since Android 1.0 */ public void setDoInput(boolean newValue) { if (connected) { @@ -871,14 +881,13 @@ public abstract class URLConnection { /** * Sets the flag indicating whether this {@code URLConnection} allows * output. It cannot be set after the connection is established. - * + * * @param newValue * the new value for the flag to be set. * @throws IllegalAccessError * if this method attempts to change the value after the * connection has been already established. * @see #doOutput - * @since Android 1.0 */ public void setDoOutput(boolean newValue) { if (connected) { @@ -890,10 +899,9 @@ public abstract class URLConnection { /** * Sets the internal map which is used by all {@code URLConnection} * instances to determine the MIME-type according to a filename extension. - * + * * @param map * the MIME table to be set. - * @since Android 1.0 */ public static void setFileNameMap(FileNameMap map) { SecurityManager manager = System.getSecurityManager(); @@ -908,13 +916,12 @@ public abstract class URLConnection { * transmitted. Some protocols transmit data only if it has been modified * more recently than a particular time. The data will be transmitted * regardless of its timestamp if this option is set to {@code 0}. - * + * * @param newValue * the time in milliseconds since January 1, 1970 GMT. * @throws IllegalStateException * if this {@code URLConnection} has already been connected. * @see #ifModifiedSince - * @since Android 1.0 */ public void setIfModifiedSince(long newValue) { if (connected) { @@ -927,7 +934,7 @@ public abstract class URLConnection { * Sets the value of the specified request header field. The value will only * be used by the current {@code URLConnection} instance. This method can * only be called before the connection is established. - * + * * @param field * the request header field to be set. * @param newValue @@ -936,7 +943,6 @@ public abstract class URLConnection { * if the connection has been already established. * @throws NullPointerException * if the parameter {@code field} is {@code null}. - * @since Android 1.0 */ public void setRequestProperty(String field, String newValue) { if (connected) { @@ -951,14 +957,13 @@ public abstract class URLConnection { * Sets the flag indicating whether this connection allows to use caches or * not. This method can only be called prior to the connection * establishment. - * + * * @param newValue * the value of the flag to be set. * @throws IllegalStateException * if this method attempts to change the flag after the * connection has been established. * @see #useCaches - * @since Android 1.0 */ public void setUseCaches(boolean newValue) { if (connected) { @@ -973,12 +978,11 @@ public abstract class URLConnection { * SocketTimeoutException} is thrown if the connection could not be * established in this time. Default is {@code 0} which stands for an * infinite timeout. - * + * * @param timeout * the connecting timeout in milliseconds. * @throws IllegalArgumentException * if the parameter {@code timeout} is less than zero. - * @since Android 1.0 */ public void setConnectTimeout(int timeout) { if (0 > timeout) { @@ -989,9 +993,8 @@ public abstract class URLConnection { /** * Gets the configured connecting timeout. - * + * * @return the connecting timeout value in milliseconds. - * @since Android 1.0 */ public int getConnectTimeout() { return connectTimeout; @@ -1003,12 +1006,11 @@ public abstract class URLConnection { * SocketTimeoutException} is thrown if the connection could not be * established in this time. Default is {@code 0} which stands for an * infinite timeout. - * + * * @param timeout * the reading timeout in milliseconds. * @throws IllegalArgumentException * if the parameter {@code timeout} is less than zero. - * @since Android 1.0 */ public void setReadTimeout(int timeout) { if (0 > timeout) { @@ -1020,9 +1022,8 @@ public abstract class URLConnection { /** * Gets the configured timeout for reading from the input stream of an * established connection to the resource. - * + * * @return the reading timeout value in milliseconds. - * @since Android 1.0 */ public int getReadTimeout() { return readTimeout; @@ -1031,9 +1032,8 @@ public abstract class URLConnection { /** * Returns the string representation containing the name of this class and * the URL. - * + * * @return the string representation of this {@code URLConnection} instance. - * @since Android 1.0 */ @Override public String toString() { diff --git a/luni/src/main/java/java/net/URLDecoder.java b/luni/src/main/java/java/net/URLDecoder.java index d272aa7..fd2753c 100644 --- a/luni/src/main/java/java/net/URLDecoder.java +++ b/luni/src/main/java/java/net/URLDecoder.java @@ -17,20 +17,23 @@ package java.net; -import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; import org.apache.harmony.luni.util.Msg; -import org.apache.harmony.luni.util.Util; /** * This class is used to decode a string which is encoded in the {@code * application/x-www-form-urlencoded} MIME content type. - * - * @since Android 1.0 */ public class URLDecoder { + static Charset defaultCharset; + /** * Decodes the argument which is assumed to be encoded in the {@code * x-www-form-urlencoded} MIME content type. @@ -39,19 +42,32 @@ public class URLDecoder { * characters are converted to the equivalent byte value. All other * characters are passed through unmodified. For example "A+B+C %24%25" -> * "A B C $%". - * </p> - * + * * @param s * the encoded string. * @return the decoded clear-text representation of the given string. * @deprecated use {@link #decode(String, String)} instead. - * @since Android 1.0 */ @Deprecated public static String decode(String s) { - return Util.decode(s, true); + + if (defaultCharset == null) { + try { + defaultCharset = Charset.forName( + System.getProperty("file.encoding")); //$NON-NLS-1$ + } catch (IllegalCharsetNameException e) { + // Ignored + } catch (UnsupportedCharsetException e) { + // Ignored + } + + if (defaultCharset == null) { + defaultCharset = Charset.forName("ISO-8859-1"); //$NON-NLS-1$ + } + } + return decode(s, defaultCharset); } - + /** * Decodes the argument which is assumed to be encoded in the {@code * x-www-form-urlencoded} MIME content type using the specified encoding @@ -61,8 +77,7 @@ public class URLDecoder { * characters are converted to the equivalent byte value. All other * characters are passed through unmodified. For example "A+B+C %24%25" -> * "A B C $%". - * </p> - * + * * @param s * the encoded string. * @param enc @@ -70,7 +85,6 @@ public class URLDecoder { * @return the decoded clear-text representation of the given string. * @throws UnsupportedEncodingException * if the specified encoding scheme is invalid. - * @since Android 1.0 */ public static String decode(String s, String enc) throws UnsupportedEncodingException { @@ -81,40 +95,80 @@ public class URLDecoder { // If the given encoding is an empty string throw an exception. if (enc.length() == 0) { - throw new UnsupportedEncodingException(Msg - .getString("K00a5", "enc")); //$NON-NLS-1$ //$NON-NLS-2$ + throw new UnsupportedEncodingException( + // K00a5=Invalid parameter - {0} + Msg.getString("K00a5", "enc")); //$NON-NLS-1$ //$NON-NLS-2$ + } + + if (s.indexOf('%') == -1) { + if (s.indexOf('+') == -1) + return s; + char str[] = s.toCharArray(); + for (int i = 0; i < str.length; i++) { + if (str[i] == '+') + str[i] = ' '; + } + return new String(str); + } + + Charset charset = null; + try { + charset = Charset.forName(enc); + } catch (IllegalCharsetNameException e) { + throw (UnsupportedEncodingException) (new UnsupportedEncodingException( + enc).initCause(e)); + } catch (UnsupportedCharsetException e) { + throw (UnsupportedEncodingException) (new UnsupportedEncodingException( + enc).initCause(e)); } - StringBuffer result = new StringBuffer(s.length()); - ByteArrayOutputStream out = new ByteArrayOutputStream(); + return decode(s, charset); + } + + private static String decode(String s, Charset charset) { + + char str_buf[] = new char[s.length()]; + byte buf[] = new byte[s.length() / 3]; + int buf_len = 0; + for (int i = 0; i < s.length();) { char c = s.charAt(i); if (c == '+') { - result.append(' '); + str_buf[buf_len] = ' '; } else if (c == '%') { - out.reset(); + + int len = 0; do { if (i + 2 >= s.length()) { - throw new IllegalArgumentException(Msg.getString( - "K01fe", i)); //$NON-NLS-1$ + throw new IllegalArgumentException( + // K01fe=Incomplete % sequence at\: {0} + Msg.getString("K01fe", i)); //$NON-NLS-1$ } int d1 = Character.digit(s.charAt(i + 1), 16); int d2 = Character.digit(s.charAt(i + 2), 16); if (d1 == -1 || d2 == -1) { - throw new IllegalArgumentException(Msg.getString( - "K01ff", //$NON-NLS-1$ - s.substring(i, i + 3), String.valueOf(i))); + throw new IllegalArgumentException( + // K01ff=Invalid % sequence ({0}) at\: {1} + Msg.getString( + "K01ff", //$NON-NLS-1$ + s.substring(i, i + 3), + String.valueOf(i))); } - out.write((byte) ((d1 << 4) + d2)); + buf[len++] = (byte) ((d1 << 4) + d2); i += 3; } while (i < s.length() && s.charAt(i) == '%'); - result.append(out.toString(enc)); + + CharBuffer cb = charset.decode(ByteBuffer.wrap(buf, 0, len)); + len = cb.length(); + System.arraycopy(cb.array(), 0, str_buf, buf_len, len); + buf_len += len; continue; } else { - result.append(c); + str_buf[buf_len] = c; } i++; + buf_len++; } - return result.toString(); + return new String(str_buf, 0, buf_len); } } diff --git a/luni/src/main/java/java/net/URLEncoder.java b/luni/src/main/java/java/net/URLEncoder.java index 69f2d37..2c21aa6 100644 --- a/luni/src/main/java/java/net/URLEncoder.java +++ b/luni/src/main/java/java/net/URLEncoder.java @@ -22,8 +22,6 @@ import java.io.UnsupportedEncodingException; /** * This class is used to encode a string using the format required by * {@code application/x-www-form-urlencoded} MIME content type. - * - * @since Android 1.0 */ public class URLEncoder { @@ -43,13 +41,11 @@ public class URLEncoder { * and characters '.', '-', '*', '_' are converted into their hexadecimal * value prepended by '%'. For example: '#' -> %23. In addition, spaces are * substituted by '+' - * </p> - * + * * @param s * the string to be encoded. * @return the encoded string. * @deprecated use {@link #encode(String, String)} instead. - * @since Android 1.0 */ @Deprecated public static String encode(String s) { @@ -81,8 +77,7 @@ public class URLEncoder { * and characters '.', '-', '*', '_' are converted into their hexadecimal * value prepended by '%'. For example: '#' -> %23. In addition, spaces are * substituted by '+' - * </p> - * + * * @param s * the string to be encoded. * @param enc @@ -90,10 +85,10 @@ public class URLEncoder { * @return the encoded string. * @throws UnsupportedEncodingException * if the specified encoding scheme is invalid. - * @since Android 1.0 */ public static String encode(String s, String enc) throws UnsupportedEncodingException { + if (s == null || enc == null) { throw new NullPointerException(); } diff --git a/luni/src/main/java/java/net/URLStreamHandler.java b/luni/src/main/java/java/net/URLStreamHandler.java index f05c8bd..f039b00 100644 --- a/luni/src/main/java/java/net/URLStreamHandler.java +++ b/luni/src/main/java/java/net/URLStreamHandler.java @@ -26,11 +26,8 @@ import org.apache.harmony.luni.util.URLUtil; * The abstract class {@code URLStreamHandler} is the base for all classes which * can handle the communication with a URL object over a particular protocol * type. - * - * @since Android 1.0 */ public abstract class URLStreamHandler { - /** * Establishes a new connection to the resource specified by the URL {@code * u}. Since different protocols also have unique ways of connecting, it @@ -41,7 +38,6 @@ public abstract class URLStreamHandler { * @return the opened URLConnection to the specified resource. * @throws IOException * if an I/O error occurs during opening the connection. - * @since Android 1.0 */ protected abstract URLConnection openConnection(URL u) throws IOException; @@ -62,7 +58,6 @@ public abstract class URLStreamHandler { * wrong. * @throws UnsupportedOperationException * if the protocol handler doesn't support this method. - * @since Android 1.0 */ protected URLConnection openConnection(URL u, Proxy proxy) throws IOException { @@ -74,7 +69,7 @@ public abstract class URLStreamHandler { * generally have the following format: * <p> * http://www.company.com/java/file1.java#reference - * </p> + * <p> * The string is parsed in HTTP format. If the protocol has a different URL * format this method must be overridden. * @@ -88,7 +83,6 @@ public abstract class URLStreamHandler { * the string position to stop parsing. * @see #toExternalForm * @see URL - * @since Android 1.0 */ protected void parseURL(URL u, String str, int start, int end) { // For compatibility, refer to Harmony-2941 @@ -259,7 +253,6 @@ public abstract class URLStreamHandler { * the reference. * @deprecated use setURL(URL, String String, int, String, String, String, * String, String) instead. - * @since Android 1.0 */ @Deprecated protected void setURL(URL u, String protocol, String host, int port, @@ -292,7 +285,6 @@ public abstract class URLStreamHandler { * the query. * @param ref * the reference. - * @since Android 1.0 */ protected void setURL(URL u, String protocol, String host, int port, String authority, String userInfo, String file, String query, @@ -311,7 +303,6 @@ public abstract class URLStreamHandler { * @return the clear text representation of the specified URL. * @see #parseURL * @see URL#toExternalForm() - * @since Android 1.0 */ protected String toExternalForm(URL url) { StringBuffer answer = new StringBuffer(url.getProtocol().length() @@ -346,7 +337,6 @@ public abstract class URLStreamHandler { * the second URL to compare. * @return {@code true} if the URLs are the same, {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ protected boolean equals(URL url1, URL url2) { if (!sameFile(url1, url2)) { @@ -364,9 +354,8 @@ public abstract class URLStreamHandler { /** * Returns the default port of the protocol used by the handled URL. The * current implementation returns always {@code -1}. - * + * * @return the appropriate default port number of the protocol. - * @since Android 1.0 */ protected int getDefaultPort() { return -1; @@ -374,11 +363,10 @@ public abstract class URLStreamHandler { /** * Returns the host address of the given URL. - * + * * @param url * the URL object where to read the host address from. * @return the host address of the specified URL. - * @since Android 1.0 */ protected InetAddress getHostAddress(URL url) { try { @@ -398,7 +386,6 @@ public abstract class URLStreamHandler { * @param url * the URL to determine the hashcode. * @return the hashcode of the given URL. - * @since Android 1.0 */ protected int hashCode(URL url) { return toExternalForm(url).hashCode(); @@ -406,14 +393,13 @@ public abstract class URLStreamHandler { /** * Compares two URL objects whether they refer to the same host. - * + * * @param url1 * the first URL to be compared. * @param url2 * the second URL to be compared. * @return {@code true} if both URLs refer to the same host, {@code false} * otherwise. - * @since Android 1.0 */ protected boolean hostsEqual(URL url1, URL url2) { String host1 = getHost(url1), host2 = getHost(url2); @@ -439,7 +425,6 @@ public abstract class URLStreamHandler { * the second URL to be compared. * @return {@code true} if both URLs refer to the same file, {@code false} * otherwise. - * @since Android 1.0 */ protected boolean sameFile(URL url1, URL url2) { String s1 = url1.getProtocol(); diff --git a/luni/src/main/java/java/net/URLStreamHandlerFactory.java b/luni/src/main/java/java/net/URLStreamHandlerFactory.java index e696410..4e50792 100644 --- a/luni/src/main/java/java/net/URLStreamHandlerFactory.java +++ b/luni/src/main/java/java/net/URLStreamHandlerFactory.java @@ -20,11 +20,9 @@ package java.net; /** * Defines a factory which creates an {@code URLStreamHandler} for a specified * protocol. It is used by the class {@code URL}. - * - * @since Android 1.0 */ public interface URLStreamHandlerFactory { - + /** * Creates a new {@code URLStreamHandler} instance for the given {@code * protocol}. @@ -32,7 +30,6 @@ public interface URLStreamHandlerFactory { * @param protocol * the protocol for which a handler is needed. * @return the created handler. - * @since Android 1.0 */ URLStreamHandler createURLStreamHandler(String protocol); } diff --git a/luni/src/main/java/java/net/UnknownHostException.java b/luni/src/main/java/java/net/UnknownHostException.java index 9f7c63a..db05558 100644 --- a/luni/src/main/java/java/net/UnknownHostException.java +++ b/luni/src/main/java/java/net/UnknownHostException.java @@ -21,8 +21,6 @@ import java.io.IOException; /** * Is thrown when a hostname can not be resolved. - * - * @since Android 1.0 */ public class UnknownHostException extends IOException { @@ -31,8 +29,6 @@ public class UnknownHostException extends IOException { /** * Constructs a new {@code UnknownHostException} instance with its walkback * filled in. - * - * @since Android 1.0 */ public UnknownHostException() { super(); @@ -44,7 +40,6 @@ public class UnknownHostException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public UnknownHostException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/net/UnknownServiceException.java b/luni/src/main/java/java/net/UnknownServiceException.java index 4865d6d..6ad2a19 100644 --- a/luni/src/main/java/java/net/UnknownServiceException.java +++ b/luni/src/main/java/java/net/UnknownServiceException.java @@ -24,8 +24,6 @@ import java.io.IOException; * particular service requested by the URL connection. This could be happened if * there is an invalid MIME type or the application wants to send data over a * read-only connection. - * - * @since Android 1.0 */ public class UnknownServiceException extends IOException { @@ -34,8 +32,6 @@ public class UnknownServiceException extends IOException { /** * Constructs a new {@code UnknownServiceException} instance with its * walkback filled in. - * - * @since Android 1.0 */ public UnknownServiceException() { super(); @@ -47,7 +43,6 @@ public class UnknownServiceException extends IOException { * * @param detailMessage * the detail message for this exception. - * @since Android 1.0 */ public UnknownServiceException(String detailMessage) { super(detailMessage); diff --git a/luni/src/main/java/java/util/AbstractCollection.java b/luni/src/main/java/java/util/AbstractCollection.java index 9f26445..6511b11 100644 --- a/luni/src/main/java/java/util/AbstractCollection.java +++ b/luni/src/main/java/java/util/AbstractCollection.java @@ -17,7 +17,6 @@ package java.util; - import java.lang.reflect.Array; /** @@ -26,23 +25,18 @@ import java.lang.reflect.Array; * iterator()} and {@code size()} to create an immutable collection. To create a * modifiable collection it's necessary to override the {@code add()} method that * currently throws an {@code UnsupportedOperationException}. - * - * @since Android 1.0 + * + * @since 1.2 */ public abstract class AbstractCollection<E> implements Collection<E> { /** - * Constructs a new instance of this {@code AbstractCollection}. - * - * @since Android 1.0 + * Constructs a new instance of this AbstractCollection. */ protected AbstractCollection() { super(); } - /** - * @see Collection#add - */ public boolean add(E object) { throw new UnsupportedOperationException(); } @@ -64,18 +58,17 @@ public abstract class AbstractCollection<E> implements Collection<E> { * the collection of objects. * @return {@code true} if this {@code Collection} is modified, {@code false} * otherwise. - * @exception UnsupportedOperationException - * when adding to this {@code Collection} is not supported. - * @exception ClassCastException - * when the class of an object is inappropriate for this + * @throws UnsupportedOperationException + * if adding to this {@code Collection} is not supported. + * @throws ClassCastException + * if the class of an object is inappropriate for this * {@code Collection}. - * @exception IllegalArgumentException - * when an object cannot be added to this {@code Collection}. - * @exception NullPointerException - * when {@code collection} is {@code null}, or if it contains + * @throws IllegalArgumentException + * if an object cannot be added to this {@code Collection}. + * @throws NullPointerException + * if {@code collection} is {@code null}, or if it contains * {@code null} elements and this {@code Collection} does not support * such elements. - * @since Android 1.0 */ public boolean addAll(Collection<? extends E> collection) { boolean result = false; @@ -97,13 +90,12 @@ public abstract class AbstractCollection<E> implements Collection<E> { * Concrete implementations usually can clear a {@code Collection} more efficiently * and should therefore overwrite this method. * - * @exception UnsupportedOperationException - * when the iterator does not support removing elements from + * @throws UnsupportedOperationException + * it the iterator does not support removing elements from * this {@code Collection} * @see #iterator * @see #isEmpty * @see #size - * @since Android 1.0 */ public void clear() { Iterator<E> it = iterator(); @@ -126,12 +118,11 @@ public abstract class AbstractCollection<E> implements Collection<E> { * the object to search for. * @return {@code true} if object is an element of this {@code Collection}, {@code * false} otherwise. - * @exception ClassCastException + * @throws ClassCastException * if the object to look for isn't of the correct type. - * @exception NullPointerException + * @throws NullPointerException * if the object to look for is {@code null} and this * {@code Collection} doesn't support {@code null} elements. - * @since Android 1.0 */ public boolean contains(Object object) { Iterator<E> it = iterator(); @@ -161,16 +152,15 @@ public abstract class AbstractCollection<E> implements Collection<E> { * the collection of objects. * @return {@code true} if all objects in the specified {@code Collection} are * elements of this {@code Collection}, {@code false} otherwise. - * @exception ClassCastException + * @throws ClassCastException * if one or more elements of {@code collection} isn't of the * correct type. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} contains at least one {@code null} * element and this {@code Collection} doesn't support {@code null} * elements. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} is {@code null}. - * @since Android 1.0 */ public boolean containsAll(Collection<?> collection) { Iterator<?> it = collection.iterator(); @@ -188,9 +178,8 @@ public abstract class AbstractCollection<E> implements Collection<E> { * * @return {@code true} if this {@code Collection} has no elements, {@code false} * otherwise. - * + * * @see #size - * @since Android 1.0 */ public boolean isEmpty() { return size() == 0; @@ -206,7 +195,6 @@ public abstract class AbstractCollection<E> implements Collection<E> { * by concrete {@code Collection} implementations. * * @return an iterator for accessing the {@code Collection} contents. - * @since Android 1.0 */ public abstract Iterator<E> iterator(); @@ -226,14 +214,13 @@ public abstract class AbstractCollection<E> implements Collection<E> { * the object to remove. * @return {@code true} if this {@code Collection} is modified, {@code false} * otherwise. - * @exception UnsupportedOperationException - * when removing from this {@code Collection} is not supported. - * @exception ClassCastException - * when the object passed is not of the correct type. - * @exception NullPointerException + * @throws UnsupportedOperationException + * if removing from this {@code Collection} is not supported. + * @throws ClassCastException + * if the object passed is not of the correct type. + * @throws NullPointerException * if {@code object} is {@code null} and this {@code Collection} * doesn't support {@code null} elements. - * @since Android 1.0 */ public boolean remove(Object object) { Iterator<?> it = iterator(); @@ -272,18 +259,17 @@ public abstract class AbstractCollection<E> implements Collection<E> { * the collection of objects to remove. * @return {@code true} if this {@code Collection} is modified, {@code false} * otherwise. - * @exception UnsupportedOperationException - * when removing from this {@code Collection} is not supported. - * @exception ClassCastException + * @throws UnsupportedOperationException + * if removing from this {@code Collection} is not supported. + * @throws ClassCastException * if one or more elements of {@code collection} isn't of the * correct type. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} contains at least one {@code null} * element and this {@code Collection} doesn't support {@code null} * elements. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} is {@code null}. - * @since Android 1.0 */ public boolean removeAll(Collection<?> collection) { boolean result = false; @@ -314,18 +300,17 @@ public abstract class AbstractCollection<E> implements Collection<E> { * the collection of objects to retain. * @return {@code true} if this {@code Collection} is modified, {@code false} * otherwise. - * @exception UnsupportedOperationException - * when removing from this {@code Collection} is not supported. - * @exception ClassCastException + * @throws UnsupportedOperationException + * if removing from this {@code Collection} is not supported. + * @throws ClassCastException * if one or more elements of {@code collection} * isn't of the correct type. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} contains at least one * {@code null} element and this {@code Collection} doesn't support * {@code null} elements. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} is {@code null}. - * @since Android 1.0 */ public boolean retainAll(Collection<?> collection) { boolean result = false; @@ -348,7 +333,6 @@ public abstract class AbstractCollection<E> implements Collection<E> { * @return how many objects this {@code Collection} contains, or {@code Integer.MAX_VALUE} * if there are more than {@code Integer.MAX_VALUE} elements in this * {@code Collection}. - * @since Android 1.0 */ public abstract int size(); @@ -367,10 +351,10 @@ public abstract class AbstractCollection<E> implements Collection<E> { int size = size(), index = 0; if (size > contents.length) { Class<?> ct = contents.getClass().getComponentType(); - contents = (T[])Array.newInstance(ct, size); + contents = (T[]) Array.newInstance(ct, size); } - for (E entry: this) { - contents[index++] = (T)entry; + for (E entry : this) { + contents[index++] = (T) entry; } if (index < contents.length) { contents[index] = null; @@ -384,7 +368,6 @@ public abstract class AbstractCollection<E> implements Collection<E> { * are separated by ', ' (comma and space). * * @return the string representation of this {@code Collection}. - * @since Android 1.0 */ @Override public String toString() { @@ -402,7 +385,7 @@ public abstract class AbstractCollection<E> implements Collection<E> { } else { buffer.append("(this Collection)"); //$NON-NLS-1$ } - if(it.hasNext()) { + if (it.hasNext()) { buffer.append(", "); //$NON-NLS-1$ } } diff --git a/luni/src/main/java/java/util/AbstractList.java b/luni/src/main/java/java/util/AbstractList.java index cfd8c6f..899affd 100644 --- a/luni/src/main/java/java/util/AbstractList.java +++ b/luni/src/main/java/java/util/AbstractList.java @@ -24,16 +24,14 @@ package java.util; * methods {@code get()} and {@code size()}, and to create a * modifiable {@code List} it's necessary to override the {@code add()} method that * currently throws an {@code UnsupportedOperationException}. - * - * @since Android 1.0 + * + * @since 1.2 */ public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { /** * A counter for changes to the list. - * - * @since Android 1.0 */ protected transient int modCount; @@ -67,22 +65,25 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements } public void remove() { - if (expectedModCount == modCount) { - try { - AbstractList.this.remove(lastPosition); - } catch (IndexOutOfBoundsException e) { - throw new IllegalStateException(); - } - if (modCount != expectedModCount) { - expectedModCount++; - } - if (pos == lastPosition) { - pos--; - } - lastPosition = -1; - } else { + if (this.lastPosition == -1) { + throw new IllegalStateException(); + } + + if (expectedModCount != modCount) { + throw new ConcurrentModificationException(); + } + + try { + AbstractList.this.remove(lastPosition); + } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } + + expectedModCount = modCount; + if (pos == lastPosition) { + pos--; + } + lastPosition = -1; } } @@ -107,7 +108,7 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements pos++; lastPosition = -1; if (modCount != expectedModCount) { - expectedModCount++; + expectedModCount = modCount; } } else { throw new ConcurrentModificationException(); @@ -374,8 +375,6 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Constructs a new instance of this AbstractList. - * - * @since Android 1.0 */ protected AbstractList() { super(); @@ -386,15 +385,15 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * The object is inserted before any previous element at the specified * location. If the location is equal to the size of this List, the object * is added at the end. - * + * <p> * Concrete implementations that would like to support the add functionality - * must override this method. - * + * must override this method. + * * @param location * the index at which to insert. * @param object * the object to add. - * + * * @throws UnsupportedOperationException * if adding to this List is not supported. * @throws ClassCastException @@ -404,7 +403,6 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * if the object cannot be added to this List * @throws IndexOutOfBoundsException * if {@code location < 0 || >= size()} - * @since Android 1.0 */ public void add(int location, E object) { throw new UnsupportedOperationException(); @@ -412,12 +410,12 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Adds the specified object at the end of this List. - * - * + * + * * @param object * the object to add * @return true - * + * * @throws UnsupportedOperationException * if adding to this List is not supported * @throws ClassCastException @@ -425,7 +423,6 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * List * @throws IllegalArgumentException * if the object cannot be added to this List - * @since Android 1.0 */ @Override public boolean add(E object) { @@ -437,7 +434,7 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * Inserts the objects in the specified Collection at the specified location * in this List. The objects are added in the order they are returned from * the collection's iterator. - * + * * @param location * the index at which to insert. * @param collection @@ -451,7 +448,6 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * if an object cannot be added to this list. * @throws IndexOutOfBoundsException * if {@code location < 0 || > size()} - * @since Android 1.0 */ public boolean addAll(int location, Collection<? extends E> collection) { Iterator<? extends E> it = collection.iterator(); @@ -463,12 +459,11 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Removes all elements from this list, leaving it empty. - * + * * @throws UnsupportedOperationException * if removing from this list is not supported. * @see List#isEmpty * @see List#size - * @since Android 1.0 */ @Override public void clear() { @@ -479,13 +474,12 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * Compares the specified object to this list and return true if they are * equal. Two lists are equal when they both contain the same objects in the * same order. - * + * * @param object * the object to compare to this object. * @return {@code true} if the specified object is equal to this list, * {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -512,24 +506,22 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Returns the element at the specified location in this list. - * + * * @param location * the index of the element to return. * @return the element at the specified index. * @throws IndexOutOfBoundsException * if {@code location < 0 || >= size()} - * @since Android 1.0 */ public abstract E get(int location); /** * Returns the hash code of this list. The hash code is calculated by taking * each element's hashcode into account. - * + * * @return the hash code. * @see #equals * @see List#hashCode() - * @since Android 1.0 */ @Override public int hashCode() { @@ -545,12 +537,11 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Searches this list for the specified object and returns the index of the * first occurrence. - * + * * @param object * the object to search for. * @return the index of the first occurrence of the object, or -1 if it was * not found. - * @since Android 1.0 */ public int indexOf(Object object) { ListIterator<?> it = listIterator(); @@ -573,10 +564,9 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Returns an iterator on the elements of this list. The elements are * iterated in the same order as they occur in the list. - * + * * @return an iterator on the elements of this list. * @see Iterator - * @since Android 1.0 */ @Override public Iterator<E> iterator() { @@ -586,12 +576,11 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Searches this list for the specified object and returns the index of the * last occurrence. - * + * * @param object * the object to search for. * @return the index of the last occurrence of the object, or -1 if the * object was not found. - * @since Android 1.0 */ public int lastIndexOf(Object object) { ListIterator<?> it = listIterator(size()); @@ -614,10 +603,9 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Returns a ListIterator on the elements of this list. The elements are * iterated in the same order that they occur in the list. - * + * * @return a ListIterator on the elements of this list * @see ListIterator - * @since Android 1.0 */ public ListIterator<E> listIterator() { return listIterator(0); @@ -627,14 +615,13 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * Returns a list iterator on the elements of this list. The elements are * iterated in the same order as they occur in the list. The iteration * starts at the specified location. - * + * * @param location * the index at which to start the iteration. * @return a ListIterator on the elements of this list. * @throws IndexOutOfBoundsException * if {@code location < 0 || location > size()} * @see ListIterator - * @since Android 1.0 */ public ListIterator<E> listIterator(int location) { return new FullListIterator(location); @@ -642,7 +629,7 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Removes the object at the specified location from this list. - * + * * @param location * the index of the object to remove. * @return the removed object. @@ -650,7 +637,6 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * if removing from this list is not supported. * @throws IndexOutOfBoundsException * if {@code location < 0 || >= size()} - * @since Android 1.0 */ public E remove(int location) { throw new UnsupportedOperationException(); @@ -659,7 +645,7 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Removes the objects in the specified range from the start to the end * index minus one. - * + * * @param start * the index at which to start removing. * @param end @@ -668,7 +654,6 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * if removing from this list is not supported. * @throws IndexOutOfBoundsException * if {@code start < 0} or {@code start >= size()}. - * @since Android 1.0 */ protected void removeRange(int start, int end) { Iterator<?> it = listIterator(start); @@ -681,7 +666,7 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements /** * Replaces the element at the specified location in this list with the * specified object. - * + * * @param location * the index at which to put the specified object. * @param object @@ -695,7 +680,6 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * if an object cannot be added to this list. * @throws IndexOutOfBoundsException * if {@code location < 0 || >= size()} - * @since Android 1.0 */ public E set(int location, E object) { throw new UnsupportedOperationException(); @@ -733,7 +717,7 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * <p> * All methods will throw a ConcurrentModificationException if the modCount * of the original list is not equal to the expected value. - * + * * @param start * start index of the subList (inclusive). * @param end @@ -744,7 +728,6 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements * if (start < 0 || end > size()) * @throws IllegalArgumentException * if (start > end) - * @since Android 1.0 */ public List<E> subList(int start, int end) { if (0 <= start && end <= size()) { diff --git a/luni/src/main/java/java/util/AbstractMap.java b/luni/src/main/java/java/util/AbstractMap.java index 00266a7..b687e72 100644 --- a/luni/src/main/java/java/util/AbstractMap.java +++ b/luni/src/main/java/java/util/AbstractMap.java @@ -17,17 +17,12 @@ package java.util; -// BEGIN android-added -// copied from newer harmony -import java.util.Map.Entry; -// END android-added - /** * This class is an abstract implementation of the {@code Map} interface. This * implementation does not support adding. A subclass must implement the * abstract method entrySet(). - * - * @since Android 1.0 + * + * @since 1.2 */ public abstract class AbstractMap<K, V> implements Map<K, V> { @@ -38,8 +33,6 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Constructs a new instance of this {@code AbstractMap}. - * - * @since Android 1.0 */ protected AbstractMap() { super(); @@ -47,12 +40,11 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Removes all elements from this map, leaving it empty. - * + * * @throws UnsupportedOperationException * if removing from this map is not supported. * @see #isEmpty() * @see #size() - * @since Android 1.0 */ public void clear() { entrySet().clear(); @@ -60,12 +52,11 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Returns whether this map contains the specified key. - * + * * @param key * the key to search for. * @return {@code true} if this map contains the specified key, * {@code false} otherwise. - * @since Android 1.0 */ public boolean containsKey(Object key) { Iterator<Map.Entry<K, V>> it = entrySet().iterator(); @@ -87,12 +78,11 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Returns whether this map contains the specified value. - * + * * @param value * the value to search for. * @return {@code true} if this map contains the specified value, * {@code false} otherwise. - * @since Android 1.0 */ public boolean containsValue(Object value) { Iterator<Map.Entry<K, V>> it = entrySet().iterator(); @@ -116,23 +106,21 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { * Returns a set containing all of the mappings in this map. Each mapping is * an instance of {@link Map.Entry}. As the set is backed by this map, * changes in one will be reflected in the other. - * + * * @return a set of the mappings. - * @since Android 1.0 */ public abstract Set<Map.Entry<K, V>> entrySet(); /** * Compares the specified object to this instance, and returns {@code true} * if the specified object is a map and both maps contain the same mappings. - * + * * @param object * the object to compare with this object. * @return boolean {@code true} if the object is the same as this object, * and {@code false} if it is different from this object. * @see #hashCode() * @see #entrySet() - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -145,19 +133,21 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { return false; } - // BEGIN android-changed - // copied from newer version of harmony Iterator<Map.Entry<K, V>> it = entrySet().iterator(); - while (it.hasNext()) { - Entry<K, V> entry = it.next(); - K key = entry.getKey(); - V value = entry.getValue(); - Object obj = map.get(key); - if( null != obj && (!obj.equals(value)) || null == obj && obj != value) { - return false; + + try { + while (it.hasNext()) { + Entry<K, V> entry = it.next(); + K key = entry.getKey(); + V value = entry.getValue(); + Object obj = map.get(key); + if( null != obj && (!obj.equals(value)) || null == obj && obj != value) { + return false; + } } + } catch (ClassCastException cce) { + return false; } - // END android-changed return true; } return false; @@ -165,12 +155,11 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Returns the value of the mapping with the specified key. - * + * * @param key * the key. * @return the value of the mapping with the specified key, or {@code null} * if no mapping for the specified key is found. - * @since Android 1.0 */ public V get(Object key) { Iterator<Map.Entry<K, V>> it = entrySet().iterator(); @@ -195,10 +184,9 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Returns the hash code for this object. Objects which are equal must * return the same value for this method. - * + * * @return the hash code of this object. * @see #equals(Object) - * @since Android 1.0 */ @Override public int hashCode() { @@ -212,11 +200,10 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Returns whether this map is empty. - * + * * @return {@code true} if this map has no elements, {@code false} * otherwise. * @see #size() - * @since Android 1.0 */ public boolean isEmpty() { return size() == 0; @@ -226,9 +213,8 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { * Returns a set of the keys contained in this map. The set is backed by * this map so changes to one are reflected by the other. The returned set * does not support adding. - * + * * @return a set of the keys. - * @since Android 1.0 */ public Set<K> keySet() { if (keySet == null) { @@ -269,7 +255,7 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Maps the specified key to the specified value. - * + * * @param key * the key. * @param value @@ -286,7 +272,6 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { * @throws NullPointerException * if the key or value is {@code null} and this Map does not * support {@code null} keys or values. - * @since Android 1.0 */ public V put(K key, V value) { throw new UnsupportedOperationException(); @@ -294,7 +279,7 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Copies every mapping in the specified map to this map. - * + * * @param map * the map to copy mappings from. * @throws UnsupportedOperationException @@ -307,7 +292,6 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { * @throws NullPointerException * if a key or value is {@code null} and this map does not * support {@code null} keys or values. - * @since Android 1.0 */ public void putAll(Map<? extends K, ? extends V> map) { for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) { @@ -317,14 +301,13 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Removes a mapping with the specified key from this Map. - * + * * @param key * the key of the mapping to remove. * @return the value of the removed mapping or {@code null} if no mapping * for the specified key was found. * @throws UnsupportedOperationException * if removing from this map is not supported. - * @since Android 1.0 */ public V remove(Object key) { Iterator<Map.Entry<K, V>> it = entrySet().iterator(); @@ -350,9 +333,8 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Returns the number of elements in this map. - * + * * @return the number of elements in this map. - * @since Android 1.0 */ public int size() { return entrySet().size(); @@ -360,9 +342,8 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Returns the string representation of this map. - * + * * @return the string representation of this map. - * @since Android 1.0 */ @Override public String toString() { @@ -407,16 +388,13 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { * "wrapper object" over the iterator of map's entrySet(). The {@code size} * method wraps the map's size method and the {@code contains} method wraps * the map's containsValue method. - * </p> * <p> * The collection is created when this method is called for the first time * and returned in response to all subsequent calls. This method may return * different collections when multiple concurrent calls occur to this * method, since no synchronization is performed. - * </p> - * + * * @return a collection of the values contained in this map. - * @since Android 1.0 */ public Collection<V> values() { if (valuesCollection == null) { @@ -458,12 +436,11 @@ public abstract class AbstractMap<K, V> implements Map<K, V> { /** * Returns a new instance of the same class as this instance, whose slots * have been filled in with the values of the slots of this instance. - * + * * @return a shallow copy of this object. * @throws CloneNotSupportedException * if the receiver's class does not implement the interface * {@code Cloneable}. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") diff --git a/luni/src/main/java/java/util/AbstractQueue.java b/luni/src/main/java/java/util/AbstractQueue.java index 0b9bdf1..4b4fccf 100644 --- a/luni/src/main/java/java/util/AbstractQueue.java +++ b/luni/src/main/java/java/util/AbstractQueue.java @@ -22,18 +22,15 @@ package java.util; * {@code element} are based on {@code offer, poll}, and {@code peek} except * that they throw exceptions to indicate some error instead of returning true * or false. - * + * * @param <E> * the type of the element in the collection. - * @since Android 1.0 */ public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E> { /** * Constructor to be used by subclasses. - * - * @since Android 1.0 */ protected AbstractQueue() { super(); @@ -47,7 +44,6 @@ public abstract class AbstractQueue<E> extends AbstractCollection<E> implements * @return {@code true} if the operation succeeds, otherwise {@code false}. * @throws IllegalStateException * if the element is not allowed to be added to the queue. - * @since Android 1.0 */ @Override public boolean add(E o) { @@ -76,7 +72,6 @@ public abstract class AbstractQueue<E> extends AbstractCollection<E> implements * @throws IllegalArgumentException * If the collection to be added to the queue is the queue * itself. - * @since Android 1.0 */ @Override public boolean addAll(Collection<? extends E> c) { @@ -95,7 +90,6 @@ public abstract class AbstractQueue<E> extends AbstractCollection<E> implements * @return the element at the head of the queue. * @throws NoSuchElementException * if the queue is empty. - * @since Android 1.0 */ public E remove() { E o = poll(); @@ -111,7 +105,6 @@ public abstract class AbstractQueue<E> extends AbstractCollection<E> implements * @return the element at the head of the queue. * @throws NoSuchElementException * if the queue is empty. - * @since Android 1.0 */ public E element() { E o = peek(); @@ -123,8 +116,6 @@ public abstract class AbstractQueue<E> extends AbstractCollection<E> implements /** * Removes all elements of the queue, leaving it empty. - * - * @since Android 1.0 */ @Override public void clear() { diff --git a/luni/src/main/java/java/util/AbstractSequentialList.java b/luni/src/main/java/java/util/AbstractSequentialList.java index 4ca8f7b..dcdecaa 100644 --- a/luni/src/main/java/java/util/AbstractSequentialList.java +++ b/luni/src/main/java/java/util/AbstractSequentialList.java @@ -17,20 +17,17 @@ package java.util; - /** * AbstractSequentialList is an abstract implementation of the List interface. * This implementation does not support adding. A subclass must implement the * abstract method listIterator(). - * - * @since Android 1.0 + * + * @since 1.2 */ public abstract class AbstractSequentialList<E> extends AbstractList<E> { /** * Constructs a new instance of this AbstractSequentialList. - * - * @since Android 1.0 */ protected AbstractSequentialList() { super(); @@ -45,24 +42,11 @@ public abstract class AbstractSequentialList<E> extends AbstractList<E> { public boolean addAll(int location, Collection<? extends E> collection) { ListIterator<E> it = listIterator(location); Iterator<? extends E> colIt = collection.iterator(); - // BEGIN android-removed - // int next = it.nextIndex(); - // while (colIt.hasNext()) { - // it.add(colIt.next()); - // it.previous(); - // } - // return next != it.nextIndex(); - // END android-removed - - // BEGIN android-added - // BUG: previous/next inconsistant. We care for list - // modification NOT iterator modification. - int size = this.size(); + int next = it.nextIndex(); while (colIt.hasNext()) { it.add(colIt.next()); } - return size != this.size(); - // END android-added + return next != it.nextIndex(); } @Override @@ -97,6 +81,9 @@ public abstract class AbstractSequentialList<E> extends AbstractList<E> { @Override public E set(int location, E object) { ListIterator<E> it = listIterator(location); + if (!it.hasNext()) { + throw new IndexOutOfBoundsException(); + } E result = it.next(); it.set(object); return result; diff --git a/luni/src/main/java/java/util/AbstractSet.java b/luni/src/main/java/java/util/AbstractSet.java index a19b1f7..e6ef0bb 100644 --- a/luni/src/main/java/java/util/AbstractSet.java +++ b/luni/src/main/java/java/util/AbstractSet.java @@ -22,15 +22,13 @@ package java.util; * implementation does not support adding. A subclass must implement the * abstract methods iterator() and size(). * - * @since Android 1.0 + * @since 1.2 */ public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> { /** * Constructs a new instance of this AbstractSet. - * - * @since Android 1.0 */ protected AbstractSet() { super(); @@ -46,7 +44,6 @@ public abstract class AbstractSet<E> extends AbstractCollection<E> implements * @return {@code true} if the specified object is equal to this set, * {@code false} otherwise * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -55,14 +52,12 @@ public abstract class AbstractSet<E> extends AbstractCollection<E> implements } if (object instanceof Set) { Set<?> s = (Set<?>) object; - // BEGIN android-changed - // copied from a newer version of harmony + try { return size() == s.size() && containsAll(s); } catch (ClassCastException cce) { return false; } - // END android-changed } return false; } @@ -74,7 +69,6 @@ public abstract class AbstractSet<E> extends AbstractCollection<E> implements * * @return the hash code of this set. * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -95,9 +89,8 @@ public abstract class AbstractSet<E> extends AbstractCollection<E> implements * the collection of objects to remove. * @return {@code true} if this collection was modified, {@code false} * otherwise. - * @exception UnsupportedOperationException - * when removing from this collection is not supported. - * @since Android 1.0 + * @throws UnsupportedOperationException + * if removing from this collection is not supported. */ @Override public boolean removeAll(Collection<?> collection) { diff --git a/luni/src/main/java/java/util/ArrayList.java b/luni/src/main/java/java/util/ArrayList.java index 78f9690..ade5d27 100644 --- a/luni/src/main/java/java/util/ArrayList.java +++ b/luni/src/main/java/java/util/ArrayList.java @@ -17,7 +17,6 @@ package java.util; - import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -29,11 +28,11 @@ import java.lang.reflect.Array; * ArrayList is an implementation of {@link List}, backed by an array. All * optional operations adding, removing, and replacing are supported. The * elements can be any objects. - * - * @since Android 1.0 + * + * @since 1.2 */ -public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, - Serializable, RandomAccess { +public class ArrayList<E> extends AbstractList<E> implements List<E>, + Cloneable, Serializable, RandomAccess { private static final long serialVersionUID = 8683452581122892189L; @@ -43,53 +42,53 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, // END android-added private transient int firstIndex; - + private transient int lastIndex; private transient E[] array; /** * Constructs a new instance of {@code ArrayList} with zero capacity. - * - * @since Android 1.0 */ public ArrayList() { + // BEGIN android-changed + // default capacity is zero, not ten this(0); + // END android-changed } /** * Constructs a new instance of {@code ArrayList} with the specified * capacity. - * + * * @param capacity * the initial capacity of this {@code ArrayList}. - * @since Android 1.0 */ public ArrayList(int capacity) { - firstIndex = lastIndex = 0; - try { - array = newElementArray(capacity); - } catch (NegativeArraySizeException e) { + if (capacity < 0) { throw new IllegalArgumentException(); } + firstIndex = lastIndex = 0; + array = newElementArray(capacity); } /** * Constructs a new instance of {@code ArrayList} containing the elements of * the specified collection. The initial size of the {@code ArrayList} will * be 10% higher than the size of the specified collection. - * + * * @param collection * the collection of elements to add. - * @since Android 1.0 */ public ArrayList(Collection<? extends E> collection) { int size = collection.size(); - firstIndex = lastIndex = 0; + firstIndex = 0; array = newElementArray(size + (size / 10)); - addAll(collection); + collection.toArray(array); + lastIndex = size; + modCount = 1; } - + @SuppressWarnings("unchecked") private E[] newElementArray(int size) { // BEGIN android-added @@ -98,7 +97,7 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, } // END android-added - return (E[])new Object[size]; + return (E[]) new Object[size]; } /** @@ -106,20 +105,17 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, * location. The object is inserted before any previous element at the * specified location. If the location is equal to the size of this * {@code ArrayList}, the object is added at the end. - * + * * @param location * the index at which to insert the object. * @param object * the object to add. * @throws IndexOutOfBoundsException * when {@code location < 0 || > size()} - * @since Android 1.0 */ @Override public void add(int location, E object) { - // BEGIN android-changed: slight performance improvement int size = lastIndex - firstIndex; - // END android-changed if (0 < location && location < size) { if (firstIndex == 0 && lastIndex == array.length) { growForInsert(location, 1); @@ -153,11 +149,10 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Adds the specified object at the end of this {@code ArrayList}. - * + * * @param object * the object to add. * @return always true - * @since Android 1.0 */ @Override public boolean add(E object) { @@ -173,7 +168,7 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, * Inserts the objects in the specified collection at the specified location * in this List. The objects are added in the order they are returned from * the collection's iterator. - * + * * @param location * the index at which to insert. * @param collection @@ -182,14 +177,16 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, * otherwise. * @throws IndexOutOfBoundsException * when {@code location < 0 || > size()} - * @since Android 1.0 */ @Override public boolean addAll(int location, Collection<? extends E> collection) { - int size = size(); + int size = lastIndex - firstIndex; if (location < 0 || location > size) { throw new IndexOutOfBoundsException(); } + if (this == collection) { + collection = (ArrayList)clone(); + } int growSize = collection.size(); if (0 < location && location < size) { if (array.length - size < growSize) { @@ -223,12 +220,10 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, } if (growSize > 0) { - Iterator<? extends E> it = collection.iterator(); - int index = location + firstIndex; - int end = index + growSize; - while (index < end) { - array[index++] = it.next(); - } + Object[] dumparray = new Object[growSize]; + collection.toArray(dumparray); + System.arraycopy(dumparray, 0, this.array, location + firstIndex, + growSize); modCount++; return true; } @@ -237,37 +232,32 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Adds the objects in the specified collection to this {@code ArrayList}. - * + * * @param collection * the collection of objects. * @return {@code true} if this {@code ArrayList} is modified, {@code false} * otherwise. - * @since Android 1.0 */ @Override public boolean addAll(Collection<? extends E> collection) { - int growSize = collection.size(); - if (growSize > 0) { - if (lastIndex > array.length - growSize) { - growAtEnd(growSize); - } - Iterator<? extends E> it = collection.iterator(); - int end = lastIndex + growSize; - while (lastIndex < end) { - array[lastIndex++] = it.next(); - } - modCount++; - return true; + Object[] dumpArray = collection.toArray(); + if (dumpArray.length == 0) { + return false; } - return false; + if (dumpArray.length > array.length - lastIndex) { + growAtEnd(dumpArray.length); + } + System.arraycopy(dumpArray, 0, this.array, lastIndex, dumpArray.length); + lastIndex += dumpArray.length; + modCount++; + return true; } /** * Removes all elements from this {@code ArrayList}, leaving it empty. - * + * * @see #isEmpty * @see #size - * @since Android 1.0 */ @Override public void clear() { @@ -281,10 +271,9 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Returns a new {@code ArrayList} with the same elements, the same size and * the same capacity as this {@code ArrayList}. - * + * * @return a shallow copy of this {@code ArrayList} * @see java.lang.Cloneable - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -300,12 +289,11 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Searches this {@code ArrayList} for the specified object. - * + * * @param object * the object to search for. * @return {@code true} if {@code object} is an element of this * {@code ArrayList}, {@code false} otherwise - * @since Android 1.0 */ @Override public boolean contains(Object object) { @@ -328,10 +316,9 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Ensures that after this operation the {@code ArrayList} can hold the * specified number of elements without further growing. - * + * * @param minimumCapacity * the minimum capacity asked for. - * @since Android 1.0 */ public void ensureCapacity(int minimumCapacity) { if (array.length < minimumCapacity) { @@ -356,7 +343,7 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, } private void growAtEnd(int required) { - int size = size(); + int size = lastIndex - firstIndex; if (firstIndex >= required - (array.length - lastIndex)) { int newLast = lastIndex - firstIndex; if (size > 0) { @@ -385,8 +372,8 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, } private void growAtFront(int required) { - int size = size(); - if (array.length - lastIndex >= required) { + int size = lastIndex - firstIndex; + if (array.length - lastIndex + firstIndex >= required) { int newFirst = array.length - size; if (size > 0) { System.arraycopy(array, firstIndex, array, newFirst, size); @@ -416,7 +403,8 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, } private void growForInsert(int location, int required) { - int size = size(), increment = size / 2; + int size = lastIndex - firstIndex; + int increment = size / 2; if (required > increment) { increment = required; } @@ -480,20 +468,17 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Removes the object at the specified location from this list. - * + * * @param location * the index of the object to remove. * @return the removed object. * @throws IndexOutOfBoundsException * when {@code location < 0 || >= size()} - * @since Android 1.0 */ @Override public E remove(int location) { E result; - // BEGIN android-changed: slight performance improvement int size = lastIndex - firstIndex; - // END android-changed if (0 <= location && location < size) { if (location == size - 1) { result = array[--lastIndex]; @@ -514,6 +499,9 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, array[--lastIndex] = null; } } + if (firstIndex == lastIndex) { + firstIndex = lastIndex = 0; + } } else { throw new IndexOutOfBoundsException(); } @@ -522,41 +510,34 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, return result; } - // BEGIN android-added - /* - * The remove(Object) implementation from AbstractCollection creates - * a new Iterator on every remove and ends up calling remove(int). - */ @Override public boolean remove(Object object) { - int index = indexOf(object); - if (index >= 0) { - remove(index); + int location = indexOf(object); + if (location >= 0) { + remove(location); return true; } return false; } - // END android-added /** * Removes the objects in the specified range from the start to the end, but * not including the end index. - * + * * @param start * the index at which to start removing. * @param end * the index one after the end of the range to remove. * @throws IndexOutOfBoundsException * when {@code start < 0, start > end} or {@code end > size()} - * @since Android 1.0 */ @Override protected void removeRange(int start, int end) { - if (start >= 0 && start <= end && end <= size()) { + if (start >= 0 && start <= end && end <= (lastIndex - firstIndex)) { if (start == end) { return; } - int size = size(); + int size = lastIndex - firstIndex; if (end == size) { Arrays.fill(array, firstIndex + start, lastIndex, null); lastIndex = firstIndex + start; @@ -579,7 +560,7 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Replaces the element at the specified location in this {@code ArrayList} * with the specified object. - * + * * @param location * the index at which to put the specified object. * @param object @@ -587,13 +568,10 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, * @return the previous element at the index. * @throws IndexOutOfBoundsException * when {@code location < 0 || >= size()} - * @since Android 1.0 */ @Override public E set(int location, E object) { - // BEGIN android-changed: slight performance improvement if (0 <= location && location < (lastIndex - firstIndex)) { - // END android-changed E result = array[firstIndex + location]; array[firstIndex + location] = object; return result; @@ -603,9 +581,8 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Returns the number of elements in this {@code ArrayList}. - * + * * @return the number of elements in this {@code ArrayList}. - * @since Android 1.0 */ @Override public int size() { @@ -615,13 +592,12 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Returns a new array containing all elements contained in this * {@code ArrayList}. - * + * * @return an array of the elements from this {@code ArrayList} - * @since Android 1.0 */ @Override public Object[] toArray() { - int size = size(); + int size = lastIndex - firstIndex; Object[] result = new Object[size]; System.arraycopy(array, firstIndex, result, 0, size); return result; @@ -634,19 +610,18 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, * type is created. If the specified array is used and is larger than this * {@code ArrayList}, the array element following the collection elements * is set to null. - * + * * @param contents * the array. * @return an array of the elements from this {@code ArrayList}. * @throws ArrayStoreException * when the type of an element in this {@code ArrayList} cannot * be stored in the type of the specified array. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") public <T> T[] toArray(T[] contents) { - int size = size(); + int size = lastIndex - firstIndex; if (size > contents.length) { Class<?> ct = contents.getClass().getComponentType(); contents = (T[]) Array.newInstance(ct, size); @@ -661,17 +636,17 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, /** * Sets the capacity of this {@code ArrayList} to be the same as the current * size. - * + * * @see #size - * @since Android 1.0 */ public void trimToSize() { - int size = size(); + int size = lastIndex - firstIndex; E[] newArray = newElementArray(size); System.arraycopy(array, firstIndex, newArray, 0, size); array = newArray; firstIndex = 0; lastIndex = array.length; + modCount = 0; } private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField( @@ -679,7 +654,7 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, private void writeObject(ObjectOutputStream stream) throws IOException { ObjectOutputStream.PutField fields = stream.putFields(); - fields.put("size", size()); //$NON-NLS-1$ + fields.put("size", lastIndex - firstIndex); //$NON-NLS-1$ stream.writeFields(); stream.writeInt(array.length); Iterator<?> it = iterator(); @@ -695,7 +670,7 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable, lastIndex = fields.get("size", 0); //$NON-NLS-1$ array = newElementArray(stream.readInt()); for (int i = 0; i < lastIndex; i++) { - array[i] = (E)stream.readObject(); + array[i] = (E) stream.readObject(); } } } diff --git a/luni/src/main/java/java/util/Arrays.java b/luni/src/main/java/java/util/Arrays.java index d479945..4fc1e85 100644 --- a/luni/src/main/java/java/util/Arrays.java +++ b/luni/src/main/java/java/util/Arrays.java @@ -22,11 +22,16 @@ import java.lang.reflect.Array; /** * {@code Arrays} contains static methods which operate on arrays. - * - * @since Android 1.0 + * + * @since 1.2 */ public class Arrays { + // BEGIN android-removed + /* Specifies when to switch to insertion sort */ + // private static final int SIMPLE_LENGTH = 7; + // END android-removed + private static class ArrayList<E> extends AbstractList<E> implements List<E>, Serializable, RandomAccess { @@ -152,11 +157,10 @@ public class Arrays { * {@code List} cannot be modified, i.e. adding and removing are unsupported, but * the elements can be set. Setting an element modifies the underlying * array. - * + * * @param array * the array. * @return a {@code List} of the elements of the specified array. - * @since Android 1.0 */ public static <T> List<T> asList(T... array) { return new ArrayList<T>(array); @@ -167,19 +171,18 @@ public class Arrays { * ascending sorted array. Searching in an unsorted array has an undefined * result. It's also undefined which element is found if there are multiple * occurrences of the same element. - * + * * @param array * the sorted {@code byte} array to search. * @param value * the {@code byte} element to find. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @since Android 1.0 */ public static int binarySearch(byte[] array, byte value) { int low = 0, mid = -1, high = array.length - 1; while (low <= high) { - mid = (low + high) >> 1; + mid = (low + high) >>> 1; if (value > array[mid]) { low = mid + 1; } else if (value == array[mid]) { @@ -200,19 +203,18 @@ public class Arrays { * ascending sorted array. Searching in an unsorted array has an undefined * result. It's also undefined which element is found if there are multiple * occurrences of the same element. - * + * * @param array * the sorted {@code char} array to search. * @param value * the {@code char} element to find. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @since Android 1.0 */ public static int binarySearch(char[] array, char value) { int low = 0, mid = -1, high = array.length - 1; while (low <= high) { - mid = (low + high) >> 1; + mid = (low + high) >>> 1; if (value > array[mid]) { low = mid + 1; } else if (value == array[mid]) { @@ -232,20 +234,19 @@ public class Arrays { * ascending sorted array. Searching in an unsorted array has an undefined * result. It's also undefined which element is found if there are multiple * occurrences of the same element. - * + * * @param array * the sorted {@code double} array to search. * @param value * the {@code double} element to find. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @since Android 1.0 */ public static int binarySearch(double[] array, double value) { long longBits = Double.doubleToLongBits(value); int low = 0, mid = -1, high = array.length - 1; while (low <= high) { - mid = (low + high) >> 1; + mid = (low + high) >>> 1; if (lessThan(array[mid], value)) { low = mid + 1; } else if (longBits == Double.doubleToLongBits(array[mid])) { @@ -265,20 +266,19 @@ public class Arrays { * ascending sorted array. Searching in an unsorted array has an undefined * result. It's also undefined which element is found if there are multiple * occurrences of the same element. - * + * * @param array * the sorted {@code float} array to search. * @param value * the {@code float} element to find. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @since Android 1.0 */ public static int binarySearch(float[] array, float value) { int intBits = Float.floatToIntBits(value); int low = 0, mid = -1, high = array.length - 1; while (low <= high) { - mid = (low + high) >> 1; + mid = (low + high) >>> 1; if (lessThan(array[mid], value)) { low = mid + 1; } else if (intBits == Float.floatToIntBits(array[mid])) { @@ -298,19 +298,18 @@ public class Arrays { * ascending sorted array. Searching in an unsorted array has an undefined * result. It's also undefined which element is found if there are multiple * occurrences of the same element. - * + * * @param array * the sorted {@code int} array to search. * @param value * the {@code int} element to find. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @since Android 1.0 */ public static int binarySearch(int[] array, int value) { int low = 0, mid = -1, high = array.length - 1; while (low <= high) { - mid = (low + high) >> 1; + mid = (low + high) >>> 1; if (value > array[mid]) { low = mid + 1; } else if (value == array[mid]) { @@ -330,19 +329,18 @@ public class Arrays { * ascending sorted array. Searching in an unsorted array has an undefined * result. It's also undefined which element is found if there are multiple * occurrences of the same element. - * + * * @param array * the sorted {@code long} array to search. * @param value * the {@code long} element to find. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @since Android 1.0 */ public static int binarySearch(long[] array, long value) { int low = 0, mid = -1, high = array.length - 1; while (low <= high) { - mid = (low + high) >> 1; + mid = (low + high) >>> 1; if (value > array[mid]) { low = mid + 1; } else if (value == array[mid]) { @@ -362,28 +360,27 @@ public class Arrays { * ascending sorted array. Searching in an unsorted array has an undefined * result. It's also undefined which element is found if there are multiple * occurrences of the same element. - * + * * @param array * the sorted {@code Object} array to search. * @param object * the {@code Object} element to find. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @exception ClassCastException + * @throws ClassCastException * if an element in the array or the search element does not * implement {@code Comparable}, or cannot be compared to each other. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static int binarySearch(Object[] array, Object object) { if (array.length == 0) { return -1; } - Comparable<Object> key = (Comparable<Object>) object; + int low = 0, mid = 0, high = array.length - 1, result = 0; while (low <= high) { - mid = (low + high) >> 1; - if ((result = key.compareTo(array[mid])) > 0) { + mid = (low + high) >>> 1; + if ((result = ((Comparable<Object>)array[mid]).compareTo(object)) < 0){ low = mid + 1; } else if (result == 0) { return mid; @@ -391,7 +388,7 @@ public class Arrays { high = mid - 1; } } - return -mid - (result <= 0 ? 1 : 2); + return -mid - (result >= 0 ? 1 : 2); } /** @@ -400,7 +397,7 @@ public class Arrays { * Searching in an unsorted array has an undefined result. It's also * undefined which element is found if there are multiple occurrences of the * same element. - * + * * @param array * the sorted array to search * @param object @@ -409,10 +406,9 @@ public class Arrays { * the {@code Comparator} sued to compare the elements. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @exception ClassCastException - * if an element in the array cannot be compared to the search element + * @throws ClassCastException + * if an element in the array cannot be compared to the search element * using the {@code Comparator}. - * @since Android 1.0 */ public static <T> int binarySearch(T[] array, T object, Comparator<? super T> comparator) { @@ -422,7 +418,7 @@ public class Arrays { int low = 0, mid = 0, high = array.length - 1, result = 0; while (low <= high) { - mid = (low + high) >> 1; + mid = (low + high) >>> 1; if ((result = comparator.compare(array[mid], object)) < 0) { low = mid + 1; } else if (result == 0) { @@ -439,19 +435,18 @@ public class Arrays { * ascending sorted array. Searching in an unsorted array has an undefined * result. It's also undefined which element is found if there are multiple * occurrences of the same element. - * + * * @param array * the sorted {@code short} array to search. * @param value * the {@code short} element to find. * @return the non-negative index of the element, or a negative index which * is {@code -index - 1} where the element would be inserted. - * @since Android 1.0 */ public static int binarySearch(short[] array, short value) { int low = 0, mid = -1, high = array.length - 1; while (low <= high) { - mid = (low + high) >> 1; + mid = (low + high) >>> 1; if (value > array[mid]) { low = mid + 1; } else if (value == array[mid]) { @@ -468,12 +463,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code byte} array to fill. * @param value * the {@code byte} element. - * @since Android 1.0 */ public static void fill(byte[] array, byte value) { for (int i = 0; i < array.length; i++) { @@ -483,7 +477,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code byte} array to fill. * @param start @@ -492,11 +486,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code byte} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(byte[] array, int start, int end, byte value) { // Check for null first @@ -514,12 +507,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code short} array to fill. * @param value * the {@code short} element. - * @since Android 1.0 */ public static void fill(short[] array, short value) { for (int i = 0; i < array.length; i++) { @@ -529,7 +521,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code short} array to fill. * @param start @@ -538,11 +530,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code short} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(short[] array, int start, int end, short value) { // Check for null first @@ -560,12 +551,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code char} array to fill. * @param value * the {@code char} element. - * @since Android 1.0 */ public static void fill(char[] array, char value) { for (int i = 0; i < array.length; i++) { @@ -575,7 +565,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code char} array to fill. * @param start @@ -584,11 +574,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code char} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(char[] array, int start, int end, char value) { // Check for null first @@ -606,12 +595,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code int} array to fill. * @param value * the {@code int} element. - * @since Android 1.0 */ public static void fill(int[] array, int value) { for (int i = 0; i < array.length; i++) { @@ -621,7 +609,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code int} array to fill. * @param start @@ -630,11 +618,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code int} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(int[] array, int start, int end, int value) { // Check for null first @@ -652,12 +639,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code long} array to fill. * @param value * the {@code long} element. - * @since Android 1.0 */ public static void fill(long[] array, long value) { for (int i = 0; i < array.length; i++) { @@ -667,7 +653,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code long} array to fill. * @param start @@ -676,11 +662,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code long} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(long[] array, int start, int end, long value) { // Check for null first @@ -698,12 +683,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code float} array to fill. * @param value * the {@code float} element. - * @since Android 1.0 */ public static void fill(float[] array, float value) { for (int i = 0; i < array.length; i++) { @@ -713,7 +697,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code float} array to fill. * @param start @@ -722,11 +706,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code float} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(float[] array, int start, int end, float value) { // Check for null first @@ -744,12 +727,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code double} array to fill. * @param value * the {@code double} element. - * @since Android 1.0 */ public static void fill(double[] array, double value) { for (int i = 0; i < array.length; i++) { @@ -759,7 +741,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code double} array to fill. * @param start @@ -768,11 +750,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code double} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(double[] array, int start, int end, double value) { // Check for null first @@ -790,12 +771,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code boolean} array to fill. * @param value * the {@code boolean} element. - * @since Android 1.0 */ public static void fill(boolean[] array, boolean value) { for (int i = 0; i < array.length; i++) { @@ -805,7 +785,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code boolean} array to fill. * @param start @@ -814,11 +794,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code boolean} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(boolean[] array, int start, int end, boolean value) { // Check for null first @@ -836,12 +815,11 @@ public class Arrays { /** * Fills the specified array with the specified element. - * + * * @param array * the {@code Object} array to fill. * @param value * the {@code Object} element. - * @since Android 1.0 */ public static void fill(Object[] array, Object value) { for (int i = 0; i < array.length; i++) { @@ -851,7 +829,7 @@ public class Arrays { /** * Fills the specified range in the array with the specified element. - * + * * @param array * the {@code Object} array to fill. * @param start @@ -860,11 +838,10 @@ public class Arrays { * the last + 1 index to fill. * @param value * the {@code Object} element. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void fill(Object[] array, int start, int end, Object value) { // Check for null first @@ -882,7 +859,7 @@ public class Arrays { /** * Returns a hash code based on the contents of the given array. For any two - * {@code boolean} arrays {@code a} and {@code b}, if + * {@code boolean} arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}. * <p> @@ -891,11 +868,10 @@ public class Arrays { * containing a sequence of {@link Boolean}} instances representing the * elements of array in the same order. If the array is {@code null}, the return * value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(boolean[] array) { if (array == null) { @@ -911,7 +887,7 @@ public class Arrays { /** * Returns a hash code based on the contents of the given array. For any two - * not-null {@code int} arrays {@code a} and {@code b}, if + * not-null {@code int} arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}. * <p> @@ -920,11 +896,10 @@ public class Arrays { * containing a sequence of {@link Integer}} instances representing the * elements of array in the same order. If the array is {@code null}, the return * value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(int[] array) { if (array == null) { @@ -940,7 +915,7 @@ public class Arrays { /** * Returns a hash code based on the contents of the given array. For any two - * {@code short} arrays {@code a} and {@code b}, if + * {@code short} arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}. * <p> @@ -949,11 +924,10 @@ public class Arrays { * containing a sequence of {@link Short}} instances representing the * elements of array in the same order. If the array is {@code null}, the return * value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(short[] array) { if (array == null) { @@ -969,7 +943,7 @@ public class Arrays { /** * Returns a hash code based on the contents of the given array. For any two - * {@code char} arrays {@code a} and {@code b}, if + * {@code char} arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}. * <p> @@ -978,11 +952,10 @@ public class Arrays { * containing a sequence of {@link Character}} instances representing the * elements of array in the same order. If the array is {@code null}, the return * value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(char[] array) { if (array == null) { @@ -998,7 +971,7 @@ public class Arrays { /** * Returns a hash code based on the contents of the given array. For any two - * {@code byte} arrays {@code a} and {@code b}, if + * {@code byte} arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}. * <p> @@ -1007,11 +980,10 @@ public class Arrays { * containing a sequence of {@link Byte}} instances representing the * elements of array in the same order. If the array is {@code null}, the return * value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(byte[] array) { if (array == null) { @@ -1027,7 +999,7 @@ public class Arrays { /** * Returns a hash code based on the contents of the given array. For any two - * {@code long} arrays {@code a} and {@code b}, if + * {@code long} arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}. * <p> @@ -1036,11 +1008,10 @@ public class Arrays { * containing a sequence of {@link Long}} instances representing the * elements of array in the same order. If the array is {@code null}, the return * value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(long[] array) { if (array == null) { @@ -1060,7 +1031,7 @@ public class Arrays { /** * Returns a hash code based on the contents of the given array. For any two - * {@code float} arrays {@code a} and {@code b}, if + * {@code float} arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}. * <p> @@ -1069,11 +1040,10 @@ public class Arrays { * containing a sequence of {@link Float}} instances representing the * elements of array in the same order. If the array is {@code null}, the return * value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(float[] array) { if (array == null) { @@ -1092,7 +1062,7 @@ public class Arrays { /** * Returns a hash code based on the contents of the given array. For any two - * {@code double} arrays {@code a} and {@code b}, if + * {@code double} arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}. * <p> @@ -1101,11 +1071,10 @@ public class Arrays { * containing a sequence of {@link Double}} instances representing the * elements of array in the same order. If the array is {@code null}, the return * value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(double[] array) { if (array == null) { @@ -1131,19 +1100,18 @@ public class Arrays { * method on an array that contains itself as an element, either directly or * indirectly. * <p> - * For any two arrays {@code a} and {@code b}, if + * For any two arrays {@code a} and {@code b}, if * {@code Arrays.equals(a, b)} returns {@code true}, it means - * that the return value of {@code Arrays.hashCode(a)} equals + * that the return value of {@code Arrays.hashCode(a)} equals * {@code Arrays.hashCode(b)}. * <p> * The value returned by this method is the same value as the method * Arrays.asList(array).hashCode(). If the array is {@code null}, the return value * is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int hashCode(Object[] array) { if (array == null) { @@ -1170,7 +1138,7 @@ public class Arrays { * this method on an array that contains itself as an element, either * directly or indirectly. * <p> - * For any two arrays {@code a} and {@code b}, if + * For any two arrays {@code a} and {@code b}, if * {@code Arrays.deepEquals(a, b)} returns {@code true}, it * means that the return value of {@code Arrays.deepHashCode(a)} equals * {@code Arrays.deepHashCode(b)}. @@ -1185,11 +1153,10 @@ public class Arrays { * an array of a reference type. The value returned by this method is the * same value as the method {@code Arrays.asList(array).hashCode()}. If the array is * {@code null}, the return value is 0. - * + * * @param array * the array whose hash code to compute. * @return the hash code for {@code array}. - * @since Android 1.0 */ public static int deepHashCode(Object[] array) { if (array == null) { @@ -1247,7 +1214,7 @@ public class Arrays { /** * Compares the two arrays. - * + * * @param array1 * the first {@code byte} array. * @param array2 @@ -1255,7 +1222,6 @@ public class Arrays { * @return {@code true} if both arrays are {@code null} or if the arrays have the * same length and the elements at each index in the two arrays are * equal, {@code false} otherwise. - * @since Android 1.0 */ public static boolean equals(byte[] array1, byte[] array2) { if (array1 == array2) { @@ -1274,7 +1240,7 @@ public class Arrays { /** * Compares the two arrays. - * + * * @param array1 * the first {@code short} array. * @param array2 @@ -1282,7 +1248,6 @@ public class Arrays { * @return {@code true} if both arrays are {@code null} or if the arrays have the * same length and the elements at each index in the two arrays are * equal, {@code false} otherwise. - * @since Android 1.0 */ public static boolean equals(short[] array1, short[] array2) { if (array1 == array2) { @@ -1301,7 +1266,7 @@ public class Arrays { /** * Compares the two arrays. - * + * * @param array1 * the first {@code char} array. * @param array2 @@ -1309,7 +1274,6 @@ public class Arrays { * @return {@code true} if both arrays are {@code null} or if the arrays have the * same length and the elements at each index in the two arrays are * equal, {@code false} otherwise. - * @since Android 1.0 */ public static boolean equals(char[] array1, char[] array2) { if (array1 == array2) { @@ -1328,7 +1292,7 @@ public class Arrays { /** * Compares the two arrays. - * + * * @param array1 * the first {@code int} array. * @param array2 @@ -1336,7 +1300,6 @@ public class Arrays { * @return {@code true} if both arrays are {@code null} or if the arrays have the * same length and the elements at each index in the two arrays are * equal, {@code false} otherwise. - * @since Android 1.0 */ public static boolean equals(int[] array1, int[] array2) { if (array1 == array2) { @@ -1355,7 +1318,7 @@ public class Arrays { /** * Compares the two arrays. - * + * * @param array1 * the first {@code long} array. * @param array2 @@ -1363,7 +1326,6 @@ public class Arrays { * @return {@code true} if both arrays are {@code null} or if the arrays have the * same length and the elements at each index in the two arrays are * equal, {@code false} otherwise. - * @since Android 1.0 */ public static boolean equals(long[] array1, long[] array2) { if (array1 == array2) { @@ -1383,7 +1345,7 @@ public class Arrays { /** * Compares the two arrays. The values are compared in the same manner as * {@code Float.equals()}. - * + * * @param array1 * the first {@code float} array. * @param array2 @@ -1392,7 +1354,6 @@ public class Arrays { * same length and the elements at each index in the two arrays are * equal, {@code false} otherwise. * @see Float#equals(Object) - * @since Android 1.0 */ public static boolean equals(float[] array1, float[] array2) { if (array1 == array2) { @@ -1413,7 +1374,7 @@ public class Arrays { /** * Compares the two arrays. The values are compared in the same manner as * {@code Double.equals()}. - * + * * @param array1 * the first {@code double} array. * @param array2 @@ -1422,7 +1383,6 @@ public class Arrays { * same length and the elements at each index in the two arrays are * equal, {@code false} otherwise. * @see Double#equals(Object) - * @since Android 1.0 */ public static boolean equals(double[] array1, double[] array2) { if (array1 == array2) { @@ -1442,7 +1402,7 @@ public class Arrays { /** * Compares the two arrays. - * + * * @param array1 * the first {@code boolean} array. * @param array2 @@ -1450,7 +1410,6 @@ public class Arrays { * @return {@code true} if both arrays are {@code null} or if the arrays have the * same length and the elements at each index in the two arrays are * equal, {@code false} otherwise. - * @since Android 1.0 */ public static boolean equals(boolean[] array1, boolean[] array2) { if (array1 == array2) { @@ -1469,7 +1428,7 @@ public class Arrays { /** * Compares the two arrays. - * + * * @param array1 * the first {@code Object} array. * @param array2 @@ -1477,7 +1436,6 @@ public class Arrays { * @return {@code true} if both arrays are {@code null} or if the arrays have the * same length and the elements at each index in the two arrays are * equal according to {@code equals()}, {@code false} otherwise. - * @since Android 1.0 */ public static boolean equals(Object[] array1, Object[] array2) { if (array1 == array2) { @@ -1522,7 +1480,7 @@ public class Arrays { * <p> * If either of the given arrays contain themselves as elements, the * behavior of this method is uncertain. - * + * * @param array1 * the first {@code Object} array. * @param array2 @@ -1530,7 +1488,6 @@ public class Arrays { * @return {@code true} if both arrays are {@code null} or if the arrays have the * same length and the elements at each index in the two arrays are * equal according to {@code equals()}, {@code false} otherwise. - * @since Android 1.0 */ public static boolean deepEquals(Object[] array1, Object[] array2) { if (array1 == array2) { @@ -1603,41 +1560,58 @@ public class Arrays { } private static boolean lessThan(double double1, double double2) { - long d1, d2; - long NaNbits = Double.doubleToLongBits(Double.NaN); - if ((d1 = Double.doubleToLongBits(double1)) == NaNbits) { + // A slightly specialized version of + // Double.compare(double1, double2) < 0. + + // Non-zero and non-NaN checking. + if (double1 < double2) { + return true; + } + if (double1 > double2) { return false; } - if ((d2 = Double.doubleToLongBits(double2)) == NaNbits) { - return true; + if (double1 == double2 && 0.0d != double1) { + return false; } - if (double1 == double2) { - if (d1 == d2) { - return false; - } - // check for -0 - return d1 < d2; + + // NaNs are equal to other NaNs and larger than any other double. + if (Double.isNaN(double1)) { + return false; + } else if (Double.isNaN(double2)) { + return true; } - return double1 < double2; + + // Deal with +0.0 and -0.0. + long d1 = Double.doubleToRawLongBits(double1); + long d2 = Double.doubleToRawLongBits(double2); + return d1 < d2; } private static boolean lessThan(float float1, float float2) { - int f1, f2; - int NaNbits = Float.floatToIntBits(Float.NaN); - if ((f1 = Float.floatToIntBits(float1)) == NaNbits) { + // A slightly specialized version of Float.compare(float1, float2) < 0. + + // Non-zero and non-NaN checking. + if (float1 < float2) { + return true; + } + if (float1 > float2) { return false; } - if ((f2 = Float.floatToIntBits(float2)) == NaNbits) { - return true; + if (float1 == float2 && 0.0f != float1) { + return false; } - if (float1 == float2) { - if (f1 == f2) { - return false; - } - // check for -0 - return f1 < f2; + + // NaNs are equal to other NaNs and larger than any other float + if (Float.isNaN(float1)) { + return false; + } else if (Float.isNaN(float2)) { + return true; } - return float1 < float2; + + // Deal with +0.0 and -0.0 + int f1 = Float.floatToRawIntBits(float1); + int f2 = Float.floatToRawIntBits(float2); + return f1 < f2; } private static int med3(byte[] array, int a, int b, int c) { @@ -1684,10 +1658,9 @@ public class Arrays { /** * Sorts the specified array in ascending numerical order. - * + * * @param array * the {@code byte} array to be sorted. - * @since Android 1.0 */ public static void sort(byte[] array) { sort(0, array.length, array); @@ -1695,18 +1668,17 @@ public class Arrays { /** * Sorts the specified range in the array in ascending numerical order. - * + * * @param array * the {@code byte} array to be sorted. * @param start * the start index to sort. * @param end * the last + 1 index to sort. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void sort(byte[] array, int start, int end) { if (array == null) { @@ -1718,8 +1690,8 @@ public class Arrays { private static void checkBounds(int arrLength, int start, int end) { if (start > end) { - throw new IllegalArgumentException("fromIndex(" + start //$NON-NLS-1$ - + ") > toIndex(" + end + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + throw new IllegalArgumentException("start(" + start //$NON-NLS-1$ + + ") > end(" + end + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } if (start < 0 || end > arrLength) { throw new ArrayIndexOutOfBoundsException(); @@ -1806,10 +1778,9 @@ public class Arrays { /** * Sorts the specified array in ascending numerical order. - * + * * @param array * the {@code char} array to be sorted. - * @since Android 1.0 */ public static void sort(char[] array) { sort(0, array.length, array); @@ -1817,18 +1788,17 @@ public class Arrays { /** * Sorts the specified range in the array in ascending numerical order. - * + * * @param array * the {@code char} array to be sorted. * @param start * the start index to sort. * @param end * the last + 1 index to sort. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void sort(char[] array, int start, int end) { if (array == null) { @@ -1918,11 +1888,10 @@ public class Arrays { /** * Sorts the specified array in ascending numerical order. - * + * * @param array * the {@code double} array to be sorted. * @see #sort(double[], int, int) - * @since Android 1.0 */ public static void sort(double[] array) { sort(0, array.length, array); @@ -1931,19 +1900,18 @@ public class Arrays { /** * Sorts the specified range in the array in ascending numerical order. The * values are sorted according to the order imposed by {@code Double.compareTo()}. - * + * * @param array * the {@code double} array to be sorted. * @param start * the start index to sort. * @param end * the last + 1 index to sort. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. * @see Double#compareTo(Double) - * @since Android 1.0 */ public static void sort(double[] array, int start, int end) { if (array == null) { @@ -2033,11 +2001,10 @@ public class Arrays { /** * Sorts the specified array in ascending numerical order. - * + * * @param array * the {@code float} array to be sorted. * @see #sort(float[], int, int) - * @since Android 1.0 */ public static void sort(float[] array) { sort(0, array.length, array); @@ -2046,19 +2013,18 @@ public class Arrays { /** * Sorts the specified range in the array in ascending numerical order. The * values are sorted according to the order imposed by {@code Float.compareTo()}. - * + * * @param array * the {@code float} array to be sorted. * @param start * the start index to sort. * @param end * the last + 1 index to sort. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. * @see Float#compareTo(Float) - * @since Android 1.0 */ public static void sort(float[] array, int start, int end) { if (array == null) { @@ -2148,10 +2114,9 @@ public class Arrays { /** * Sorts the specified array in ascending numerical order. - * + * * @param array * the {@code int} array to be sorted. - * @since Android 1.0 */ public static void sort(int[] array) { sort(0, array.length, array); @@ -2159,18 +2124,17 @@ public class Arrays { /** * Sorts the specified range in the array in ascending numerical order. - * + * * @param array * the {@code int} array to be sorted. * @param start * the start index to sort. * @param end * the last + 1 index to sort. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void sort(int[] array, int start, int end) { if (array == null) { @@ -2260,10 +2224,9 @@ public class Arrays { /** * Sorts the specified array in ascending numerical order. - * + * * @param array * the {@code long} array to be sorted. - * @since Android 1.0 */ public static void sort(long[] array) { sort(0, array.length, array); @@ -2271,18 +2234,17 @@ public class Arrays { /** * Sorts the specified range in the array in ascending numerical order. - * + * * @param array * the {@code long} array to be sorted. * @param start * the start index to sort. * @param end * the last + 1 index to sort. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void sort(long[] array, int start, int end) { if (array == null) { @@ -2370,7 +2332,7 @@ public class Arrays { } } -// BEGIN android-changed +// BEGIN android-note /* * <p>If this platform has an optimizing VM, check whether ComparableTimSort @@ -2405,19 +2367,22 @@ public class Arrays { // sort(a, fromIndex, toIndex, NATURAL_ORDER); // } +// END android-note + /** * Sorts the specified array in ascending natural order. - * + * * @param array * the {@code Object} array to be sorted. - * @exception ClassCastException + * @throws ClassCastException * if an element in the array does not implement {@code Comparable} * or if some elements cannot be compared to each other. * @see #sort(Object[], int, int) - * @since Android 1.0 */ public static void sort(Object[] array) { + // BEGIN android-changed ComparableTimSort.sort(array); + // END android-changed } /** @@ -2425,31 +2390,76 @@ public class Arrays { * elements must implement the {@code Comparable} interface and must be * comparable to each other without a {@code ClassCastException} being * thrown. - * + * * @param array * the {@code Object} array to be sorted. * @param start * the start index to sort. * @param end * the last + 1 index to sort. - * @exception ClassCastException + * @throws ClassCastException * if an element in the array does not implement {@code Comparable} * or some elements cannot be compared to each other. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void sort(Object[] array, int start, int end) { + // BEGIN android-changed ComparableTimSort.sort(array, start, end); + // END android-changed } + // BEGIN android-removed + /* + private static void sort(int start, int end, Object[] array) { + ... + } + private static void swap(int a, int b, Object[] arr) { + ... + } + private static void mergeSort(Object[] in, Object[] out, int start, + int end) { + ... + } + private static void mergeSort(Object[] in, Object[] out, int start, + int end, Comparator c) { + ... + } + private static int find(Object[] arr, Comparable val, int bnd, int l, int r) { + ... + } + private static int find(Object[] arr, Object val, int bnd, int l, int r, + Comparator c) { + ... + } + private static int medChar(int a, int b, int c, String[] arr, int id) { + ... + } + private static int charAt(String str, int i) { + ... + } + private static void copySwap(Object[] src, int from, Object[] dst, int to, + int len) { + ... + } + private static void stableStringSort(String[] arr, int start, + int end) { + ... + } + private static void stableStringSort(String[] arr, String[] src, + String[] dst, int start, int end, int chId) { + ... + } + */ + // END android-removed + /** * Sorts the specified range in the array using the specified {@code Comparator}. * All elements must be comparable to each other without a * {@code ClassCastException} being thrown. - * + * * @param array * the {@code Object} array to be sorted. * @param start @@ -2458,45 +2468,44 @@ public class Arrays { * the last + 1 index to sort. * @param comparator * the {@code Comparator}. - * @exception ClassCastException + * @throws ClassCastException * if elements in the array cannot be compared to each other * using the {@code Comparator}. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static <T> void sort(T[] array, int start, int end, Comparator<? super T> comparator) { + // BEGIN android-changed TimSort.sort(array, start, end, comparator); + // END android-changed } /** * Sorts the specified array using the specified {@code Comparator}. All elements * must be comparable to each other without a {@code ClassCastException} being thrown. - * + * * @param array * the {@code Object} array to be sorted. * @param comparator * the {@code Comparator}. - * @exception ClassCastException + * @throws ClassCastException * if elements in the array cannot be compared to each other * using the {@code Comparator}. - * @since Android 1.0 */ public static <T> void sort(T[] array, Comparator<? super T> comparator) { + // BEGIN android-changed TimSort.sort(array, comparator); + // END android-changed } -// END android-changed - /** * Sorts the specified array in ascending numerical order. - * + * * @param array * the {@code short} array to be sorted. - * @since Android 1.0 */ public static void sort(short[] array) { sort(0, array.length, array); @@ -2504,18 +2513,17 @@ public class Arrays { /** * Sorts the specified range in the array in ascending numerical order. - * + * * @param array * the {@code short} array to be sorted. * @param start * the start index to sort. * @param end * the last + 1 index to sort. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code start > end}. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if {@code start < 0} or {@code end > array.length}. - * @since Android 1.0 */ public static void sort(short[] array, int start, int end) { if (array == null) { @@ -2604,18 +2612,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code boolean[]} passed. * The result is surrounded by brackets ({@code "[]"}), each * element is converted to a {@code String} via the * {@link String#valueOf(boolean)} and separated by {@code ", "}. * If the array is {@code null}, then {@code "null"} is returned. - * </p> - * + * * @param array * the {@code boolean} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(boolean[] array) { if (array == null) { @@ -2636,18 +2642,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code byte[]} passed. The * result is surrounded by brackets ({@code "[]"}), each element * is converted to a {@code String} via the {@link String#valueOf(int)} and * separated by {@code ", "}. If the array is {@code null}, then * {@code "null"} is returned. - * </p> - * + * * @param array * the {@code byte} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(byte[] array) { if (array == null) { @@ -2668,18 +2672,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code char[]} passed. The * result is surrounded by brackets ({@code "[]"}), each element * is converted to a {@code String} via the {@link String#valueOf(char)} and * separated by {@code ", "}. If the array is {@code null}, then * {@code "null"} is returned. - * </p> - * + * * @param array * the {@code char} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(char[] array) { if (array == null) { @@ -2700,18 +2702,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code double[]} passed. * The result is surrounded by brackets ({@code "[]"}), each * element is converted to a {@code String} via the * {@link String#valueOf(double)} and separated by {@code ", "}. * If the array is {@code null}, then {@code "null"} is returned. - * </p> - * + * * @param array * the {@code double} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(double[] array) { if (array == null) { @@ -2732,18 +2732,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code float[]} passed. * The result is surrounded by brackets ({@code "[]"}), each * element is converted to a {@code String} via the * {@link String#valueOf(float)} and separated by {@code ", "}. * If the array is {@code null}, then {@code "null"} is returned. - * </p> - * + * * @param array * the {@code float} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(float[] array) { if (array == null) { @@ -2764,18 +2762,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code int[]} passed. The * result is surrounded by brackets ({@code "[]"}), each element * is converted to a {@code String} via the {@link String#valueOf(int)} and * separated by {@code ", "}. If the array is {@code null}, then * {@code "null"} is returned. - * </p> - * + * * @param array * the {@code int} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(int[] array) { if (array == null) { @@ -2796,18 +2792,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code long[]} passed. The * result is surrounded by brackets ({@code "[]"}), each element * is converted to a {@code String} via the {@link String#valueOf(long)} and * separated by {@code ", "}. If the array is {@code null}, then * {@code "null"} is returned. - * </p> - * + * * @param array * the {@code long} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(long[] array) { if (array == null) { @@ -2828,18 +2822,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code short[]} passed. * The result is surrounded by brackets ({@code "[]"}), each * element is converted to a {@code String} via the * {@link String#valueOf(int)} and separated by {@code ", "}. If * the array is {@code null}, then {@code "null"} is returned. - * </p> - * + * * @param array * the {@code short} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(short[] array) { if (array == null) { @@ -2860,18 +2852,16 @@ public class Arrays { } /** - * <p> * Creates a {@code String} representation of the {@code Object[]} passed. * The result is surrounded by brackets ({@code "[]"}), each * element is converted to a {@code String} via the * {@link String#valueOf(Object)} and separated by {@code ", "}. * If the array is {@code null}, then {@code "null"} is returned. - * </p> - * + * * @param array * the {@code Object} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String toString(Object[] array) { if (array == null) { @@ -2892,11 +2882,9 @@ public class Arrays { } /** - * <p> * Creates a <i>"deep"</i> {@code String} representation of the * {@code Object[]} passed, such that if the array contains other arrays, * the {@code String} representation of those arrays is generated as well. - * </p> * <p> * If any of the elements are primitive arrays, the generation is delegated * to the other {@code toString} methods in this class. If any element @@ -2904,12 +2892,11 @@ public class Arrays { * as {@code "[...]"}. If an element is an {@code Object[]}, then its * representation is generated by a recursive call to this method. All other * elements are converted via the {@link String#valueOf(Object)} method. - * </p> - * + * * @param array * the {@code Object} array to convert. * @return the {@code String} representation of {@code array}. - * @since Android 1.0 + * @since 1.5 */ public static String deepToString(Object[] array) { // Special case null to prevent NPE @@ -2923,10 +2910,8 @@ public class Arrays { } /** - * <p> * Implementation method used by {@link #deepToString(Object[])}. - * </p> - * + * * @param array * the {@code Object[]} to dive into. * @param origArrays @@ -3010,11 +2995,9 @@ public class Arrays { } /** - * <p> * Utility method used to assist the implementation of * {@link #deepToString(Object[])}. - * </p> - * + * * @param origArrays * An array of Object[] references. * @param array diff --git a/luni/src/main/java/java/util/BitSet.java b/luni/src/main/java/java/util/BitSet.java index aa60be0..d2d7c0a 100644 --- a/luni/src/main/java/java/util/BitSet.java +++ b/luni/src/main/java/java/util/BitSet.java @@ -17,6 +17,8 @@ package java.util; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serializable; import org.apache.harmony.luni.util.Msg; @@ -26,20 +28,43 @@ import org.apache.harmony.luni.util.Msg; * {@code BitSet} can be on(1) or off(0). A {@code BitSet} is created with a * given size and grows if this size is exceeded. Growth is always rounded to a * 64 bit boundary. - * - * @since Android 1.0 */ public class BitSet implements Serializable, Cloneable { private static final long serialVersionUID = 7997698588986878753L; - // Size in bits of the data type being used in the bits array - private static final int ELM_SIZE = 64; + private static final int OFFSET = 6; + + private static final int ELM_SIZE = 1 << OFFSET; + + private static final int RIGHT_BITS = ELM_SIZE - 1; + + private static final long[] TWO_N_ARRAY = new long[] { 0x1L, 0x2L, 0x4L, + 0x8L, 0x10L, 0x20L, 0x40L, 0x80L, 0x100L, 0x200L, 0x400L, 0x800L, + 0x1000L, 0x2000L, 0x4000L, 0x8000L, 0x10000L, 0x20000L, 0x40000L, + 0x80000L, 0x100000L, 0x200000L, 0x400000L, 0x800000L, 0x1000000L, + 0x2000000L, 0x4000000L, 0x8000000L, 0x10000000L, 0x20000000L, + 0x40000000L, 0x80000000L, 0x100000000L, 0x200000000L, 0x400000000L, + 0x800000000L, 0x1000000000L, 0x2000000000L, 0x4000000000L, + 0x8000000000L, 0x10000000000L, 0x20000000000L, 0x40000000000L, + 0x80000000000L, 0x100000000000L, 0x200000000000L, 0x400000000000L, + 0x800000000000L, 0x1000000000000L, 0x2000000000000L, + 0x4000000000000L, 0x8000000000000L, 0x10000000000000L, + 0x20000000000000L, 0x40000000000000L, 0x80000000000000L, + 0x100000000000000L, 0x200000000000000L, 0x400000000000000L, + 0x800000000000000L, 0x1000000000000000L, 0x2000000000000000L, + 0x4000000000000000L, 0x8000000000000000L }; private long[] bits; + private transient boolean needClear; + + private transient int actualArrayLength; + + private transient boolean isLengthActual; + /** * Create a new {@code BitSet} with size equal to 64 bits. - * + * * @see #clear(int) * @see #set(int) * @see #clear() @@ -47,17 +72,18 @@ public class BitSet implements Serializable, Cloneable { * @see #set(int, boolean) * @see #set(int, int) * @see #set(int, int, boolean) - * @since Android 1.0 */ public BitSet() { - this(64); + bits = new long[1]; + actualArrayLength = 0; + isLengthActual = true; } /** * Create a new {@code BitSet} with size equal to nbits. If nbits is not a * multiple of 64, then create a {@code BitSet} with size nbits rounded to * the next closest multiple of 64. - * + * * @param nbits * the size of the bit set. * @throws NegativeArraySizeException @@ -69,31 +95,34 @@ public class BitSet implements Serializable, Cloneable { * @see #set(int, boolean) * @see #set(int, int) * @see #set(int, int, boolean) - * @since Android 1.0 */ public BitSet(int nbits) { - if (nbits >= 0) { - bits = new long[(nbits / ELM_SIZE) + (nbits % ELM_SIZE > 0 ? 1 : 0)]; - } else { + if (nbits < 0) { throw new NegativeArraySizeException(); } + bits = new long[(nbits >> OFFSET) + ((nbits & RIGHT_BITS) > 0 ? 1 : 0)]; + actualArrayLength = 0; + isLengthActual = true; } /** * Private constructor called from get(int, int) method - * + * * @param bits * the size of the bit set */ - private BitSet(long[] bits) { + private BitSet(long[] bits, boolean needClear, int actualArrayLength, + boolean isLengthActual) { this.bits = bits; + this.needClear = needClear; + this.actualArrayLength = actualArrayLength; + this.isLengthActual = isLengthActual; } /** * Creates a copy of this {@code BitSet}. - * + * * @return a copy of this {@code BitSet}. - * @since Android 1.0 */ @Override public Object clone() { @@ -110,13 +139,12 @@ public class BitSet implements Serializable, Cloneable { * Compares the argument to this {@code BitSet} and returns whether they are * equal. The object must be an instance of {@code BitSet} with the same * bits set. - * + * * @param obj * the {@code BitSet} object to compare. * @return a {@code boolean} indicating whether or not this {@code BitSet} and * {@code obj} are equal. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object obj) { @@ -125,10 +153,13 @@ public class BitSet implements Serializable, Cloneable { } if (obj instanceof BitSet) { long[] bsBits = ((BitSet) obj).bits; - int length1 = bits.length, length2 = bsBits.length; + int length1 = this.actualArrayLength, length2 = ((BitSet) obj).actualArrayLength; + if (this.isLengthActual && ((BitSet) obj).isLengthActual + && length1 != length2) { + return false; + } // If one of the BitSets is larger than the other, check to see if - // any of - // its extra bits are set. If so return false. + // any of its extra bits are set. If so return false. if (length1 <= length2) { for (int i = 0; i < length1; i++) { if (bits[i] != bsBits[i]) { @@ -160,35 +191,29 @@ public class BitSet implements Serializable, Cloneable { /** * Increase the size of the internal array to accommodate {@code pos} bits. * The new array max index will be a multiple of 64. - * - * @param pos + * + * @param len * the index the new array needs to be able to access. - * @since Android 1.0 */ - private void growBits(int pos) { - pos++; // Inc to get correct bit count - long[] tempBits = new long[(pos / ELM_SIZE) - + (pos % ELM_SIZE > 0 ? 1 : 0)]; - System.arraycopy(bits, 0, tempBits, 0, bits.length); + private final void growLength(int len) { + long[] tempBits = new long[Math.max(len, bits.length * 2)]; + System.arraycopy(bits, 0, tempBits, 0, this.actualArrayLength); bits = tempBits; } /** * Computes the hash code for this {@code BitSet}. If two {@code BitSet}s are equal * the have to return the same result for {@code hashCode()}. - * + * * @return the {@code int} representing the hash code for this bit * set. * @see #equals * @see java.util.Hashtable - * @since Android 1.0 */ @Override public int hashCode() { long x = 1234; - // for (int i = 0, length = bits.length; i < length; i+=2) - // x ^= (bits[i] + ((long)bits[i+1] << 32)) * (i/2 + 1); - for (int i = 0, length = bits.length; i < length; i++) { + for (int i = 0, length = actualArrayLength; i < length; i++) { x ^= bits[i] * (i + 1); } return (int) ((x >> 32) ^ x); @@ -197,7 +222,7 @@ public class BitSet implements Serializable, Cloneable { /** * Retrieves the bit at index {@code pos}. Grows the {@code BitSet} if * {@code pos > size}. - * + * * @param pos * the index of the bit to be retrieved. * @return {@code true} if the bit at {@code pos} is set, @@ -211,89 +236,98 @@ public class BitSet implements Serializable, Cloneable { * @see #set(int, boolean) * @see #set(int, int) * @see #set(int, int, boolean) - * @since Android 1.0 */ public boolean get(int pos) { - if (pos >= 0) { - if (pos < bits.length * ELM_SIZE) { - return (bits[pos / ELM_SIZE] & (1L << (pos % ELM_SIZE))) != 0; - } - return false; + if (pos < 0) { + // Negative index specified + throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ } - // Negative index specified - throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + + int arrayPos = pos >> OFFSET; + if (arrayPos < actualArrayLength) { + return (bits[arrayPos] & TWO_N_ARRAY[pos & RIGHT_BITS]) != 0; + } + return false; } /** * Retrieves the bits starting from {@code pos1} to {@code pos2} and returns * back a new bitset made of these bits. Grows the {@code BitSet} if * {@code pos2 > size}. - * + * * @param pos1 - * beginning position. + * inclusive beginning position. * @param pos2 - * ending position. + * exclusive ending position. * @return new bitset of the range specified. * @throws IndexOutOfBoundsException * if {@code pos1} or {@code pos2} is negative, or if * {@code pos2} is smaller than {@code pos1}. * @see #get(int) - * @since Android 1.0 */ public BitSet get(int pos1, int pos2) { - if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) { - int last = (bits.length * ELM_SIZE); - if (pos1 >= last || pos1 == pos2) { - return new BitSet(0); - } - if (pos2 > last) { - pos2 = last; - } + if (pos1 < 0 || pos2 < 0 || pos2 < pos1) { + throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + } - int idx1 = pos1 / ELM_SIZE; - int idx2 = (pos2 - 1) / ELM_SIZE; - long factor1 = (~0L) << (pos1 % ELM_SIZE); - long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE)); + int last = actualArrayLength << OFFSET; + if (pos1 >= last || pos1 == pos2) { + return new BitSet(0); + } + if (pos2 > last) { + pos2 = last; + } - if (idx1 == idx2) { - long result = (bits[idx1] & (factor1 & factor2)) >>> (pos1 % ELM_SIZE); - return new BitSet(new long[] { result }); - } - long[] newbits = new long[idx2 - idx1 + 1]; - // first fill in the first and last indexes in the new bitset - newbits[0] = bits[idx1] & factor1; - newbits[newbits.length - 1] = bits[idx2] & factor2; - - // fill in the in between elements of the new bitset - for (int i = 1; i < idx2 - idx1; i++) { - newbits[i] = bits[idx1 + i]; + int idx1 = pos1 >> OFFSET; + int idx2 = (pos2 - 1) >> OFFSET; + long factor1 = (~0L) << (pos1 & RIGHT_BITS); + long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS)); + + if (idx1 == idx2) { + long result = (bits[idx1] & (factor1 & factor2)) >>> (pos1 % ELM_SIZE); + if (result == 0) { + return new BitSet(0); } + return new BitSet(new long[] { result }, needClear, 1, true); + } + long[] newbits = new long[idx2 - idx1 + 1]; + // first fill in the first and last indexes in the new bitset + newbits[0] = bits[idx1] & factor1; + newbits[newbits.length - 1] = bits[idx2] & factor2; + + // fill in the in between elements of the new bitset + for (int i = 1; i < idx2 - idx1; i++) { + newbits[i] = bits[idx1 + i]; + } - // shift all the elements in the new bitset to the right by pos1 - // % ELM_SIZE - int numBitsToShift = pos1 % ELM_SIZE; - if (numBitsToShift != 0) { - for (int i = 0; i < newbits.length; i++) { - // shift the current element to the right regardless of - // sign - newbits[i] = newbits[i] >>> (numBitsToShift); - - // apply the last x bits of newbits[i+1] to the current - // element - if (i != newbits.length - 1) { - newbits[i] |= newbits[i + 1] << (ELM_SIZE - (numBitsToShift)); - } + // shift all the elements in the new bitset to the right by pos1 + // % ELM_SIZE + int numBitsToShift = pos1 & RIGHT_BITS; + int actualLen = newbits.length; + if (numBitsToShift != 0) { + for (int i = 0; i < newbits.length; i++) { + // shift the current element to the right regardless of + // sign + newbits[i] = newbits[i] >>> (numBitsToShift); + + // apply the last x bits of newbits[i+1] to the current + // element + if (i != newbits.length - 1) { + newbits[i] |= newbits[i + 1] << (ELM_SIZE - (numBitsToShift)); + } + if (newbits[i] != 0) { + actualLen = i + 1; } } - return new BitSet(newbits); } - throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + return new BitSet(newbits, needClear, actualLen, + newbits[actualLen - 1] != 0); } /** * Sets the bit at index {@code pos} to 1. Grows the {@code BitSet} if * {@code pos > size}. - * + * * @param pos * the index of the bit to set. * @throws IndexOutOfBoundsException @@ -301,23 +335,28 @@ public class BitSet implements Serializable, Cloneable { * @see #clear(int) * @see #clear() * @see #clear(int, int) - * @since Android 1.0 */ public void set(int pos) { - if (pos >= 0) { - if (pos >= bits.length * ELM_SIZE) { - growBits(pos); - } - bits[pos / ELM_SIZE] |= 1L << (pos % ELM_SIZE); - } else { + if (pos < 0) { throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ } + + int len = (pos >> OFFSET) + 1; + if (len > bits.length) { + growLength(len); + } + bits[len - 1] |= TWO_N_ARRAY[pos & RIGHT_BITS]; + if (len > actualArrayLength) { + actualArrayLength = len; + isLengthActual = true; + } + needClear(); } /** * Sets the bit at index {@code pos} to {@code val}. Grows the * {@code BitSet} if {@code pos > size}. - * + * * @param pos * the index of the bit to set. * @param val @@ -325,7 +364,6 @@ public class BitSet implements Serializable, Cloneable { * @throws IndexOutOfBoundsException * if {@code pos} is negative. * @see #set(int) - * @since Android 1.0 */ public void set(int pos, boolean val) { if (val) { @@ -338,60 +376,68 @@ public class BitSet implements Serializable, Cloneable { /** * Sets the bits starting from {@code pos1} to {@code pos2}. Grows the * {@code BitSet} if {@code pos2 > size}. - * + * * @param pos1 - * beginning position. + * inclusive beginning position. * @param pos2 - * ending position. + * exclusive ending position. * @throws IndexOutOfBoundsException * if {@code pos1} or {@code pos2} is negative, or if * {@code pos2} is smaller than {@code pos1}. * @see #set(int) - * @since Android 1.0 */ public void set(int pos1, int pos2) { - if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) { - if (pos1 == pos2) { - return; - } - if (pos2 >= bits.length * ELM_SIZE) { - growBits(pos2); - } + if (pos1 < 0 || pos2 < 0 || pos2 < pos1) { + throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + } - int idx1 = pos1 / ELM_SIZE; - int idx2 = (pos2 - 1) / ELM_SIZE; - long factor1 = (~0L) << (pos1 % ELM_SIZE); - long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE)); + if (pos1 == pos2) { + return; + } + int len2 = ((pos2 - 1) >> OFFSET) + 1; + if (len2 > bits.length) { + growLength(len2); + } - if (idx1 == idx2) { - bits[idx1] |= (factor1 & factor2); - } else { - bits[idx1] |= factor1; - bits[idx2] |= factor2; - for (int i = idx1 + 1; i < idx2; i++) { - bits[i] |= (~0L); - } - } + int idx1 = pos1 >> OFFSET; + int idx2 = (pos2 - 1) >> OFFSET; + long factor1 = (~0L) << (pos1 & RIGHT_BITS); + long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS)); + + if (idx1 == idx2) { + bits[idx1] |= (factor1 & factor2); } else { - throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + bits[idx1] |= factor1; + bits[idx2] |= factor2; + for (int i = idx1 + 1; i < idx2; i++) { + bits[i] |= (~0L); + } + } + if (idx2 + 1 > actualArrayLength) { + actualArrayLength = idx2 + 1; + isLengthActual = true; } + needClear(); + } + + private void needClear() { + this.needClear = true; } /** * Sets the bits starting from {@code pos1} to {@code pos2} to the given * {@code val}. Grows the {@code BitSet} if {@code pos2 > size}. - * + * * @param pos1 - * beginning position. + * inclusive beginning position. * @param pos2 - * ending position. + * exclusive ending position. * @param val * value to set these bits. * @throws IndexOutOfBoundsException * if {@code pos1} or {@code pos2} is negative, or if * {@code pos2} is smaller than {@code pos1}. * @see #set(int,int) - * @since Android 1.0 */ public void set(int pos1, int pos2, boolean val) { if (val) { @@ -403,159 +449,183 @@ public class BitSet implements Serializable, Cloneable { /** * Clears all the bits in this {@code BitSet}. - * + * * @see #clear(int) * @see #clear(int, int) - * @since Android 1.0 */ public void clear() { - for (int i = 0; i < bits.length; i++) { - bits[i] = 0L; + if (needClear) { + for (int i = 0; i < bits.length; i++) { + bits[i] = 0L; + } + actualArrayLength = 0; + isLengthActual = true; + needClear = false; } } /** * Clears the bit at index {@code pos}. Grows the {@code BitSet} if * {@code pos > size}. - * + * * @param pos * the index of the bit to clear. * @throws IndexOutOfBoundsException * if {@code pos} is negative. * @see #clear(int, int) - * @since Android 1.0 */ public void clear(int pos) { - if (pos >= 0) { - if (pos < bits.length * ELM_SIZE) { - bits[pos / ELM_SIZE] &= ~(1L << (pos % ELM_SIZE)); - } - } else { + if (pos < 0) { // Negative index specified throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ } + + if (!needClear) { + return; + } + int arrayPos = pos >> OFFSET; + if (arrayPos < actualArrayLength) { + bits[arrayPos] &= ~(TWO_N_ARRAY[pos & RIGHT_BITS]); + if (bits[actualArrayLength - 1] == 0) { + isLengthActual = false; + } + } } /** * Clears the bits starting from {@code pos1} to {@code pos2}. Grows the * {@code BitSet} if {@code pos2 > size}. - * + * * @param pos1 - * beginning position. + * inclusive beginning position. * @param pos2 - * ending position. + * exclusive ending position. * @throws IndexOutOfBoundsException * if {@code pos1} or {@code pos2} is negative, or if * {@code pos2} is smaller than {@code pos1}. * @see #clear(int) - * @since Android 1.0 */ public void clear(int pos1, int pos2) { - if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) { - int last = (bits.length * ELM_SIZE); - if (pos1 >= last || pos1 == pos2) { - return; - } - if (pos2 > last) { - pos2 = last; - } + if (pos1 < 0 || pos2 < 0 || pos2 < pos1) { + throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + } - int idx1 = pos1 / ELM_SIZE; - int idx2 = (pos2 - 1) / ELM_SIZE; - long factor1 = (~0L) << (pos1 % ELM_SIZE); - long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE)); + if (!needClear) { + return; + } + int last = (actualArrayLength << OFFSET); + if (pos1 >= last || pos1 == pos2) { + return; + } + if (pos2 > last) { + pos2 = last; + } - if (idx1 == idx2) { - bits[idx1] &= ~(factor1 & factor2); - } else { - bits[idx1] &= ~factor1; - bits[idx2] &= ~factor2; - for (int i = idx1 + 1; i < idx2; i++) { - bits[i] = 0L; - } - } + int idx1 = pos1 >> OFFSET; + int idx2 = (pos2 - 1) >> OFFSET; + long factor1 = (~0L) << (pos1 & RIGHT_BITS); + long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS)); + + if (idx1 == idx2) { + bits[idx1] &= ~(factor1 & factor2); } else { - throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + bits[idx1] &= ~factor1; + bits[idx2] &= ~factor2; + for (int i = idx1 + 1; i < idx2; i++) { + bits[i] = 0L; + } + } + if ((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0)) { + isLengthActual = false; } } /** * Flips the bit at index {@code pos}. Grows the {@code BitSet} if * {@code pos > size}. - * + * * @param pos * the index of the bit to flip. * @throws IndexOutOfBoundsException * if {@code pos} is negative. * @see #flip(int, int) - * @since Android 1.0 */ public void flip(int pos) { - if (pos >= 0) { - if (pos >= bits.length * ELM_SIZE) { - growBits(pos); - } - bits[pos / ELM_SIZE] ^= 1L << (pos % ELM_SIZE); - } else { + if (pos < 0) { throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ } + + int len = (pos >> OFFSET) + 1; + if (len > bits.length) { + growLength(len); + } + bits[len - 1] ^= TWO_N_ARRAY[pos & RIGHT_BITS]; + if (len > actualArrayLength) { + actualArrayLength = len; + } + isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0)); + needClear(); } /** * Flips the bits starting from {@code pos1} to {@code pos2}. Grows the * {@code BitSet} if {@code pos2 > size}. - * + * * @param pos1 - * beginning position. + * inclusive beginning position. * @param pos2 - * ending position. + * exclusive ending position. * @throws IndexOutOfBoundsException * if {@code pos1} or {@code pos2} is negative, or if * {@code pos2} is smaller than {@code pos1}. * @see #flip(int) - * @since Android 1.0 */ public void flip(int pos1, int pos2) { - if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) { - if (pos1 == pos2) { - return; - } - if (pos2 >= bits.length * ELM_SIZE) { - growBits(pos2); - } + if (pos1 < 0 || pos2 < 0 || pos2 < pos1) { + throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + } + + if (pos1 == pos2) { + return; + } + int len2 = ((pos2 - 1) >> OFFSET) + 1; + if (len2 > bits.length) { + growLength(len2); + } - int idx1 = pos1 / ELM_SIZE; - int idx2 = (pos2 - 1) / ELM_SIZE; - long factor1 = (~0L) << (pos1 % ELM_SIZE); - long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE)); + int idx1 = pos1 >> OFFSET; + int idx2 = (pos2 - 1) >> OFFSET; + long factor1 = (~0L) << (pos1 & RIGHT_BITS); + long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS)); - if (idx1 == idx2) { - bits[idx1] ^= (factor1 & factor2); - } else { - bits[idx1] ^= factor1; - bits[idx2] ^= factor2; - for (int i = idx1 + 1; i < idx2; i++) { - bits[i] ^= (~0L); - } - } + if (idx1 == idx2) { + bits[idx1] ^= (factor1 & factor2); } else { - throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + bits[idx1] ^= factor1; + bits[idx2] ^= factor2; + for (int i = idx1 + 1; i < idx2; i++) { + bits[i] ^= (~0L); + } } + if (len2 > actualArrayLength) { + actualArrayLength = len2; + } + isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0)); + needClear(); } /** * Checks if these two {@code BitSet}s have at least one bit set to true in the same * position. - * + * * @param bs * {@code BitSet} used to calculate the intersection. * @return {@code true} if bs intersects with this {@code BitSet}, * {@code false} otherwise. - * @since Android 1.0 */ public boolean intersects(BitSet bs) { long[] bsBits = bs.bits; - int length1 = bits.length, length2 = bsBits.length; + int length1 = actualArrayLength, length2 = bs.actualArrayLength; if (length1 <= length2) { for (int i = 0; i < length1; i++) { @@ -575,19 +645,20 @@ public class BitSet implements Serializable, Cloneable { } /** - * Performs the logical AND of this {@code BitSet} with another + * Performs the logical AND of this {@code BitSet} with another * {@code BitSet}. The values of this {@code BitSet} are changed accordingly. - * + * * @param bs * {@code BitSet} to AND with. * @see #or * @see #xor - * @since Android 1.0 */ - public void and(BitSet bs) { long[] bsBits = bs.bits; - int length1 = bits.length, length2 = bsBits.length; + if (!needClear) { + return; + } + int length1 = actualArrayLength, length2 = bs.actualArrayLength; if (length1 <= length2) { for (int i = 0; i < length1; i++) { bits[i] &= bsBits[i]; @@ -599,109 +670,151 @@ public class BitSet implements Serializable, Cloneable { for (int i = length2; i < length1; i++) { bits[i] = 0; } + actualArrayLength = length2; } + isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0)); } /** * Clears all bits in the receiver which are also set in the parameter * {@code BitSet}. The values of this {@code BitSet} are changed accordingly. - * + * * @param bs * {@code BitSet} to ANDNOT with. - * @since Android 1.0 */ public void andNot(BitSet bs) { long[] bsBits = bs.bits; - int range = bits.length < bsBits.length ? bits.length : bsBits.length; + if (!needClear) { + return; + } + int range = actualArrayLength < bs.actualArrayLength ? actualArrayLength + : bs.actualArrayLength; for (int i = 0; i < range; i++) { bits[i] &= ~bsBits[i]; } + + if (actualArrayLength < range) { + actualArrayLength = range; + } + isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0)); } /** * Performs the logical OR of this {@code BitSet} with another {@code BitSet}. * The values of this {@code BitSet} are changed accordingly. - * + * * @param bs * {@code BitSet} to OR with. * @see #xor * @see #and - * @since Android 1.0 */ public void or(BitSet bs) { - int nbits = bs.length(); - int length = nbits / ELM_SIZE + (nbits % ELM_SIZE > 0 ? 1 : 0); - if (length > bits.length) { - growBits(nbits - 1); - } - long[] bsBits = bs.bits; - for (int i = 0; i < length; i++) { - bits[i] |= bsBits[i]; + int bsActualLen = bs.getActualArrayLength(); + if (bsActualLen > bits.length) { + long[] tempBits = new long[bsActualLen]; + System.arraycopy(bs.bits, 0, tempBits, 0, bs.actualArrayLength); + for (int i = 0; i < actualArrayLength; i++) { + tempBits[i] |= bits[i]; + } + bits = tempBits; + actualArrayLength = bsActualLen; + isLengthActual = true; + } else { + long[] bsBits = bs.bits; + for (int i = 0; i < bsActualLen; i++) { + bits[i] |= bsBits[i]; + } + if (bsActualLen > actualArrayLength) { + actualArrayLength = bsActualLen; + isLengthActual = true; + } } + needClear(); } /** * Performs the logical XOR of this {@code BitSet} with another {@code BitSet}. * The values of this {@code BitSet} are changed accordingly. - * + * * @param bs * {@code BitSet} to XOR with. * @see #or * @see #and - * @since Android 1.0 */ public void xor(BitSet bs) { - int nbits = bs.length(); - int length = nbits / ELM_SIZE + (nbits % ELM_SIZE > 0 ? 1 : 0); - if (length > bits.length) { - growBits(nbits - 1); - } - long[] bsBits = bs.bits; - for (int i = 0; i < length; i++) { - bits[i] ^= bsBits[i]; + int bsActualLen = bs.getActualArrayLength(); + if (bsActualLen > bits.length) { + long[] tempBits = new long[bsActualLen]; + System.arraycopy(bs.bits, 0, tempBits, 0, bs.actualArrayLength); + for (int i = 0; i < actualArrayLength; i++) { + tempBits[i] ^= bits[i]; + } + bits = tempBits; + actualArrayLength = bsActualLen; + isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0)); + } else { + long[] bsBits = bs.bits; + for (int i = 0; i < bsActualLen; i++) { + bits[i] ^= bsBits[i]; + } + if (bsActualLen > actualArrayLength) { + actualArrayLength = bsActualLen; + isLengthActual = true; + } } - + needClear(); } /** * Returns the number of bits this {@code BitSet} has. - * + * * @return the number of bits contained in this {@code BitSet}. * @see #length - * @since Android 1.0 */ public int size() { - return bits.length * ELM_SIZE; + return bits.length << OFFSET; } /** * Returns the number of bits up to and including the highest bit set. - * + * * @return the length of the {@code BitSet}. - * @since Android 1.0 */ public int length() { - int idx = bits.length - 1; + int idx = actualArrayLength - 1; while (idx >= 0 && bits[idx] == 0) { --idx; } + actualArrayLength = idx + 1; if (idx == -1) { return 0; } int i = ELM_SIZE - 1; long val = bits[idx]; - while ((val & (1L << i)) == 0 && i > 0) { + while ((val & (TWO_N_ARRAY[i])) == 0 && i > 0) { i--; } - return idx * ELM_SIZE + i + 1; + return (idx << OFFSET) + i + 1; + } + + private final int getActualArrayLength() { + if (isLengthActual) { + return actualArrayLength; + } + int idx = actualArrayLength - 1; + while (idx >= 0 && bits[idx] == 0) { + --idx; + } + actualArrayLength = idx + 1; + isLengthActual = true; + return actualArrayLength; } /** * Returns a string containing a concise, human-readable description of the * receiver. - * + * * @return a comma delimited list of the indices of all bits that are set. - * @since Android 1.0 */ @Override public String toString() { @@ -715,7 +828,7 @@ public class BitSet implements Serializable, Cloneable { continue; } for (int j = 0; j < ELM_SIZE; j++) { - if (((bits[i] & (1L << j)) != 0)) { + if (((bits[i] & (TWO_N_ARRAY[j])) != 0)) { if (comma) { sb.append(", "); //$NON-NLS-1$ } @@ -731,131 +844,152 @@ public class BitSet implements Serializable, Cloneable { /** * Returns the position of the first bit that is {@code true} on or after {@code pos}. - * + * * @param pos * the starting position (inclusive). * @return -1 if there is no bits that are set to {@code true} on or after {@code pos}. - * @since Android 1.0 */ public int nextSetBit(int pos) { - if (pos >= 0) { - if (pos >= bits.length * ELM_SIZE) { - return -1; - } - - int idx = pos / ELM_SIZE; - // first check in the same bit set element - if (bits[idx] != 0L) { - for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) { - if (((bits[idx] & (1L << j)) != 0)) { - return idx * ELM_SIZE + j; - } - } + if (pos < 0) { + throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + } - } - idx++; - while (idx < bits.length && bits[idx] == 0L) { - idx++; - } - if (idx == bits.length) { - return -1; - } + if (pos >= actualArrayLength << OFFSET) { + return -1; + } - // we know for sure there is a bit set to true in this element - // since the bitset value is not 0L - for (int j = 0; j < ELM_SIZE; j++) { - if (((bits[idx] & (1L << j)) != 0)) { - return idx * ELM_SIZE + j; + int idx = pos >> OFFSET; + // first check in the same bit set element + if (bits[idx] != 0L) { + for (int j = pos & RIGHT_BITS; j < ELM_SIZE; j++) { + if (((bits[idx] & (TWO_N_ARRAY[j])) != 0)) { + return (idx << OFFSET) + j; } } + } + idx++; + while (idx < actualArrayLength && bits[idx] == 0L) { + idx++; + } + if (idx == actualArrayLength) { return -1; } - throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + + // we know for sure there is a bit set to true in this element + // since the bitset value is not 0L + for (int j = 0; j < ELM_SIZE; j++) { + if (((bits[idx] & (TWO_N_ARRAY[j])) != 0)) { + return (idx << OFFSET) + j; + } + } + + return -1; } /** * Returns the position of the first bit that is {@code false} on or after {@code pos}. - * + * * @param pos * the starting position (inclusive). * @return the position of the next bit set to {@code false}, even if it is further * than this {@code BitSet}'s size. - * @since Android 1.0 */ public int nextClearBit(int pos) { - if (pos >= 0) { - int bssize = bits.length * ELM_SIZE; - if (pos >= bssize) { - return pos; - } - - int idx = pos / ELM_SIZE; - // first check in the same bit set element - if (bits[idx] != (~0L)) { - for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) { - if (((bits[idx] & (1L << j)) == 0)) { - return idx * ELM_SIZE + j; - } - } + if (pos < 0) { + throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + } - } - idx++; - while (idx < bits.length && bits[idx] == (~0L)) { - idx++; - } - if (idx == bits.length) { - return bssize; - } + int length = actualArrayLength; + int bssize = length << OFFSET; + if (pos >= bssize) { + return pos; + } - // we know for sure there is a bit set to true in this element - // since the bitset value is not 0L - for (int j = 0; j < ELM_SIZE; j++) { - if (((bits[idx] & (1L << j)) == 0)) { + int idx = pos >> OFFSET; + // first check in the same bit set element + if (bits[idx] != (~0L)) { + for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) { + if (((bits[idx] & (TWO_N_ARRAY[j])) == 0)) { return idx * ELM_SIZE + j; } } - + } + idx++; + while (idx < length && bits[idx] == (~0L)) { + idx++; + } + if (idx == length) { return bssize; } - throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$ + + // we know for sure there is a bit set to true in this element + // since the bitset value is not 0L + for (int j = 0; j < ELM_SIZE; j++) { + if (((bits[idx] & (TWO_N_ARRAY[j])) == 0)) { + return (idx << OFFSET) + j; + } + } + + return bssize; } /** * Returns true if all the bits in this {@code BitSet} are set to false. - * + * * @return {@code true} if the {@code BitSet} is empty, * {@code false} otherwise. - * @since Android 1.0 */ public boolean isEmpty() { - for (int idx = 0; idx < bits.length; idx++) { + if (!needClear) { + return true; + } + int length = bits.length; + for (int idx = 0; idx < length; idx++) { if (bits[idx] != 0L) { return false; } } - return true; } /** * Returns the number of bits that are {@code true} in this {@code BitSet}. - * + * * @return the number of {@code true} bits in the set. - * @since Android 1.0 */ public int cardinality() { + if (!needClear) { + return 0; + } int count = 0; - for (int idx = 0; idx < bits.length; idx++) { - long temp = bits[idx]; - if (temp != 0L) { - for (int i = 0; i < ELM_SIZE; i++) { - if ((temp & (1L << i)) != 0L) { - count++; - } - } - } + int length = bits.length; + // FIXME: need to test performance, if still not satisfied, change it to + // 256-bits table based + for (int idx = 0; idx < length; idx++) { + count += pop(bits[idx] & 0xffffffffL); + count += pop(bits[idx] >>> 32); } return count; } + + private final int pop(long x) { + // BEGIN android-note + // delegate to Integer.bitCount(i); consider using native code + // END android-note + x = x - ((x >>> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >>> 2) & 0x33333333); + x = (x + (x >>> 4)) & 0x0f0f0f0f; + x = x + (x >>> 8); + x = x + (x >>> 16); + return (int) x & 0x0000003f; + } + + private void readObject(ObjectInputStream ois) throws IOException, + ClassNotFoundException { + ois.defaultReadObject(); + this.isLengthActual = false; + this.actualArrayLength = bits.length; + this.needClear = this.getActualArrayLength() != 0; + } } diff --git a/luni/src/main/java/java/util/Calendar.java b/luni/src/main/java/java/util/Calendar.java index 98840b2..088347d 100644 --- a/luni/src/main/java/java/util/Calendar.java +++ b/luni/src/main/java/java/util/Calendar.java @@ -14,27 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2008, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ package java.util; - import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamField; import java.io.Serializable; -// BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. -// END android-note /** * {@code Calendar} is an abstract base class for converting between a * {@code Date} object and a set of integer fields such as @@ -42,22 +30,22 @@ import java.io.Serializable; * {@code HOUR}, and so on. (A {@code Date} object represents a * specific instant in time with millisecond precision. See {@link Date} for * information about the {@code Date} class.) - * + * * <p> * Subclasses of {@code Calendar} interpret a {@code Date} * according to the rules of a specific calendar system. - * + * * <p> * Like other locale-sensitive classes, {@code Calendar} provides a class * method, {@code getInstance}, for getting a default instance of * this class for general use. {@code Calendar}'s {@code getInstance} method * returns a calendar whose locale is based on system settings and whose time fields * have been initialized with the current date and time: <blockquote> - * + * * <pre>Calendar rightNow = Calendar.getInstance()</pre> - * + * * </blockquote> - * + * * <p> * A {@code Calendar} object can produce all the time field values needed * to implement the date-time formatting for a particular language and calendar @@ -68,7 +56,7 @@ import java.io.Serializable; * Other values are defined by the concrete subclass, such as {@code ERA} * and {@code YEAR}. See individual field documentation and subclass * documentation for details. - * + * * <p> * When a {@code Calendar} is <em>lenient</em>, it accepts a wider * range of field values than it produces. For example, a lenient @@ -79,14 +67,14 @@ import java.io.Serializable; * by {@code get()}, they normalize them. For example, a * {@code GregorianCalendar} always produces {@code DAY_OF_MONTH} * values between 1 and the length of the month. - * + * * <p> * {@code Calendar} defines a locale-specific seven day week using two * parameters: the first day of the week and the minimal days in first week * (from 1 to 7). These numbers are taken from the locale resource data when a * {@code Calendar} is constructed. They may also be specified explicitly * through the API. - * + * * <p> * When setting or getting the {@code WEEK_OF_MONTH} or * {@code WEEK_OF_YEAR} fields, {@code Calendar} must determine @@ -99,76 +87,74 @@ import java.io.Serializable; * be different. For example, a specific {@code Calendar} subclass may * designate the week before week 1 of a year as week <em>n</em> of the * previous year. - * + * * <p> * When computing a {@code Date} from time fields, two special * circumstances may arise: there may be insufficient information to compute the * {@code Date} (such as only year and month but no day in the month), or * there may be inconsistent information (such as "Tuesday, July 15, 1996" -- * July 15, 1996 is actually a Monday). - * + * * <p> * <strong>Insufficient information.</strong> The calendar will use default * information to specify the missing fields. This may vary by calendar; for the * Gregorian calendar, the default for a field is the same as that of the start * of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc. - * + * * <p> * <strong>Inconsistent information.</strong> If fields conflict, the calendar * will give preference to fields set more recently. For example, when * determining the day, the calendar will look for one of the following * combinations of fields. The most recent combination, as determined by the * most recently set single field, will be used. - * + * * <blockquote> - * + * * <pre> * MONTH + DAY_OF_MONTH * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK * DAY_OF_YEAR * DAY_OF_WEEK + WEEK_OF_YEAR</pre> - * + * * </blockquote> - * + * * For the time of day: - * + * * <blockquote> - * + * * <pre> * HOUR_OF_DAY * AM_PM + HOUR</pre> - * + * * </blockquote> - * + * * <p> * <strong>Note:</strong> There are certain possible ambiguities in * interpretation of certain singular times, which are resolved in the following * ways: * <ol> * <li> 24:00:00 "belongs" to the following day. That is, 23:59 on Dec 31, 1969 - * < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970 form a sequence of - * three consecutive minutes in time. - * + * < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970 form a sequence of + * three consecutive minutes in time. + * * <li> Although historically not precise, midnight also belongs to "am", and * noon belongs to "pm", so on the same day, we have 12:00 am (midnight) < 12:01 am, * and 12:00 pm (noon) < 12:01 pm * </ol> - * + * * <p> * The date or time format strings are not part of the definition of a calendar, * as those must be modifiable or overridable by the user at runtime. Use * {@link java.text.DateFormat} to format dates. - * + * * <p> * <strong>Field manipulation methods</strong> - * </p> - * + * * <p> * {@code Calendar} fields can be changed using three methods: * {@code set()}, {@code add()}, and {@code roll()}. - * </p> - * + * * <p> * <strong>{@code set(f, value)}</strong> changes field {@code f} * to {@code value}. In addition, it sets an internal member variable to @@ -182,8 +168,7 @@ import java.io.Serializable; * the calendar system. In addition, {@code get(f)} will not necessarily * return {@code value} after the fields have been recomputed. The * specifics are determined by the concrete calendar class. - * </p> - * + * * <p> * <em>Example</em>: Consider a {@code GregorianCalendar} originally * set to August 31, 1999. Calling <code>set(Calendar.MONTH, @@ -193,15 +178,13 @@ import java.io.Serializable; * then called. However, a call to {@code set(Calendar.DAY_OF_MONTH, 30)} * before the call to {@code getTime()} sets the calendar to September * 30, 1999, since no recomputation occurs after {@code set()} itself. - * </p> - * + * * <p> * <strong>{@code add(f, delta)}</strong> adds {@code delta} to * field {@code f}. This is equivalent to calling <code>set(f, * get(f) + delta)</code> * with two adjustments: - * </p> - * + * * <blockquote> * <p> * <strong>Add rule 1</strong>. The value of field {@code f} after the @@ -210,8 +193,7 @@ import java.io.Serializable; * {@code f}. Overflow occurs when a field value exceeds its range and, * as a result, the next larger field is incremented or decremented and the * field value is adjusted back into its range. - * </p> - * + * * <p> * <strong>Add rule 2</strong>. If a smaller field is expected to be invariant, * but it is impossible for it to be equal to its prior value because of @@ -221,14 +203,12 @@ import java.io.Serializable; * smaller field than {@code DAY_OF_MONTH}. No adjustment is made to * smaller fields that are not expected to be invariant. The calendar system * determines what fields are expected to be invariant. - * </p> * </blockquote> - * + * * <p> * In addition, unlike {@code set()}, {@code add()} forces an * immediate recomputation of the calendar's milliseconds and all fields. - * </p> - * + * * <p> * <em>Example</em>: Consider a {@code GregorianCalendar} originally * set to August 31, 1999. Calling {@code add(Calendar.MONTH, 13)} sets @@ -240,22 +220,19 @@ import java.io.Serializable; * Although it is a smaller field, {@code DAY_OF_WEEK} is not adjusted by * rule 2, since it is expected to change when the month changes in a * {@code GregorianCalendar}. - * </p> - * + * * <p> * <strong>{@code roll(f, delta)}</strong> adds {@code delta} to * field {@code f} without changing larger fields. This is equivalent to * calling {@code add(f, delta)} with the following adjustment: - * </p> - * + * * <blockquote> * <p> * <strong>Roll rule</strong>. Larger fields are unchanged after the call. A * larger field represents a larger unit of time. {@code DAY_OF_MONTH} is * a larger field than {@code HOUR}. - * </p> * </blockquote> - * + * * <p> * <em>Example</em>: Consider a {@code GregorianCalendar} originally * set to August 31, 1999. Calling <code>roll(Calendar.MONTH, @@ -265,8 +242,7 @@ import java.io.Serializable; * the {@code DAY_OF_MONTH} cannot be 31 in the month April. Add rule 2 * sets it to the closest possible value, 30. Finally, the <strong>roll rule</strong> * maintains the {@code YEAR} field value of 1999. - * </p> - * + * * <p> * <em>Example</em>: Consider a {@code GregorianCalendar} originally * set to Sunday June 6, 1999. Calling @@ -279,8 +255,7 @@ import java.io.Serializable; * According to add rule 2, the {@code DAY_OF_WEEK}, an invariant when * changing the {@code WEEK_OF_MONTH}, is set to Tuesday, the closest * possible value to Sunday (where Sunday is the first day of the week). - * </p> - * + * * <p> * <strong>Usage model</strong>. To motivate the behavior of {@code add()} * and {@code roll()}, consider a user interface component with @@ -294,8 +269,7 @@ import java.io.Serializable; * {@code add()} or {@code roll()}, depending on whether larger * fields should be affected, the user interface can behave as most users will * intuitively expect. - * </p> - * + * * <p> * <b>Note:</b> You should always use {@code roll} and {@code add} rather than * attempting to perform arithmetic operations directly on the fields of a @@ -304,11 +278,10 @@ import java.io.Serializable; * during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt> * methods will take this into account, while simple arithmetic manipulations * may give invalid results. - * + * * @see Date * @see GregorianCalendar * @see TimeZone - * @since Android 1.0 */ public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> { @@ -318,38 +291,28 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Set to {@code true} when the calendar fields have been set from the time, set to * {@code false} when a field is changed and the fields must be recomputed. - * - * @since Android 1.0 */ protected boolean areFieldsSet; /** * An integer array of calendar fields. The length is {@code FIELD_COUNT}. - * - * @since Android 1.0 */ protected int[] fields; /** * A boolean array. Each element indicates if the corresponding field has * been set. The length is {@code FIELD_COUNT}. - * - * @since Android 1.0 */ protected boolean[] isSet; /** * Set to {@code true} when the time has been set, set to {@code false} when a field is * changed and the time must be recomputed. - * - * @since Android 1.0 */ protected boolean isTimeSet; /** * The time in milliseconds since January 1, 1970. - * - * @since Android 1.0 */ protected long time; @@ -365,100 +328,75 @@ public abstract class Calendar implements Serializable, Cloneable, private TimeZone zone; - // BEGIN android-changed /** * Value of the {@code MONTH} field indicating the first month of the * year. - * - * @since Android 1.0 */ public static final int JANUARY = 0; /** * Value of the {@code MONTH} field indicating the second month of * the year. - * - * @since Android 1.0 */ public static final int FEBRUARY = 1; /** * Value of the {@code MONTH} field indicating the third month of the * year. - * - * @since Android 1.0 */ public static final int MARCH = 2; /** * Value of the {@code MONTH} field indicating the fourth month of * the year. - * - * @since Android 1.0 */ public static final int APRIL = 3; /** * Value of the {@code MONTH} field indicating the fifth month of the * year. - * - * @since Android 1.0 */ public static final int MAY = 4; /** * Value of the {@code MONTH} field indicating the sixth month of the * year. - * - * @since Android 1.0 */ public static final int JUNE = 5; /** * Value of the {@code MONTH} field indicating the seventh month of * the year. - * - * @since Android 1.0 */ public static final int JULY = 6; /** * Value of the {@code MONTH} field indicating the eighth month of * the year. - * - * @since Android 1.0 */ public static final int AUGUST = 7; /** * Value of the {@code MONTH} field indicating the ninth month of the * year. - * - * @since Android 1.0 */ public static final int SEPTEMBER = 8; /** * Value of the {@code MONTH} field indicating the tenth month of the * year. - * - * @since Android 1.0 */ public static final int OCTOBER = 9; /** * Value of the {@code MONTH} field indicating the eleventh month of * the year. - * - * @since Android 1.0 */ public static final int NOVEMBER = 10; /** * Value of the {@code MONTH} field indicating the twelfth month of * the year. - * - * @since Android 1.0 */ public static final int DECEMBER = 11; @@ -466,57 +404,41 @@ public abstract class Calendar implements Serializable, Cloneable, * Value of the {@code MONTH} field indicating the thirteenth month * of the year. Although {@code GregorianCalendar} does not use this * value, lunar calendars do. - * - * @since Android 1.0 */ public static final int UNDECIMBER = 12; /** * Value of the {@code DAY_OF_WEEK} field indicating Sunday. - * - * @since Android 1.0 */ public static final int SUNDAY = 1; /** * Value of the {@code DAY_OF_WEEK} field indicating Monday. - * - * @since Android 1.0 */ public static final int MONDAY = 2; /** * Value of the {@code DAY_OF_WEEK} field indicating Tuesday. - * - * @since Android 1.0 */ public static final int TUESDAY = 3; /** * Value of the {@code DAY_OF_WEEK} field indicating Wednesday. - * - * @since Android 1.0 */ public static final int WEDNESDAY = 4; /** * Value of the {@code DAY_OF_WEEK} field indicating Thursday. - * - * @since Android 1.0 */ public static final int THURSDAY = 5; /** * Value of the {@code DAY_OF_WEEK} field indicating Friday. - * - * @since Android 1.0 */ public static final int FRIDAY = 6; /** * Value of the {@code DAY_OF_WEEK} field indicating Saturday. - * - * @since Android 1.0 */ public static final int SATURDAY = 7; @@ -524,19 +446,15 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific * value; see subclass documentation. - * + * * @see GregorianCalendar#AD * @see GregorianCalendar#BC - * - * @since Android 1.0 */ public static final int ERA = 0; /** * Field number for {@code get} and {@code set} indicating the * year. This is a calendar-specific value; see subclass documentation. - * - * @since Android 1.0 */ public static final int YEAR = 1; @@ -545,7 +463,7 @@ public abstract class Calendar implements Serializable, Cloneable, * month. This is a calendar-specific value. The first month of the year is * {@code JANUARY}; the last depends on the number of months in a * year. - * + * * @see #JANUARY * @see #FEBRUARY * @see #MARCH @@ -559,8 +477,6 @@ public abstract class Calendar implements Serializable, Cloneable, * @see #NOVEMBER * @see #DECEMBER * @see #UNDECIMBER - * - * @since Android 1.0 */ public static final int MONTH = 2; @@ -571,11 +487,9 @@ public abstract class Calendar implements Serializable, Cloneable, * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses * define the value of {@code WEEK_OF_YEAR} for days before the first * week of the year. - * + * * @see #getFirstDayOfWeek * @see #getMinimalDaysInFirstWeek - * - * @since Android 1.0 */ public static final int WEEK_OF_YEAR = 3; @@ -586,11 +500,9 @@ public abstract class Calendar implements Serializable, Cloneable, * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses * define the value of {@code WEEK_OF_MONTH} for days before the * first week of the month. - * + * * @see #getFirstDayOfWeek * @see #getMinimalDaysInFirstWeek - * - * @since Android 1.0 */ public static final int WEEK_OF_MONTH = 4; @@ -598,10 +510,8 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * day of the month. This is a synonym for {@code DAY_OF_MONTH}. The * first day of the month has value 1. - * + * * @see #DAY_OF_MONTH - * - * @since Android 1.0 */ public static final int DATE = 5; @@ -609,10 +519,8 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * day of the month. This is a synonym for {@code DATE}. The first * day of the month has value 1. - * + * * @see #DATE - * - * @since Android 1.0 */ public static final int DAY_OF_MONTH = 5; @@ -620,8 +528,6 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * day number within the current year. The first day of the year has value * 1. - * - * @since Android 1.0 */ public static final int DAY_OF_YEAR = 6; @@ -631,7 +537,7 @@ public abstract class Calendar implements Serializable, Cloneable, * {@code MONDAY}, {@code TUESDAY}, {@code WEDNESDAY}, * {@code THURSDAY}, {@code FRIDAY}, and * {@code SATURDAY}. - * + * * @see #SUNDAY * @see #MONDAY * @see #TUESDAY @@ -639,8 +545,6 @@ public abstract class Calendar implements Serializable, Cloneable, * @see #THURSDAY * @see #FRIDAY * @see #SATURDAY - * - * @since Android 1.0 */ public static final int DAY_OF_WEEK = 7; @@ -664,11 +568,9 @@ public abstract class Calendar implements Serializable, Cloneable, * within the month than positive values. For example, if a month has 31 * days, {@code DAY_OF_WEEK_IN_MONTH -1} will overlap * {@code DAY_OF_WEEK_IN_MONTH 5} and the end of {@code 4}. - * + * * @see #DAY_OF_WEEK * @see #WEEK_OF_MONTH - * - * @since Android 1.0 */ public static final int DAY_OF_WEEK_IN_MONTH = 8; @@ -676,12 +578,10 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating * whether the {@code HOUR} is before or after noon. E.g., at * 10:04:15.250 PM the {@code AM_PM} is {@code PM}. - * + * * @see #AM * @see #PM * @see #HOUR - * - * @since Android 1.0 */ public static final int AM_PM = 9; @@ -689,11 +589,9 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * hour of the morning or afternoon. {@code HOUR} is used for the * 12-hour clock. E.g., at 10:04:15.250 PM the {@code HOUR} is 10. - * + * * @see #AM_PM * @see #HOUR_OF_DAY - * - * @since Android 1.0 */ public static final int HOUR = 10; @@ -701,10 +599,8 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * hour of the day. {@code HOUR_OF_DAY} is used for the 24-hour * clock. E.g., at 10:04:15.250 PM the {@code HOUR_OF_DAY} is 22. - * + * * @see #HOUR - * - * @since Android 1.0 */ public static final int HOUR_OF_DAY = 11; @@ -712,8 +608,6 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * minute within the hour. E.g., at 10:04:15.250 PM the {@code MINUTE} * is 4. - * - * @since Android 1.0 */ public static final int MINUTE = 12; @@ -721,8 +615,6 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * second within the minute. E.g., at 10:04:15.250 PM the * {@code SECOND} is 15. - * - * @since Android 1.0 */ public static final int SECOND = 13; @@ -730,61 +622,46 @@ public abstract class Calendar implements Serializable, Cloneable, * Field number for {@code get} and {@code set} indicating the * millisecond within the second. E.g., at 10:04:15.250 PM the * {@code MILLISECOND} is 250. - * - * @since Android 1.0 */ public static final int MILLISECOND = 14; /** * Field number for {@code get} and {@code set} indicating the * raw offset from GMT in milliseconds. - * - * @since Android 1.0 */ public static final int ZONE_OFFSET = 15; /** * Field number for {@code get} and {@code set} indicating the * daylight savings offset in milliseconds. - * - * @since Android 1.0 */ public static final int DST_OFFSET = 16; /** * This is the total number of fields in this calendar. - * - * @since Android 1.0 */ public static final int FIELD_COUNT = 17; /** * Value of the {@code AM_PM} field indicating the period of the day * from midnight to just before noon. - * - * @since Android 1.0 */ public static final int AM = 0; /** * Value of the {@code AM_PM} field indicating the period of the day * from noon to just before midnight. - * - * @since Android 1.0 */ public static final int PM = 1; - // END android-changed private static String[] fieldNames = { "ERA=", "YEAR=", "MONTH=", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - "WEEK_OF_YEAR=", "WEEK_OF_MONTH=", "DAY_OF_MONTH=", "DAY_OF_YEAR=", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - "DAY_OF_WEEK=", "DAY_OF_WEEK_IN_MONTH=", "AM_PM=", "HOUR=", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ + "WEEK_OF_YEAR=", "WEEK_OF_MONTH=", "DAY_OF_MONTH=", "DAY_OF_YEAR=", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + "DAY_OF_WEEK=", "DAY_OF_WEEK_IN_MONTH=", "AM_PM=", "HOUR=", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ "HOUR_OF_DAY", "MINUTE=", "SECOND=", "MILLISECOND=", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ "ZONE_OFFSET=", "DST_OFFSET=" }; //$NON-NLS-1$ //$NON-NLS-2$ /** * Constructs a {@code Calendar} instance using the default {@code TimeZone} and {@code Locale}. - * - * @since Android 1.0 */ protected Calendar() { this(TimeZone.getDefault(), Locale.getDefault()); @@ -800,30 +677,38 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Constructs a {@code Calendar} instance using the specified {@code TimeZone} and {@code Locale}. - * + * * @param timezone * the timezone. * @param locale * the locale. - * - * @since Android 1.0 */ protected Calendar(TimeZone timezone, Locale locale) { this(timezone); + // BEGIN android-changed + // com.ibm.icu.util.Calendar icuCalendar = com.ibm.icu.util.Calendar + // .getInstance(com.ibm.icu.util.SimpleTimeZone + // .getTimeZone(timezone.getID()), locale); + // setFirstDayOfWeek(icuCalendar.getFirstDayOfWeek()); + // setMinimalDaysInFirstWeek(icuCalendar.getMinimalDaysInFirstWeek()); ResourceBundle bundle = Locale.getBundle("Locale", locale); //$NON-NLS-1$ setFirstDayOfWeek(((Integer) bundle.getObject("First_Day")).intValue()); //$NON-NLS-1$ setMinimalDaysInFirstWeek(((Integer) bundle.getObject("Minimal_Days")) //$NON-NLS-1$ .intValue()); + // END android-changed } + /** * Adds the specified amount to a {@code Calendar} field. - * + * * @param field * the {@code Calendar} field to modify. * @param value * the amount to add to the field. - * @since Android 1.0 + * @throws IllegalArgumentException + * if {@code field} is {@code DST_OFFSET} or {@code + * ZONE_OFFSET}. */ abstract public void add(int field, int value); @@ -831,11 +716,13 @@ public abstract class Calendar implements Serializable, Cloneable, * Returns whether the {@code Date} specified by this {@code Calendar} instance is after the {@code Date} * specified by the parameter. The comparison is not dependent on the time * zones of the {@code Calendar}. - * + * * @param calendar * the {@code Calendar} instance to compare. * @return {@code true} when this Calendar is after calendar, {@code false} otherwise. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the time is not set and the time cannot be computed + * from the current field values. */ public boolean after(Object calendar) { if (!(calendar instanceof Calendar)) { @@ -848,11 +735,13 @@ public abstract class Calendar implements Serializable, Cloneable, * Returns whether the {@code Date} specified by this {@code Calendar} instance is before the * {@code Date} specified by the parameter. The comparison is not dependent on the * time zones of the {@code Calendar}. - * + * * @param calendar * the {@code Calendar} instance to compare. * @return {@code true} when this Calendar is before calendar, {@code false} otherwise. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the time is not set and the time cannot be computed + * from the current field values. */ public boolean before(Object calendar) { if (!(calendar instanceof Calendar)) { @@ -864,8 +753,6 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Clears all of the fields of this {@code Calendar}. All fields are initialized to * zero. - * - * @since Android 1.0 */ public final void clear() { for (int i = 0; i < FIELD_COUNT; i++) { @@ -877,10 +764,9 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Clears the specified field to zero and sets the isSet flag to {@code false}. - * + * * @param field * the field to clear. - * @since Android 1.0 */ public final void clear(int field) { fields[field] = 0; @@ -890,11 +776,10 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Returns a new {@code Calendar} with the same properties. - * + * * @return a shallow copy of this {@code Calendar}. - * + * * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -912,11 +797,10 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Computes the time from the fields if the time has not already been set. * Computes the fields from the time if the fields are not already set. - * - * @exception IllegalArgumentException - * when the time is not set and the time cannot be computed + * + * @throws IllegalArgumentException + * if the time is not set and the time cannot be computed * from the current field values. - * @since Android 1.0 */ protected void complete() { if (!isTimeSet) { @@ -931,18 +815,15 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Computes the {@code Calendar} fields from {@code time}. - * - * @since Android 1.0 */ protected abstract void computeFields(); /** * Computes {@code time} from the Calendar fields. - * - * @exception IllegalArgumentException - * when the time cannot be computed from the current field + * + * @throws IllegalArgumentException + * if the time cannot be computed from the current field * values. - * @since Android 1.0 */ protected abstract void computeTime(); @@ -950,12 +831,11 @@ public abstract class Calendar implements Serializable, Cloneable, * Compares the specified object to this {@code Calendar} and returns whether they are * equal. The object must be an instance of {@code Calendar} and have the same * properties. - * + * * @param object * the object to compare with this object. * @return {@code true} if the specified object is equal to this {@code Calendar}, {@code false} * otherwise. - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -977,18 +857,17 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Gets the value of the specified field after computing the field values by * calling {@code complete()} first. - * + * * @param field * the field to get. * @return the value of the specified field. - * - * @exception IllegalArgumentException - * when the fields are not set, the time is not set, and the + * + * @throws IllegalArgumentException + * if the fields are not set, the time is not set, and the * time cannot be computed from the current field values. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if the field is not inside the range of possible fields. * The range is starting at 0 up to {@code FIELD_COUNT}. - * @since Android 1.0 */ public int get(int field) { complete(); @@ -997,11 +876,10 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Gets the maximum value of the specified field for the current date. - * + * * @param field * the field. * @return the maximum value of the specified field. - * @since Android 1.0 */ public int getActualMaximum(int field) { int value, next; @@ -1023,11 +901,10 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Gets the minimum value of the specified field for the current date. - * + * * @param field * the field. * @return the minimum value of the specified field. - * @since Android 1.0 */ public int getActualMinimum(int field) { int value, next; @@ -1049,9 +926,8 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Gets the list of installed {@code Locale}s which support {@code Calendar}. - * + * * @return an array of {@code Locale}. - * @since Android 1.0 */ public static synchronized Locale[] getAvailableLocales() { return Locale.getAvailableLocales(); @@ -1059,9 +935,8 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Gets the first day of the week for this {@code Calendar}. - * + * * @return the first day of the week. - * @since Android 1.0 */ public int getFirstDayOfWeek() { return firstDayOfWeek; @@ -1071,21 +946,19 @@ public abstract class Calendar implements Serializable, Cloneable, * Gets the greatest minimum value of the specified field. This is the * biggest value that {@code getActualMinimum} can return for any possible * time. - * + * * @param field * the field. * @return the greatest minimum value of the specified field. - * @since Android 1.0 */ abstract public int getGreatestMinimum(int field); /** * Constructs a new instance of the {@code Calendar} subclass appropriate for the * default {@code Locale}. - * + * * @return a {@code Calendar} subclass instance set to the current date and time in * the default {@code Timezone}. - * @since Android 1.0 */ public static synchronized Calendar getInstance() { return new GregorianCalendar(); @@ -1094,11 +967,10 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Constructs a new instance of the {@code Calendar} subclass appropriate for the * specified {@code Locale}. - * + * * @param locale * the locale to use. * @return a {@code Calendar} subclass instance set to the current date and time. - * @since Android 1.0 */ public static synchronized Calendar getInstance(Locale locale) { return new GregorianCalendar(locale); @@ -1107,12 +979,11 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Constructs a new instance of the {@code Calendar} subclass appropriate for the * default {@code Locale}, using the specified {@code TimeZone}. - * + * * @param timezone * the {@code TimeZone} to use. * @return a {@code Calendar} subclass instance set to the current date and time in * the specified timezone. - * @since Android 1.0 */ public static synchronized Calendar getInstance(TimeZone timezone) { return new GregorianCalendar(timezone); @@ -1121,14 +992,13 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Constructs a new instance of the {@code Calendar} subclass appropriate for the * specified {@code Locale}. - * + * * @param timezone * the {@code TimeZone} to use. * @param locale * the {@code Locale} to use. * @return a {@code Calendar} subclass instance set to the current date and time in * the specified timezone. - * @since Android 1.0 */ public static synchronized Calendar getInstance(TimeZone timezone, Locale locale) { @@ -1139,30 +1009,27 @@ public abstract class Calendar implements Serializable, Cloneable, * Gets the smallest maximum value of the specified field. This is the * smallest value that {@code getActualMaximum()} can return for any * possible time. - * + * * @param field * the field number. * @return the smallest maximum value of the specified field. - * @since Android 1.0 */ abstract public int getLeastMaximum(int field); /** * Gets the greatest maximum value of the specified field. This returns the * biggest value that {@code get} can return for the specified field. - * + * * @param field * the field. * @return the greatest maximum value of the specified field. - * @since Android 1.0 */ abstract public int getMaximum(int field); /** * Gets the minimal days in the first week of the year. - * + * * @return the minimal days in the first week of the year. - * @since Android 1.0 */ public int getMinimalDaysInFirstWeek() { return minimalDaysInFirstWeek; @@ -1171,23 +1038,21 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Gets the smallest minimum value of the specified field. this returns the * smallest value thet {@code get} can return for the specified field. - * + * * @param field * the field number. * @return the smallest minimum value of the specified field. - * @since Android 1.0 */ abstract public int getMinimum(int field); /** * Gets the time of this {@code Calendar} as a {@code Date} object. - * + * * @return a new {@code Date} initialized to the time of this {@code Calendar}. - * - * @exception IllegalArgumentException - * when the time is not set and the time cannot be computed + * + * @throws IllegalArgumentException + * if the time is not set and the time cannot be computed * from the current field values. - * @since Android 1.0 */ public final Date getTime() { return new Date(getTimeInMillis()); @@ -1195,13 +1060,12 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Computes the time from the fields if required and returns the time. - * + * * @return the time of this {@code Calendar}. - * - * @exception IllegalArgumentException - * when the time is not set and the time cannot be computed + * + * @throws IllegalArgumentException + * if the time is not set and the time cannot be computed * from the current field values. - * @since Android 1.0 */ public long getTimeInMillis() { if (!isTimeSet) { @@ -1213,9 +1077,8 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Gets the timezone of this {@code Calendar}. - * + * * @return the {@code TimeZone} used by this {@code Calendar}. - * @since Android 1.0 */ public TimeZone getTimeZone() { return zone; @@ -1224,11 +1087,10 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Returns an integer hash code for the receiver. Objects which are equal * return the same value for this method. - * + * * @return the receiver's hash. - * + * * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -1238,11 +1100,10 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Gets the value of the specified field without recomputing. - * + * * @param field * the field. * @return the value of the specified field. - * @since Android 1.0 */ protected final int internalGet(int field) { return fields[field]; @@ -1251,9 +1112,8 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Returns if this {@code Calendar} accepts field values which are outside the valid * range for the field. - * + * * @return {@code true} if this {@code Calendar} is lenient, {@code false} otherwise. - * @since Android 1.0 */ public boolean isLenient() { return lenient; @@ -1261,11 +1121,10 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Returns whether the specified field is set. - * + * * @param field * a {@code Calendar} field number. * @return {@code true} if the specified field is set, {@code false} otherwise. - * @since Android 1.0 */ public final boolean isSet(int field) { return isSet[field]; @@ -1276,12 +1135,11 @@ public abstract class Calendar implements Serializable, Cloneable, * the field when it goes beyond the maximum or minimum value for the * current date. Other fields will be adjusted as required to maintain a * consistent date. - * + * * @param field * the field to roll. * @param value * the amount to add. - * @since Android 1.0 */ public void roll(int field, int value) { boolean increment = value >= 0; @@ -1296,23 +1154,21 @@ public abstract class Calendar implements Serializable, Cloneable, * field when it goes beyond the maximum or minimum value for the current * date. Other fields will be adjusted as required to maintain a consistent * date. - * + * * @param field * the number indicating the field to roll. * @param increment * {@code true} to increment the field, {@code false} to decrement. - * @since Android 1.0 */ abstract public void roll(int field, boolean increment); /** * Sets a field to the specified value. - * + * * @param field * the code indicating the {@code Calendar} field to modify. * @param value * the value. - * @since Android 1.0 */ public void set(int field, int value) { fields[field] = value; @@ -1332,14 +1188,13 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Sets the year, month and day of the month fields. Other fields are not * changed. - * + * * @param year * the year. * @param month * the month. * @param day * the day of the month. - * @since Android 1.0 */ public final void set(int year, int month, int day) { set(YEAR, year); @@ -1350,7 +1205,7 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Sets the year, month, day of the month, hour of day and minute fields. * Other fields are not changed. - * + * * @param year * the year. * @param month @@ -1361,7 +1216,6 @@ public abstract class Calendar implements Serializable, Cloneable, * the hour of day. * @param minute * the minute. - * @since Android 1.0 */ public final void set(int year, int month, int day, int hourOfDay, int minute) { @@ -1373,7 +1227,7 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Sets the year, month, day of the month, hour of day, minute and second * fields. Other fields are not changed. - * + * * @param year * the year. * @param month @@ -1386,7 +1240,6 @@ public abstract class Calendar implements Serializable, Cloneable, * the minute. * @param second * the second. - * @since Android 1.0 */ public final void set(int year, int month, int day, int hourOfDay, int minute, int second) { @@ -1396,10 +1249,9 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Sets the first day of the week for this {@code Calendar}. - * + * * @param value * a {@code Calendar} day of the week. - * @since Android 1.0 */ public void setFirstDayOfWeek(int value) { firstDayOfWeek = value; @@ -1408,10 +1260,9 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Sets this {@code Calendar} to accept field values which are outside the valid * range for the field. - * + * * @param value * a boolean value. - * @since Android 1.0 */ public void setLenient(boolean value) { lenient = value; @@ -1419,10 +1270,9 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Sets the minimal days in the first week of the year. - * + * * @param value * the minimal days in the first week of the year. - * @since Android 1.0 */ public void setMinimalDaysInFirstWeek(int value) { minimalDaysInFirstWeek = value; @@ -1430,10 +1280,9 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Sets the time of this {@code Calendar}. - * + * * @param date * a {@code Date} object. - * @since Android 1.0 */ public final void setTime(Date date) { setTimeInMillis(date.getTime()); @@ -1441,43 +1290,45 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Sets the time of this {@code Calendar}. - * + * * @param milliseconds * the time as the number of milliseconds since Jan. 1, 1970. - * @since Android 1.0 */ public void setTimeInMillis(long milliseconds) { - time = milliseconds; - isTimeSet = true; - areFieldsSet = false; - complete(); + if (!isTimeSet || !areFieldsSet || time != milliseconds) { + time = milliseconds; + isTimeSet = true; + areFieldsSet = false; + complete(); + } } /** * Sets the {@code TimeZone} used by this Calendar. - * + * * @param timezone * a {@code TimeZone}. - * @since Android 1.0 */ public void setTimeZone(TimeZone timezone) { zone = timezone; + areFieldsSet = false; } /** * Returns the string representation of this {@code Calendar}. - * + * * @return the string representation of this {@code Calendar}. - * @since Android 1.0 */ @Override + @SuppressWarnings("nls") public String toString() { - StringBuffer result = new StringBuffer(getClass().getName() + "[time=" //$NON-NLS-1$ - + (isTimeSet ? String.valueOf(time) : "?") + ",areFieldsSet=" //$NON-NLS-1$//$NON-NLS-2$ - + areFieldsSet + - // ",areAllFieldsSet=" + areAllFieldsSet + - ",lenient=" + lenient + ",zone=" + zone + ",firstDayOfWeek=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - + firstDayOfWeek + ",minimalDaysInFirstWeek=" //$NON-NLS-1$ + StringBuffer result = new StringBuffer(getClass().getName() + "[time=" + + (isTimeSet ? String.valueOf(time) : "?") + + ",areFieldsSet=" + + areFieldsSet + + // ",areAllFieldsSet=" + areAllFieldsSet + + ",lenient=" + lenient + ",zone=" + zone + ",firstDayOfWeek=" + + firstDayOfWeek + ",minimalDaysInFirstWeek=" + minimalDaysInFirstWeek); for (int i = 0; i < FIELD_COUNT; i++) { result.append(','); @@ -1496,7 +1347,7 @@ public abstract class Calendar implements Serializable, Cloneable, /** * Compares the times of the two {@code Calendar}, which represent the milliseconds * from the January 1, 1970 00:00:00.000 GMT (Gregorian). - * + * * @param anotherCalendar * another calendar that this one is compared with. * @return 0 if the times of the two {@code Calendar}s are equal, -1 if the time of @@ -1507,7 +1358,6 @@ public abstract class Calendar implements Serializable, Cloneable, * @throws IllegalArgumentException * if the argument does not include a valid time * value. - * @since Android 1.0 */ public int compareTo(Calendar anotherCalendar) { if (null == anotherCalendar) { @@ -1524,6 +1374,7 @@ public abstract class Calendar implements Serializable, Cloneable, return -1; } + @SuppressWarnings("nls") private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("areFieldsSet", Boolean.TYPE), //$NON-NLS-1$ new ObjectStreamField("fields", int[].class), //$NON-NLS-1$ @@ -1537,6 +1388,7 @@ public abstract class Calendar implements Serializable, Cloneable, new ObjectStreamField("time", Long.TYPE), //$NON-NLS-1$ new ObjectStreamField("zone", TimeZone.class), }; //$NON-NLS-1$ + @SuppressWarnings("nls") private void writeObject(ObjectOutputStream stream) throws IOException { complete(); ObjectOutputStream.PutField putFields = stream.putFields(); @@ -1554,6 +1406,7 @@ public abstract class Calendar implements Serializable, Cloneable, stream.writeFields(); } + @SuppressWarnings("nls") private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { ObjectInputStream.GetField readFields = stream.readFields(); diff --git a/luni/src/main/java/java/util/Collection.java b/luni/src/main/java/java/util/Collection.java index e26dba6..6447e39 100644 --- a/luni/src/main/java/java/util/Collection.java +++ b/luni/src/main/java/java/util/Collection.java @@ -22,7 +22,7 @@ package java.util; * {@code Collection} is the root of the collection hierarchy. It defines operations on * data collections and the behavior that they will have in all implementations * of {@code Collection}s. - * + * * All direct or indirect implementations of {@code Collection} should implement at * least two constuctors. One with no parameters which creates an empty * collection and one with a parameter of type {@code Collection}. This second @@ -30,58 +30,55 @@ package java.util; * initial collection but with the same elements. Implementations of {@code Collection} * cannot be forced to implement these two constructors but at least all * implementations under {@code java.util} do. - * + * * Methods that change the content of a collection throw an * {@code UnsupportedOperationException} if the underlying collection does not * support that operation, though it's not mandatory to throw such an {@code Exception} * in cases where the requested operation would not change the collection. In * these cases it's up to the implementation whether it throws an * {@code UnsupportedOperationException} or not. - * + * * Methods marked with (optional) can throw an * {@code UnsupportedOperationException} if the underlying collection doesn't * support that method. - * - * @since Android 1.0 */ public interface Collection<E> extends Iterable<E> { /** * Attempts to add {@code object} to the contents of this * {@code Collection} (optional). - * + * * After this method finishes successfully it is guaranteed that the object * is contained in the collection. - * + * * If the collection was modified it returns {@code true}, {@code false} if * no changes were made. - * + * * An implementation of {@code Collection} may narrow the set of accepted * objects, but it has to specify this in the documentation. If the object * to be added does not meet this restriction, then an * {@code IllegalArgumentException} is thrown. - * + * * If a collection does not yet contain an object that is to be added and * adding the object fails, this method <i>must</i> throw an appropriate * unchecked Exception. Returning false is not permitted in this case * because it would violate the postcondition that the element will be part * of the collection after this method finishes. - * + * * @param object * the object to add. * @return {@code true} if this {@code Collection} is * modified, {@code false} otherwise. - * - * @exception UnsupportedOperationException - * when adding to this {@code Collection} is not supported. - * @exception ClassCastException - * when the class of the object is inappropriate for this + * + * @throws UnsupportedOperationException + * if adding to this {@code Collection} is not supported. + * @throws ClassCastException + * if the class of the object is inappropriate for this * collection. - * @exception IllegalArgumentException - * when the object cannot be added to this {@code Collection}. - * @exception NullPointerException - * when null elements cannot be added to the {@code Collection}. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the object cannot be added to this {@code Collection}. + * @throws NullPointerException + * if null elements cannot be added to the {@code Collection}. */ public boolean add(E object); @@ -90,35 +87,33 @@ public interface Collection<E> extends Iterable<E> { * to the contents of this {@code Collection} (optional). If the passed {@code Collection} * is changed during the process of adding elements to this {@code Collection}, the * behavior is not defined. - * + * * @param collection * the {@code Collection} of objects. * @return {@code true} if this {@code Collection} is modified, {@code false} * otherwise. - * @exception UnsupportedOperationException - * when adding to this {@code Collection} is not supported. - * @exception ClassCastException - * when the class of an object is inappropriate for this + * @throws UnsupportedOperationException + * if adding to this {@code Collection} is not supported. + * @throws ClassCastException + * if the class of an object is inappropriate for this * {@code Collection}. - * @exception IllegalArgumentException - * when an object cannot be added to this {@code Collection}. - * @exception NullPointerException - * when {@code collection} is {@code null}, or if it + * @throws IllegalArgumentException + * if an object cannot be added to this {@code Collection}. + * @throws NullPointerException + * if {@code collection} is {@code null}, or if it * contains {@code null} elements and this {@code Collection} does * not support such elements. - * @since Android 1.0 */ public boolean addAll(Collection<? extends E> collection); /** * Removes all elements from this {@code Collection}, leaving it empty (optional). - * - * @exception UnsupportedOperationException - * when removing from this {@code Collection} is not supported. - * + * + * @throws UnsupportedOperationException + * if removing from this {@code Collection} is not supported. + * * @see #isEmpty * @see #size - * @since Android 1.0 */ public void clear(); @@ -127,18 +122,17 @@ public interface Collection<E> extends Iterable<E> { * {@code true} if and only if at least one element {@code elem} in this * {@code Collection} meets following requirement: * {@code (object==null ? elem==null : object.equals(elem))}. - * + * * @param object * the object to search for. * @return {@code true} if object is an element of this {@code Collection}, * {@code false} otherwise. - * @exception ClassCastException + * @throws ClassCastException * if the object to look for isn't of the correct * type. - * @exception NullPointerException + * @throws NullPointerException * if the object to look for is {@code null} and this * {@code Collection} doesn't support {@code null} elements. - * @since Android 1.0 */ public boolean contains(Object object); @@ -147,56 +141,52 @@ public interface Collection<E> extends Iterable<E> { * specified {@code Collection}. If an elemenet {@code elem} is contained several * times in the specified {@code Collection}, the method returns {@code true} even * if {@code elem} is contained only once in this {@code Collection}. - * + * * @param collection * the collection of objects. * @return {@code true} if all objects in the specified {@code Collection} are * elements of this {@code Collection}, {@code false} otherwise. - * @exception ClassCastException + * @throws ClassCastException * if one or more elements of {@code collection} isn't of the * correct type. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} contains at least one {@code null} * element and this {@code Collection} doesn't support {@code null} * elements. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} is {@code null}. - * @since Android 1.0 */ public boolean containsAll(Collection<?> collection); /** * Compares the argument to the receiver, and returns true if they represent * the <em>same</em> object using a class specific comparison. - * + * * @param object * the object to compare with this object. * @return {@code true} if the object is the same as this object and * {@code false} if it is different from this object. * @see #hashCode - * @since Android 1.0 */ public boolean equals(Object object); /** * Returns an integer hash code for the receiver. Objects which are equal * return the same value for this method. - * + * * @return the receiver's hash. - * + * * @see #equals - * @since Android 1.0 */ public int hashCode(); /** * Returns if this {@code Collection} contains no elements. - * + * * @return {@code true} if this {@code Collection} has no elements, {@code false} * otherwise. - * + * * @see #size - * @since Android 1.0 */ public boolean isEmpty(); @@ -205,9 +195,8 @@ public interface Collection<E> extends Iterable<E> { * objects contained by this {@code Collection}. The order in which the elements are * returned by the iterator is not defined. Only if the instance of the * {@code Collection} has a defined order the elements are returned in that order. - * + * * @return an iterator for accessing the {@code Collection} contents. - * @since Android 1.0 */ public Iterator<E> iterator(); @@ -215,19 +204,18 @@ public interface Collection<E> extends Iterable<E> { * Removes one instance of the specified object from this {@code Collection} if one * is contained (optional). The element {@code elem} that is removed * complies with {@code (object==null ? elem==null : object.equals(elem)}. - * + * * @param object * the object to remove. * @return {@code true} if this {@code Collection} is modified, {@code false} * otherwise. - * @exception UnsupportedOperationException - * when removing from this {@code Collection} is not supported. - * @exception ClassCastException - * when the object passed is not of the correct type. - * @exception NullPointerException + * @throws UnsupportedOperationException + * if removing from this {@code Collection} is not supported. + * @throws ClassCastException + * if the object passed is not of the correct type. + * @throws NullPointerException * if {@code object} is {@code null} and this {@code Collection} * doesn't support {@code null} elements. - * @since Android 1.0 */ public boolean remove(Object object); @@ -236,24 +224,23 @@ public interface Collection<E> extends Iterable<E> { * specified {@code Collection} (optional). After this method returns none of the * elements in the passed {@code Collection} can be found in this {@code Collection} * anymore. - * + * * @param collection * the collection of objects to remove. * @return {@code true} if this {@code Collection} is modified, {@code false} * otherwise. - * - * @exception UnsupportedOperationException - * when removing from this {@code Collection} is not supported. - * @exception ClassCastException + * + * @throws UnsupportedOperationException + * if removing from this {@code Collection} is not supported. + * @throws ClassCastException * if one or more elements of {@code collection} * isn't of the correct type. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} contains at least one * {@code null} element and this {@code Collection} doesn't support * {@code null} elements. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} is {@code null}. - * @since Android 1.0 */ public boolean removeAll(Collection<?> collection); @@ -262,48 +249,45 @@ public interface Collection<E> extends Iterable<E> { * {@code Collection} passed (optional). After this method returns this {@code Collection} * will only contain elements that also can be found in the {@code Collection} * passed to this method. - * + * * @param collection * the collection of objects to retain. * @return {@code true} if this {@code Collection} is modified, {@code false} * otherwise. - * @exception UnsupportedOperationException - * when removing from this {@code Collection} is not supported. - * @exception ClassCastException + * @throws UnsupportedOperationException + * if removing from this {@code Collection} is not supported. + * @throws ClassCastException * if one or more elements of {@code collection} * isn't of the correct type. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} contains at least one * {@code null} element and this {@code Collection} doesn't support * {@code null} elements. - * @exception NullPointerException + * @throws NullPointerException * if {@code collection} is {@code null}. - * @since Android 1.0 */ public boolean retainAll(Collection<?> collection); /** * Returns a count of how many objects this {@code Collection} contains. - * + * * @return how many objects this {@code Collection} contains, or Integer.MAX_VALUE * if there are more than Integer.MAX_VALUE elements in this * {@code Collection}. - * @since Android 1.0 */ public int size(); /** * Returns a new array containing all elements contained in this {@code Collection}. - * + * * If the implementation has ordered elements it will return the element * array in the same order as an iterator would return them. - * + * * The array returned does not reflect any changes of the {@code Collection}. A new * array is created even if the underlying data structure is already an * array. - * + * * @return an array of the elements from this {@code Collection}. - * @since Android 1.0 */ public Object[] toArray(); @@ -313,21 +297,20 @@ public interface Collection<E> extends Iterable<E> { * array is used, otherwise an array of the same type is created. If the * specified array is used and is larger than this {@code Collection}, the array * element following the {@code Collection} elements is set to null. - * + * * If the implementation has ordered elements it will return the element * array in the same order as an iterator would return them. - * + * * {@code toArray(new Object[0])} behaves exactly the same way as * {@code toArray()} does. - * + * * @param array * the array. * @return an array of the elements from this {@code Collection}. - * - * @exception ArrayStoreException - * when the type of an element in this {@code Collection} cannot be + * + * @throws ArrayStoreException + * if the type of an element in this {@code Collection} cannot be * stored in the type of the specified array. - * @since Android 1.0 */ public <T> T[] toArray(T[] array); } diff --git a/luni/src/main/java/java/util/Collections.java b/luni/src/main/java/java/util/Collections.java index 5905bc2..767d98b 100644 --- a/luni/src/main/java/java/util/Collections.java +++ b/luni/src/main/java/java/util/Collections.java @@ -27,8 +27,8 @@ import org.apache.harmony.luni.internal.nls.Messages; /** * {@code Collections} contains static methods which operate on * {@code Collection} classes. - * - * @since Android 1.0 + * + * @since 1.2 */ public class Collections { @@ -69,7 +69,7 @@ public class Collections { @SuppressWarnings("unchecked") private static final class EmptyList extends AbstractList implements - Serializable { + RandomAccess, Serializable { private static final long serialVersionUID = 8842843931221139166L; @Override @@ -171,24 +171,18 @@ public class Collections { /** * An empty immutable instance of {@link List}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final List EMPTY_LIST = new EmptyList(); /** * An empty immutable instance of {@link Set}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final Set EMPTY_SET = new EmptySet(); /** * An empty immutable instance of {@link Map}. - * - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final Map EMPTY_MAP = new EmptyMap(); @@ -532,9 +526,9 @@ public class Collections { * problems. This is necessary since RandomAccess API was introduced * only in 1.4. * <p> - * + * * @return SynchronizedList - * + * * @see SynchronizedList#readResolve() */ private Object writeReplace() { @@ -591,15 +585,51 @@ public class Collections { } public int indexOf(Object object) { + final int size; + final Object[] array; synchronized (mutex) { - return list.indexOf(object); + size = list.size(); + array = new Object[size]; + list.toArray(array); + } + if (null != object) + for (int i = 0; i < size; i++) { + if (object.equals(array[i])) { + return i; + } + } + else { + for (int i = 0; i < size; i++) { + if (null == array[i]) { + return i; + } + } } + return -1; } public int lastIndexOf(Object object) { + final int size; + final Object[] array; synchronized (mutex) { - return list.lastIndexOf(object); + size = list.size(); + array = new Object[size]; + list.toArray(array); + } + if (null != object) + for (int i = size - 1; i >= 0; i--) { + if (object.equals(array[i])) { + return i; + } + } + else { + for (int i = size - 1; i >= 0; i--) { + if (null == array[i]) { + return i; + } + } } + return -1; } public ListIterator<E> listIterator() { @@ -646,10 +676,10 @@ public class Collections { * replaced with SynchronizedList instances during serialization for * compliance with JREs before 1.4. * <p> - * + * * @return a SynchronizedList instance if the underlying list implements * RandomAccess interface, or this same object if not. - * + * * @see SynchronizedRandomAccessList#writeReplace() */ private Object readResolve() { @@ -1033,9 +1063,9 @@ public class Collections { * problems. This is necessary since RandomAccess API was introduced * only in 1.4. * <p> - * + * * @return UnmodifiableList - * + * * @see UnmodifiableList#readResolve() */ private Object writeReplace() { @@ -1150,11 +1180,11 @@ public class Collections { * replaced with UnmodifiableList instances during serialization for * compliance with JREs before 1.4. * <p> - * + * * @return an UnmodifiableList instance if the underlying list * implements RandomAccess interface, or this same object if * not. - * + * * @see UnmodifiableRandomAccessList#writeReplace() */ private Object readResolve() { @@ -1429,13 +1459,13 @@ public class Collections { /** * Performs a binary search for the specified element in the specified - * sorted List. The List needs to be already sorted in natural sorting + * sorted list. The list needs to be already sorted in natural sorting * order. Searching in an unsorted array has an undefined result. It's also * undefined which element is found if there are multiple occurrences of the * same element. - * + * * @param list - * the sorted List to search. + * the sorted list to search. * @param object * the element to find. * @return the non-negative index of the element, or a negative index which @@ -1443,7 +1473,6 @@ public class Collections { * @throws ClassCastException * if an element in the List or the search element does not * implement Comparable, or cannot be compared to each other. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static <T> int binarySearch( @@ -1455,12 +1484,12 @@ public class Collections { return -1; } - Comparable<T> key = (Comparable<T>) object; + if (!(list instanceof RandomAccess)) { - ListIterator<T> it = (ListIterator<T>) list.listIterator(); + ListIterator<? extends Comparable<? super T>> it = list.listIterator(); while (it.hasNext()) { int result; - if ((result = key.compareTo(it.next())) <= 0) { + if ((result = -it.next().compareTo(object)) <= 0) { if (result == 0) { return it.previousIndex(); } @@ -1473,7 +1502,7 @@ public class Collections { int low = 0, mid = list.size(), high = mid - 1, result = -1; while (low <= high) { mid = (low + high) >> 1; - if ((result = key.compareTo((T) list.get(mid))) > 0) { + if ((result = -list.get(mid).compareTo(object)) > 0) { low = mid + 1; } else if (result == 0) { return mid; @@ -1486,26 +1515,28 @@ public class Collections { /** * Performs a binary search for the specified element in the specified - * sorted List using the specified Comparator. The List needs to be already + * sorted list using the specified comparator. The list needs to be already * sorted according to the comparator passed. Searching in an unsorted array * has an undefined result. It's also undefined which element is found if * there are multiple occurrences of the same element. - * + * * @param list * the sorted List to search. * @param object * the element to find. * @param comparator - * the Comparator. If the comparator is {@code null} then the + * the comparator. If the comparator is {@code null} then the * search uses the objects' natural ordering. * @return the non-negative index of the element, or a negative index which * is the {@code -index - 1} where the element would be inserted. * @throws ClassCastException * when an element in the list and the searched element cannot - * be compared to each other using the Comparator. - * @since Android 1.0 + * be compared to each other using the comparator. */ @SuppressWarnings("unchecked") + // BEGIN android-note + // removed "@param <T> The element type", which is rejected by apicheck + // END android-note public static <T> int binarySearch(List<? extends T> list, T object, Comparator<? super T> comparator) { if (comparator == null) { @@ -1516,7 +1547,7 @@ public class Collections { ListIterator<? extends T> it = list.listIterator(); while (it.hasNext()) { int result; - if ((result = comparator.compare(object, it.next())) <= 0) { + if ((result = -comparator.compare(it.next(), object)) <= 0) { if (result == 0) { return it.previousIndex(); } @@ -1529,7 +1560,7 @@ public class Collections { int low = 0, mid = list.size(), high = mid - 1, result = -1; while (low <= high) { mid = (low + high) >> 1; - if ((result = comparator.compare(object, list.get(mid))) > 0) { + if ((result = -comparator.compare(list.get(mid),object)) > 0) { low = mid + 1; } else if (result == 0) { return mid; @@ -1545,17 +1576,16 @@ public class Collections { * end both lists will have the same objects at the same index. If the * destination array is larger than the source list, the elements in the * destination list with {@code index >= source.size()} will be unchanged. - * + * * @param destination * the list whose elements are set from the source list. * @param source * the list with the elements to be copied into the destination. * @throws IndexOutOfBoundsException - * when the destination List is smaller than the source List. + * when the destination list is smaller than the source list. * @throws UnsupportedOperationException * when replacing an element in the destination list is not * supported. - * @since Android 1.0 */ public static <T> void copy(List<? super T> destination, List<? extends T> source) { @@ -1576,11 +1606,10 @@ public class Collections { /** * Returns an {@code Enumeration} on the specified collection. - * + * * @param collection * the collection to enumerate. * @return an Enumeration. - * @since Android 1.0 */ public static <T> Enumeration<T> enumeration(Collection<T> collection) { final Collection<T> c = collection; @@ -1598,15 +1627,14 @@ public class Collections { } /** - * Fills the specified List with the specified element. - * + * Fills the specified list with the specified element. + * * @param list - * the List to fill. + * the list to fill. * @param object * the element to fill the list with. * @throws UnsupportedOperationException * when replacing an element in the List is not supported. - * @since Android 1.0 */ public static <T> void fill(List<? super T> list, T object) { ListIterator<? super T> it = list.listIterator(); @@ -1617,16 +1645,15 @@ public class Collections { } /** - * Searches the specified Collection for the maximum element. - * + * Searches the specified collection for the maximum element. + * * @param collection - * the Collection to search. + * the collection to search. * @return the maximum element in the Collection. * @throws ClassCastException - * when an element in the Collection does not implement + * when an element in the collection does not implement * {@code Comparable} or elements cannot be compared to each * other. - * @since Android 1.0 */ public static <T extends Object & Comparable<? super T>> T max( Collection<? extends T> collection) { @@ -1642,18 +1669,17 @@ public class Collections { } /** - * Searches the specified Collection for the maximum element using the - * specified Comparator. - * + * Searches the specified collection for the maximum element using the + * specified comparator. + * * @param collection - * the Collection to search. + * the collection to search. * @param comparator - * the Comparator. + * the comparator. * @return the maximum element in the Collection. * @throws ClassCastException - * when elements in the Collection cannot be compared to each + * when elements in the collection cannot be compared to each * other using the {@code Comparator}. - * @since Android 1.0 */ public static <T> T max(Collection<? extends T> collection, Comparator<? super T> comparator) { @@ -1669,16 +1695,15 @@ public class Collections { } /** - * Searches the specified Collection for the minimum element. - * + * Searches the specified collection for the minimum element. + * * @param collection - * the Collection to search. - * @return the minimum element in the Collection. + * the collection to search. + * @return the minimum element in the collection. * @throws ClassCastException - * when an element in the Collection does not implement + * when an element in the collection does not implement * {@code Comparable} or elements cannot be compared to each * other. - * @since Android 1.0 */ public static <T extends Object & Comparable<? super T>> T min( Collection<? extends T> collection) { @@ -1694,18 +1719,17 @@ public class Collections { } /** - * Searches the specified Collection for the minimum element using the - * specified Comparator. - * + * Searches the specified collection for the minimum element using the + * specified comparator. + * * @param collection - * the Collection to search. + * the collection to search. * @param comparator - * the Comparator. - * @return the minimum element in the Collection. + * the comparator. + * @return the minimum element in the collection. * @throws ClassCastException - * when elements in the Collection cannot be compared to each + * when elements in the collection cannot be compared to each * other using the {@code Comparator}. - * @since Android 1.0 */ public static <T> T min(Collection<? extends T> collection, Comparator<? super T> comparator) { @@ -1721,17 +1745,16 @@ public class Collections { } /** - * Returns a List containing the specified number of the specified element. + * Returns a list containing the specified number of the specified element. * The list cannot be modified. The list is serializable. - * + * * @param length * the size of the returned list. * @param object * the element to be added {@code length} times to a list. - * @return a List containing {@code length} copies of the element. + * @return a list containing {@code length} copies of the element. * @throws IllegalArgumentException * when {@code length < 0}. - * @since Android 1.0 */ public static <T> List<T> nCopies(final int length, T object) { return new CopiesList<T>(length, object); @@ -1740,12 +1763,11 @@ public class Collections { /** * Modifies the specified {@code List} by reversing the order of the * elements. - * + * * @param list - * the List to reverse. + * the list to reverse. * @throws UnsupportedOperationException * when replacing an element in the List is not supported. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static void reverse(List<?> list) { @@ -1762,14 +1784,13 @@ public class Collections { } /** - * A Comparator which reverses the natural order of the elements. The + * A comparator which reverses the natural order of the elements. The * {@code Comparator} that's returned is {@link Serializable}. - * + * * @return a {@code Comparator} instance. * @see Comparator * @see Comparable * @see Serializable - * @since Android 1.0 */ public static <T> Comparator<T> reverseOrder() { return new ReverseComparator<T>(); @@ -1782,13 +1803,12 @@ public class Collections { * <p> * The {@code Comparator} that's returned is {@link Serializable} if the * {@code Comparator} passed is serializable or {@code null}. - * </p> - * + * * @param c * the {@code Comparator} to reverse or {@code null}. * @return a {@code Comparator} instance. * @see Comparator - * @since Android 1.0 + * @since 1.5 */ public static <T> Comparator<T> reverseOrder(Comparator<T> c) { if (c == null) { @@ -1798,38 +1818,35 @@ public class Collections { } /** - * Moves every element of the List to a random new position in the list. - * + * Moves every element of the list to a random new position in the list. + * * @param list * the List to shuffle. - * + * * @throws UnsupportedOperationException * when replacing an element in the List is not supported. - * @since Android 1.0 */ public static void shuffle(List<?> list) { shuffle(list, new Random()); } /** - * Moves every element of the List to a random new position in the list + * Moves every element of the list to a random new position in the list * using the specified random number generator. - * + * * @param list - * the List to shuffle. + * the list to shuffle. * @param random * the random number generator. - * * @throws UnsupportedOperationException - * when replacing an element in the List is not supported. - * @since Android 1.0 + * when replacing an element in the list is not supported. */ @SuppressWarnings("unchecked") public static void shuffle(List<?> list, Random random) { if (!(list instanceof RandomAccess)) { Object[] array = list.toArray(); for (int i = array.length - 1; i > 0; i--) { - int index = random.nextInt() % (i + 1); + int index = random.nextInt(i + 1); if (index < 0) { index = -index; } @@ -1848,7 +1865,7 @@ public class Collections { } else { List<Object> rawList = (List<Object>) list; for (int i = rawList.size() - 1; i > 0; i--) { - int index = random.nextInt() % (i + 1); + int index = random.nextInt(i + 1); if (index < 0) { index = -index; } @@ -1858,26 +1875,24 @@ public class Collections { } /** - * Returns a Set containing the specified element. The set cannot be + * Returns a set containing the specified element. The set cannot be * modified. The set is serializable. - * + * * @param object * the element. - * @return a Set containing the element. - * @since Android 1.0 + * @return a set containing the element. */ public static <E> Set<E> singleton(E object) { return new SingletonSet<E>(object); } /** - * Returns a List containing the specified element. The list cannot be + * Returns a list containing the specified element. The list cannot be * modified. The list is serializable. - * + * * @param object * the element. - * @return a List containing the element. - * @since Android 1.0 + * @return a list containing the element. */ public static <E> List<E> singletonList(E object) { return new SingletonList<E>(object); @@ -1886,28 +1901,26 @@ public class Collections { /** * Returns a Map containing the specified key and value. The map cannot be * modified. The map is serializable. - * + * * @param key * the key. * @param value * the value. * @return a Map containing the key and value. - * @since Android 1.0 */ public static <K, V> Map<K, V> singletonMap(K key, V value) { return new SingletonMap<K, V>(key, value); } /** - * Sorts the specified List in ascending natural order. The algorithm is + * Sorts the specified list in ascending natural order. The algorithm is * stable which means equal elements don't get reordered. - * + * * @param list - * the List to be sorted. + * the list to be sorted. * @throws ClassCastException * when an element in the List does not implement Comparable or * elements cannot be compared to each other. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static <T extends Comparable<? super T>> void sort(List<T> list) { @@ -1922,17 +1935,16 @@ public class Collections { } /** - * Sorts the specified List using the specified Comparator. The algorithm is + * Sorts the specified list using the specified comparator. The algorithm is * stable which means equal elements don't get reordered. - * + * * @param list - * the List to be sorted. + * the list to be sorted. * @param comparator - * the Comparator. + * the comparator. * @throws ClassCastException - * when elements in the List cannot be compared to each other - * using the Comparator. - * @since Android 1.0 + * when elements in the list cannot be compared to each other + * using the comparator. */ @SuppressWarnings("unchecked") public static <T> void sort(List<T> list, Comparator<? super T> comparator) { @@ -1947,26 +1959,30 @@ public class Collections { } /** - * Swaps the elements of List {@code list} at indices {@code index1} and + * Swaps the elements of list {@code list} at indices {@code index1} and * {@code index2}. - * + * * @param list - * the List to manipulate. + * the list to manipulate. * @param index1 * position of the first element to swap with the element in * index2. * @param index2 * position of the other element. - * + * * @throws IndexOutOfBoundsException * if index1 or index2 is out of range of this list. - * @since Android 1.0 + * @since 1.4 */ @SuppressWarnings("unchecked") public static void swap(List<?> list, int index1, int index2) { if (list == null) { throw new NullPointerException(); } + final int size = list.size(); + if (index1 < 0 || index1 >= size || index2 < 0 || index2 >= size) { + throw new IndexOutOfBoundsException(); + } if (index1 == index2) { return; } @@ -1978,20 +1994,18 @@ public class Collections { * Replaces all occurrences of Object {@code obj} in {@code list} with * {@code newObj}. If the {@code obj} is {@code null}, then all * occurrences of {@code null} are replaced with {@code newObj}. - * + * * @param list - * the List to modify. + * the list to modify. * @param obj - * the Object to find and replace occurrences of. + * the object to find and replace occurrences of. * @param obj2 - * the Object to replace all occurrences of {@code obj} in + * the object to replace all occurrences of {@code obj} in * {@code list}. * @return true, if at least one occurrence of {@code obj} has been found in * {@code list}. - * * @throws UnsupportedOperationException * if the list does not support setting elements. - * @since Android 1.0 */ public static <T> boolean replaceAll(List<T> list, T obj, T obj2) { int index; @@ -2005,19 +2019,17 @@ public class Collections { } /** - * Rotates the elements in List {@code list} by the distance {@code dist} + * Rotates the elements in {@code list} by the distance {@code dist} * <p> * e.g. for a given list with elements [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], * calling rotate(list, 3) or rotate(list, -7) would modify the list to look * like this: [8, 9, 0, 1, 2, 3, 4, 5, 6, 7] - * </p> - * + * * @param lst * the list whose elements are to be rotated. * @param dist * is the distance the list is rotated. This can be any valid * integer. Negative values rotate the list backwards. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static void rotate(List<?> lst, int dist) { @@ -2069,14 +2081,13 @@ public class Collections { * index of the first occurrence. * <p> * -1 is returned if the {@code sublist} does not exist in {@code list}. - * + * * @param list * the List to search {@code sublist} in. * @param sublist * the List to search in {@code list}. * @return the beginning index of the first occurrence of {@code sublist} in * {@code list}, or -1. - * @since Android 1.0 */ public static int indexOfSubList(List<?> list, List<?> sublist) { int size = list.size(); @@ -2137,14 +2148,13 @@ public class Collections { * index of the last occurrence. * <p> * -1 is returned if the {@code sublist} does not exist in {@code list}. - * + * * @param list - * the List to search {@code sublist} in. + * the list to search {@code sublist} in. * @param sublist - * the List to search in {@code list}. + * the list to search in {@code list}. * @return the beginning index of the last occurrence of {@code sublist} in * {@code list}, or -1. - * @since Android 1.0 */ public static int lastIndexOfSubList(List<?> list, List<?> sublist) { int sublistSize = sublist.size(); @@ -2198,14 +2208,13 @@ public class Collections { } /** - * Returns an {@code ArrayList} with all the elements in the - * {@code enumeration}. The elements in the returned ArrayList are in the + * Returns an {@code ArrayList} with all the elements in the {@code + * enumeration}. The elements in the returned {@code ArrayList} are in the * same order as in the {@code enumeration}. - * + * * @param enumeration * the source {@link Enumeration}. * @return an {@code ArrayList} from {@code enumeration}. - * @since Android 1.0 */ public static <T> ArrayList<T> list(Enumeration<T> enumeration) { ArrayList<T> list = new ArrayList<T>(); @@ -2216,13 +2225,12 @@ public class Collections { } /** - * Returns a wrapper on the specified Collection which synchronizes all - * access to the Collection. - * + * Returns a wrapper on the specified collection which synchronizes all + * access to the collection. + * * @param collection * the Collection to wrap in a synchronized collection. * @return a synchronized Collection. - * @since Android 1.0 */ public static <T> Collection<T> synchronizedCollection( Collection<T> collection) { @@ -2235,11 +2243,10 @@ public class Collections { /** * Returns a wrapper on the specified List which synchronizes all access to * the List. - * + * * @param list * the List to wrap in a synchronized list. * @return a synchronized List. - * @since Android 1.0 */ public static <T> List<T> synchronizedList(List<T> list) { if (list == null) { @@ -2252,13 +2259,12 @@ public class Collections { } /** - * Returns a wrapper on the specified Map which synchronizes all access to - * the Map. - * + * Returns a wrapper on the specified map which synchronizes all access to + * the map. + * * @param map - * the Map to wrap in a synchronized map. + * the map to wrap in a synchronized map. * @return a synchronized Map. - * @since Android 1.0 */ public static <K, V> Map<K, V> synchronizedMap(Map<K, V> map) { if (map == null) { @@ -2268,13 +2274,12 @@ public class Collections { } /** - * Returns a wrapper on the specified Set which synchronizes all access to - * the Set. - * + * Returns a wrapper on the specified set which synchronizes all access to + * the set. + * * @param set - * the Set to wrap in a synchronized set. - * @return a synchronized Set. - * @since Android 1.0 + * the set to wrap in a synchronized set. + * @return a synchronized set. */ public static <E> Set<E> synchronizedSet(Set<E> set) { if (set == null) { @@ -2284,13 +2289,12 @@ public class Collections { } /** - * Returns a wrapper on the specified SortedMap which synchronizes all - * access to the SortedMap. - * + * Returns a wrapper on the specified sorted map which synchronizes all + * access to the sorted map. + * * @param map - * the SortedMap to wrap in a synchronized sorted map. - * @return a synchronized SortedMap. - * @since Android 1.0 + * the sorted map to wrap in a synchronized sorted map. + * @return a synchronized sorted map. */ public static <K, V> SortedMap<K, V> synchronizedSortedMap( SortedMap<K, V> map) { @@ -2301,13 +2305,12 @@ public class Collections { } /** - * Returns a wrapper on the specified SortedSet which synchronizes all - * access to the SortedSet. - * + * Returns a wrapper on the specified sorted set which synchronizes all + * access to the sorted set. + * * @param set - * the SortedSet to wrap in a synchronized sorted set. - * @return a synchronized SortedSet. - * @since Android 1.0 + * the sorted set to wrap in a synchronized sorted set. + * @return a synchronized sorted set. */ public static <E> SortedSet<E> synchronizedSortedSet(SortedSet<E> set) { if (set == null) { @@ -2317,14 +2320,13 @@ public class Collections { } /** - * Returns a wrapper on the specified Collection which throws an + * Returns a wrapper on the specified collection which throws an * {@code UnsupportedOperationException} whenever an attempt is made to - * modify the Collection. - * + * modify the collection. + * * @param collection - * the Collection to wrap in an unmodifiable collection. - * @return an unmodifiable Collection. - * @since Android 1.0 + * the collection to wrap in an unmodifiable collection. + * @return an unmodifiable collection. */ @SuppressWarnings("unchecked") public static <E> Collection<E> unmodifiableCollection( @@ -2336,14 +2338,13 @@ public class Collections { } /** - * Returns a wrapper on the specified List which throws an + * Returns a wrapper on the specified list which throws an * {@code UnsupportedOperationException} whenever an attempt is made to - * modify the List. - * + * modify the list. + * * @param list - * the List to wrap in an unmodifiable list. + * the list to wrap in an unmodifiable list. * @return an unmodifiable List. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static <E> List<E> unmodifiableList(List<? extends E> list) { @@ -2357,14 +2358,13 @@ public class Collections { } /** - * Returns a wrapper on the specified Map which throws an + * Returns a wrapper on the specified map which throws an * {@code UnsupportedOperationException} whenever an attempt is made to - * modify the Map. - * + * modify the map. + * * @param map - * the Map to wrap in an unmodifiable map. - * @return a unmodifiable Map. - * @since Android 1.0 + * the map to wrap in an unmodifiable map. + * @return a unmodifiable map. */ @SuppressWarnings("unchecked") public static <K, V> Map<K, V> unmodifiableMap( @@ -2376,14 +2376,13 @@ public class Collections { } /** - * Returns a wrapper on the specified Set which throws an + * Returns a wrapper on the specified set which throws an * {@code UnsupportedOperationException} whenever an attempt is made to - * modify the Set. - * + * modify the set. + * * @param set - * the Set to wrap in an unmodifiable set. - * @return a unmodifiable Set. - * @since Android 1.0 + * the set to wrap in an unmodifiable set. + * @return a unmodifiable set */ @SuppressWarnings("unchecked") public static <E> Set<E> unmodifiableSet(Set<? extends E> set) { @@ -2394,14 +2393,13 @@ public class Collections { } /** - * Returns a wrapper on the specified SortedMap which throws an + * Returns a wrapper on the specified sorted map which throws an * {@code UnsupportedOperationException} whenever an attempt is made to - * modify the SortedMap. - * + * modify the sorted map. + * * @param map - * the SortedMap to wrap in an unmodifiable sorted map. - * @return a unmodifiable SortedMap. - * @since Android 1.0 + * the sorted map to wrap in an unmodifiable sorted map. + * @return a unmodifiable sorted map */ @SuppressWarnings("unchecked") public static <K, V> SortedMap<K, V> unmodifiableSortedMap( @@ -2413,14 +2411,13 @@ public class Collections { } /** - * Returns a wrapper on the specified SortedSet which throws an + * Returns a wrapper on the specified sorted set which throws an * {@code UnsupportedOperationException} whenever an attempt is made to - * modify the SortedSet. - * + * modify the sorted set. + * * @param set - * the SortedSet to wrap in an unmodifiable sorted set. - * @return a unmodifiable SortedSet. - * @since Android 1.0 + * the sorted set to wrap in an unmodifiable sorted set. + * @return a unmodifiable sorted set. */ public static <E> SortedSet<E> unmodifiableSortedSet(SortedSet<E> set) { if (set == null) { @@ -2433,8 +2430,7 @@ public class Collections { * Returns the number of elements in the {@code Collection} that match the * {@code Object} passed. If the {@code Object} is {@code null}, then the * number of {@code null} elements is returned. - * </p> - * + * * @param c * the {@code Collection} to search. * @param o @@ -2442,7 +2438,7 @@ public class Collections { * @return the number of matching elements. * @throws NullPointerException * if the {@code Collection} parameter is {@code null}. - * @since Android 1.0 + * @since 1.5 */ public static int frequency(Collection<?> c, Object o) { if (c == null) { @@ -2464,10 +2460,10 @@ public class Collections { /** * Returns a type-safe empty, immutable {@link List}. - * + * * @return an empty {@link List}. + * @since 1.5 * @see #EMPTY_LIST - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final <T> List<T> emptyList() { @@ -2476,10 +2472,10 @@ public class Collections { /** * Returns a type-safe empty, immutable {@link Set}. - * + * * @return an empty {@link Set}. + * @since 1.5 * @see #EMPTY_SET - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final <T> Set<T> emptySet() { @@ -2488,10 +2484,10 @@ public class Collections { /** * Returns a type-safe empty, immutable {@link Map}. - * + * * @return an empty {@link Map}. + * @since 1.5 * @see #EMPTY_MAP - * @since Android 1.0 */ @SuppressWarnings("unchecked") public static final <K, V> Map<K, V> emptyMap() { @@ -2503,13 +2499,12 @@ public class Collections { * to insert an element of the wrong type into this collection throws a * {@code ClassCastException}. At creation time the types in {@code c} are * not checked for correct type. - * + * * @param c * the collection to be wrapped in a typesafe collection. * @param type * the type of the elements permitted to insert. * @return a typesafe collection. - * @since Android 1.0 */ public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type) { @@ -2521,7 +2516,7 @@ public class Collections { * insert an element of the wrong type into this map throws a * {@code ClassCastException}. At creation time the types in {@code m} are * not checked for correct type. - * + * * @param m * the map to be wrapped in a typesafe map. * @param keyType @@ -2529,7 +2524,6 @@ public class Collections { * @param valueType * the type of the values permitted to insert. * @return a typesafe map. - * @since Android 1.0 */ public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) { @@ -2541,13 +2535,12 @@ public class Collections { * insert an element of the wrong type into this list throws a * {@code ClassCastException}. At creation time the types in {@code list} * are not checked for correct type. - * + * * @param list * the list to be wrapped in a typesafe list. * @param type * the type of the elements permitted to insert. * @return a typesafe list. - * @since Android 1.0 */ public static <E> List<E> checkedList(List<E> list, Class<E> type) { if (list instanceof RandomAccess) { @@ -2561,13 +2554,12 @@ public class Collections { * insert an element of the wrong type into this set throws a * {@code ClassCastException}. At creation time the types in {@code s} are * not checked for correct type. - * + * * @param s * the set to be wrapped in a typesafe set. * @param type * the type of the elements permitted to insert. * @return a typesafe set. - * @since Android 1.0 */ public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) { return new CheckedSet<E>(s, type); @@ -2578,7 +2570,7 @@ public class Collections { * to insert an element of the wrong type into this sorted map throws a * {@code ClassCastException}. At creation time the types in {@code m} are * not checked for correct type. - * + * * @param m * the sorted map to be wrapped in a typesafe sorted map. * @param keyType @@ -2586,7 +2578,6 @@ public class Collections { * @param valueType * the type of the values permitted to insert. * @return a typesafe sorted map. - * @since Android 1.0 */ public static <K, V> SortedMap<K, V> checkedSortedMap(SortedMap<K, V> m, Class<K> keyType, Class<V> valueType) { @@ -2598,13 +2589,12 @@ public class Collections { * to insert an element of the wrong type into this sorted set throws a * {@code ClassCastException}. At creation time the types in {@code s} are * not checked for correct type. - * + * * @param s * the sorted set to be wrapped in a typesafe sorted set. * @param type * the type of the elements permitted to insert. * @return a typesafe sorted set. - * @since Android 1.0 */ public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s, Class<E> type) { @@ -2613,7 +2603,7 @@ public class Collections { /** * Adds all the specified elements to the specified collection. - * + * * @param c * the collection the elements are to be inserted into. * @param a @@ -2628,7 +2618,6 @@ public class Collections { * @throws IllegalArgumentException * if at least one of the elements can't be inserted into the * collection. - * @since Android 1.0 */ public static <T> boolean addAll(Collection<? super T> c, T... a) { boolean modified = false; @@ -2640,7 +2629,7 @@ public class Collections { /** * Returns whether the specified collections have no elements in common. - * + * * @param c1 * the first collection. * @param c2 @@ -2649,7 +2638,6 @@ public class Collections { * {@code false} otherwise. * @throws NullPointerException * if one of the collections is {@code null}. - * @since Android 1.0 */ public static boolean disjoint(Collection<?> c1, Collection<?> c2) { if ((c1 instanceof Set) && !(c2 instanceof Set) @@ -2670,7 +2658,7 @@ public class Collections { /** * Checks if specified object is instance of specified class. Used for a * dynamically typesafe view of the collections. - * + * * @param obj - * object is to be checked * @param type - @@ -2701,7 +2689,7 @@ public class Collections { /** * Constructs a dynamically typesafe view of the specified collection. - * + * * @param c - * the collection for which an unmodifiable view is to be * constructed. @@ -2844,7 +2832,7 @@ public class Collections { /** * Constructs a dynamically typesafe view of the specified ListIterator. - * + * * @param i - * the listIterator for which a dynamically typesafe view to * be constructed. @@ -2930,7 +2918,7 @@ public class Collections { /** * Constructs a dynamically typesafe view of the specified list. - * + * * @param l - * the list for which a dynamically typesafe view is to be * constructed. @@ -3049,7 +3037,7 @@ public class Collections { /** * Constructs a dynamically typesafe view of the specified * randomAccessList. - * + * * @param l - * the randomAccessList for which a dynamically typesafe view * is to be constructed. @@ -3069,7 +3057,7 @@ public class Collections { /** * Constructs a dynamically typesafe view of the specified set. - * + * * @param s - * the set for which a dynamically typesafe view is to be * constructed. @@ -3111,7 +3099,7 @@ public class Collections { /** * Constructs a dynamically typesafe view of the specified map. - * + * * @param m - * the map for which a dynamically typesafe view is to be * constructed. @@ -3262,10 +3250,12 @@ public class Collections { /** * Constructs a dynamically typesafe view of the specified map * entry. - * - * @param e - + * + * @param e * the map entry for which a dynamically typesafe view is * to be constructed. + * @param valueType + * the type of the value */ public CheckedEntry(Map.Entry<K, V> e, Class<V> valueType) { if (e == null) { diff --git a/luni/src/main/java/java/util/Comparator.java b/luni/src/main/java/java/util/Comparator.java index 7b09448..2d6f598 100644 --- a/luni/src/main/java/java/util/Comparator.java +++ b/luni/src/main/java/java/util/Comparator.java @@ -25,8 +25,8 @@ package java.util; * method has to return zero for each pair of elements (a,b) where a.equals(b) * holds true. It is recommended that a {@code Comparator} implements * {@link java.io.Serializable}. - * - * @since Android 1.0 + * + * @since 1.2 */ public interface Comparator<T> { /** @@ -42,15 +42,15 @@ public interface Comparator<T> { * follow {@code compare(a,c) > 0} for all possible combinations of {@code * (a,b,c)}</li> * </ul> - * + * * @param object1 * an {@code Object}. * @param object2 * a second {@code Object} to compare with {@code object1}. * @return an integer < 0 if {@code object1} is less than {@code object2}, 0 if they are * equal, and > 0 if {@code object1} is greater than {@code object2}. - * @exception ClassCastException - * when objects are not of the correct type. + * @throws ClassCastException + * if objects are not of the correct type. */ public int compare(T object1, T object2); @@ -61,7 +61,7 @@ public interface Comparator<T> { * <p> * A {@code Comparator} never needs to override this method, but may choose so for * performance reasons. - * + * * @param object * the {@code Object} to compare with this comparator. * @return boolean {@code true} if specified {@code Object} is the same as this diff --git a/luni/src/main/java/java/util/Currency.java b/luni/src/main/java/java/util/Currency.java index 8ac0e6e..79de49d 100644 --- a/luni/src/main/java/java/util/Currency.java +++ b/luni/src/main/java/java/util/Currency.java @@ -17,15 +17,15 @@ package java.util; -import java.io.Serializable; - +// BEGIN android-added import org.apache.harmony.luni.util.Msg; +// END android-added + +import java.io.Serializable; /** * This class represents a currency as identified in the ISO 4217 currency * codes. - * - * @since Android 1.0 */ public final class Currency implements Serializable { @@ -35,9 +35,11 @@ public final class Currency implements Serializable { private String currencyCode; + // BEGIN android-added private static String currencyVars = "EURO, HK, PREEURO"; //$NON-NLS-1$ private transient int defaultFractionDigits; + // END android-added /** * @param currencyCode @@ -49,20 +51,20 @@ public final class Currency implements Serializable { /** * Returns the {@code Currency} instance for this currency code. * <p> - * + * * @param currencyCode * the currency code. * @return the {@code Currency} instance for this currency code. - * + * * @throws IllegalArgumentException * if the currency code is not a supported ISO 4217 currency * code. - * @since Android 1.0 */ public static Currency getInstance(String currencyCode) { Currency currency = codesToCurrencies.get(currencyCode); if (currency == null) { + // BEGIN android-added ResourceBundle bundle = Locale.getBundle( "ISO4CurrenciesToDigits", Locale.getDefault()); //$NON-NLS-1$ currency = new Currency(currencyCode); @@ -77,6 +79,7 @@ public final class Currency implements Serializable { } currency.defaultFractionDigits = Integer .parseInt(defaultFractionDigits); + // END android-added codesToCurrencies.put(currencyCode, currency); } @@ -85,16 +88,26 @@ public final class Currency implements Serializable { /** * Returns the {@code Currency} instance for this {@code Locale}'s country. - * + * * @param locale * the {@code Locale} of a country. * @return the {@code Currency} used in the country defined by the locale parameter. - * + * * @throws IllegalArgumentException * if the locale's country is not a supported ISO 3166 Country. - * @since Android 1.0 */ public static Currency getInstance(Locale locale) { + // BEGIN android-changed + // com.ibm.icu.util.Currency currency = null; + // try { + // currency = com.ibm.icu.util.Currency.getInstance(locale); + // } catch (IllegalArgumentException e) { + // return null; + // } + // if (currency == null) { + // throw new IllegalArgumentException(locale.getCountry()); + // } + // String currencyCode = currency.getCurrencyCode(); String country = locale.getCountry(); String variant = locale.getVariant(); if (!variant.equals("") && currencyVars.indexOf(variant) > -1) { //$NON-NLS-1$ @@ -110,6 +123,7 @@ public final class Currency implements Serializable { throw new IllegalArgumentException(Msg.getString( "K0323", locale.toString())); //$NON-NLS-1$ } + // END android-changed if (currencyCode.equals("None")) { //$NON-NLS-1$ return null; @@ -120,9 +134,8 @@ public final class Currency implements Serializable { /** * Returns this {@code Currency}'s ISO 4217 currency code. - * + * * @return this {@code Currency}'s ISO 4217 currency code. - * @since Android 1.0 */ public String getCurrencyCode() { return currencyCode; @@ -133,9 +146,8 @@ public final class Currency implements Serializable { * if the default locale is the US, the symbol of the US dollar is "$". For * other locales it may be "US$". If no symbol can be determined, the ISO * 4217 currency code of the US dollar is returned. - * + * * @return the symbol for this {@code Currency} in the default {@code Locale}. - * @since Android 1.0 */ public String getSymbol() { return getSymbol(Locale.getDefault()); @@ -157,18 +169,19 @@ public final class Currency implements Serializable { * symbol for this currency in this bundle, then the * ISO 4217 currency code is returned. * <p> - * + * * @param locale * the locale for which the currency symbol should be returned. * @return the representation of this {@code Currency}'s symbol in the specified * locale. - * @since Android 1.0 */ public String getSymbol(Locale locale) { if (locale.getCountry().equals("")) { //$NON-NLS-1$ return currencyCode; } + // BEGIN android-changed + // return com.ibm.icu.util.Currency.getInstance(currencyCode).getSymbol(locale); // check in the Locale bundle first, if the local has the same currency ResourceBundle bundle = Locale.getBundle("Locale", locale); //$NON-NLS-1$ if (((String) bundle.getObject("IntCurrencySymbol")) //$NON-NLS-1$ @@ -197,6 +210,7 @@ public final class Currency implements Serializable { return result; } return currencyCode; + // END android-changed } /** @@ -204,19 +218,20 @@ public final class Currency implements Serializable { * instance, the default number of fraction digits for the US dollar is 2. * For the Japanese Yen the number is 0. In the case of pseudo-currencies, * such as IMF Special Drawing Rights, -1 is returned. - * + * * @return the default number of fraction digits for this currency. - * @since Android 1.0 */ public int getDefaultFractionDigits() { + // BEGIN android-changed + // return com.ibm.icu.util.Currency.getInstance(currencyCode).getDefaultFractionDigits(); return defaultFractionDigits; + // END android-changed } /** * Returns this currency's ISO 4217 currency code. - * + * * @return this currency's ISO 4217 currency code. - * @since Android 1.0 */ @Override public String toString() { diff --git a/luni/src/main/java/java/util/Date.java b/luni/src/main/java/java/util/Date.java index 172f682..7bd7261 100644 --- a/luni/src/main/java/java/util/Date.java +++ b/luni/src/main/java/java/util/Date.java @@ -29,13 +29,12 @@ import org.apache.harmony.luni.internal.nls.Messages; /** * {@code Date} represents a specific moment in time, to the millisecond. - * + * * @see System#currentTimeMillis * @see Calendar * @see GregorianCalendar * @see SimpleTimeZone * @see TimeZone - * @since Android 1.0 */ public class Date implements Serializable, Cloneable, Comparable<Date> { @@ -46,10 +45,15 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { private transient long milliseconds; + private static String[] dayOfWeekNames = { "Sun", "Mon", "Tue", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + "Wed", "Thu", "Fri", "Sat" }; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + private static String[] monthNames = { "Jan", "Feb", "Mar", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + "Apr", "May", "Jun", "Jul", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + "Aug", "Sep", "Oct", "Nov", "Dec"}; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + /** * Initializes this {@code Date} instance to the current date and time. - * - * @since Android 1.0 */ public Date() { this(System.currentTimeMillis()); @@ -58,17 +62,16 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Constructs a new {@code Date} initialized to midnight in the default {@code TimeZone} on * the specified date. - * + * * @param year * the year, 0 is 1900. * @param month * the month, 0 - 11. * @param day * the day of the month, 1 - 31. - * + * * @deprecated use * {@link GregorianCalendar#GregorianCalendar(int, int, int)} - * @since Android 1.0 */ @Deprecated public Date(int year, int month, int day) { @@ -80,7 +83,7 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Constructs a new {@code Date} initialized to the specified date and time in the * default {@code TimeZone}. - * + * * @param year * the year, 0 is 1900. * @param month @@ -91,10 +94,9 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { * the hour of day, 0 - 23. * @param minute * the minute of the hour, 0 - 59. - * + * * @deprecated use * {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int)} - * @since Android 1.0 */ @Deprecated public Date(int year, int month, int day, int hour, int minute) { @@ -106,7 +108,7 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Constructs a new {@code Date} initialized to the specified date and time in the * default {@code TimeZone}. - * + * * @param year * the year, 0 is 1900. * @param month @@ -119,10 +121,9 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { * the minute of the hour, 0 - 59. * @param second * the second of the minute, 0 - 59. - * + * * @deprecated use * {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int, int)} - * @since Android 1.0 */ @Deprecated public Date(int year, int month, int day, int hour, int minute, int second) { @@ -134,24 +135,22 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Initializes this {@code Date} instance using the specified millisecond value. The * value is the number of milliseconds since Jan. 1, 1970 GMT. - * + * * @param milliseconds * the number of milliseconds since Jan. 1, 1970 GMT. - * @since Android 1.0 */ public Date(long milliseconds) { - this.setTime(milliseconds); + this.milliseconds = milliseconds; } /** * Constructs a new {@code Date} initialized to the date and time parsed from the * specified String. - * + * * @param string * the String to parse. - * + * * @deprecated use {@link DateFormat} - * @since Android 1.0 */ @Deprecated public Date(String string) { @@ -160,12 +159,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns if this {@code Date} is after the specified Date. - * + * * @param date * a Date instance to compare. * @return {@code true} if this {@code Date} is after the specified {@code Date}, * {@code false} otherwise. - * @since Android 1.0 */ public boolean after(Date date) { return milliseconds > date.milliseconds; @@ -173,12 +171,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns if this {@code Date} is before the specified Date. - * + * * @param date * a {@code Date} instance to compare. * @return {@code true} if this {@code Date} is before the specified {@code Date}, * {@code false} otherwise. - * @since Android 1.0 */ public boolean before(Date date) { return milliseconds < date.milliseconds; @@ -186,11 +183,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns a new {@code Date} with the same millisecond value as this {@code Date}. - * + * * @return a shallow copy of this {@code Date}. - * + * * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -204,12 +200,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Compare the receiver to the specified {@code Date} to determine the relative * ordering. - * + * * @param date * a {@code Date} to compare against. * @return an {@code int < 0} if this {@code Date} is less than the specified {@code Date}, {@code 0} if * they are equal, and an {@code int > 0} if this {@code Date} is greater. - * @since Android 1.0 */ public int compareTo(Date date) { if (milliseconds < date.milliseconds) { @@ -225,14 +220,13 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { * Compares the specified object to this {@code Date} and returns if they are equal. * To be equal, the object must be an instance of {@code Date} and have the same millisecond * value. - * + * * @param object * the object to compare with this object. * @return {@code true} if the specified object is equal to this {@code Date}, {@code false} * otherwise. - * + * * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -242,11 +236,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the gregorian calendar day of the month for this {@code Date} object. - * + * * @return the day of the month. - * + * * @deprecated use {@code Calendar.get(Calendar.DATE)} - * @since Android 1.0 */ @Deprecated public int getDate() { @@ -255,11 +248,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the gregorian calendar day of the week for this {@code Date} object. - * + * * @return the day of the week. - * + * * @deprecated use {@code Calendar.get(Calendar.DAY_OF_WEEK)} - * @since Android 1.0 */ @Deprecated public int getDay() { @@ -268,11 +260,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the gregorian calendar hour of the day for this {@code Date} object. - * + * * @return the hour of the day. - * + * * @deprecated use {@code Calendar.get(Calendar.HOUR_OF_DAY)} - * @since Android 1.0 */ @Deprecated public int getHours() { @@ -281,11 +272,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the gregorian calendar minute of the hour for this {@code Date} object. - * + * * @return the minutes. - * + * * @deprecated use {@code Calendar.get(Calendar.MINUTE)} - * @since Android 1.0 */ @Deprecated public int getMinutes() { @@ -294,11 +284,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the gregorian calendar month for this {@code Date} object. - * + * * @return the month. - * + * * @deprecated use {@code Calendar.get(Calendar.MONTH)} - * @since Android 1.0 */ @Deprecated public int getMonth() { @@ -307,11 +296,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the gregorian calendar second of the minute for this {@code Date} object. - * + * * @return the seconds. - * + * * @deprecated use {@code Calendar.get(Calendar.SECOND)} - * @since Android 1.0 */ @Deprecated public int getSeconds() { @@ -321,9 +309,8 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns this {@code Date} as a millisecond value. The value is the number of * milliseconds since Jan. 1, 1970, midnight GMT. - * + * * @return the number of milliseconds since Jan. 1, 1970, midnight GMT. - * @since Android 1.0 */ public long getTime() { return milliseconds; @@ -331,12 +318,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the timezone offset in minutes of the default {@code TimeZone}. - * + * * @return the timezone offset in minutes of the default {@code TimeZone}. - * + * * @deprecated use * {@code (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000} - * @since Android 1.0 */ @Deprecated public int getTimezoneOffset() { @@ -346,11 +332,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the gregorian calendar year since 1900 for this {@code Date} object. - * + * * @return the year - 1900. - * + * * @deprecated use {@code Calendar.get(Calendar.YEAR) - 1900} - * @since Android 1.0 */ @Deprecated public int getYear() { @@ -360,11 +345,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns an integer hash code for the receiver. Objects which are equal * return the same value for this method. - * + * * @return this {@code Date}'s hash. - * + * * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -384,13 +368,12 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { * Returns the millisecond value of the date and time parsed from the * specified {@code String}. Many date/time formats are recognized, including IETF * standard syntax, i.e. Tue, 22 Jun 1999 12:16:00 GMT-0500 - * + * * @param string * the String to parse. * @return the millisecond value parsed from the String. - * + * * @deprecated use {@link DateFormat} - * @since Android 1.0 */ @Deprecated public static long parse(String string) { @@ -404,7 +387,7 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { int commentLevel = 0; int offset = 0, length = string.length(), state = 0; int year = -1, month = -1, date = -1; - int hour = -1, minute = -1, second = -1, zoneOffset = 0; + 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(); @@ -442,6 +425,14 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { if (sign == '+' || sign == '-') { if (zoneOffset == 0) { zone = true; + if (next == ':') { + minutesOffset = sign == '-' ? -Integer + .parseInt(string.substring(offset, + offset + 2)) : Integer + .parseInt(string.substring(offset, + offset + 2)); + offset += 2; + } zoneOffset = sign == '-' ? -digit : digit; sign = 0; } else { @@ -557,6 +548,7 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { } else if (year < 100) { year += 1900; } + minute -= minutesOffset; if (zone) { if (zoneOffset >= 24 || zoneOffset <= -24) { hour -= zoneOffset / 100; @@ -574,12 +566,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Sets the gregorian calendar day of the month for this {@code Date} object. - * + * * @param day * the day of the month. - * + * * @deprecated use {@code Calendar.set(Calendar.DATE, day)} - * @since Android 1.0 */ @Deprecated public void setDate(int day) { @@ -590,12 +581,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Sets the gregorian calendar hour of the day for this {@code Date} object. - * + * * @param hour * the hour of the day. - * + * * @deprecated use {@code Calendar.set(Calendar.HOUR_OF_DAY, hour)} - * @since Android 1.0 */ @Deprecated public void setHours(int hour) { @@ -606,12 +596,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Sets the gregorian calendar minute of the hour for this {@code Date} object. - * + * * @param minute * the minutes. - * + * * @deprecated use {@code Calendar.set(Calendar.MINUTE, minute)} - * @since Android 1.0 */ @Deprecated public void setMinutes(int minute) { @@ -622,12 +611,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Sets the gregorian calendar month for this {@code Date} object. - * + * * @param month * the month. - * + * * @deprecated use {@code Calendar.set(Calendar.MONTH, month)} - * @since Android 1.0 */ @Deprecated public void setMonth(int month) { @@ -638,12 +626,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Sets the gregorian calendar second of the minute for this {@code Date} object. - * + * * @param second * the seconds. - * + * * @deprecated use {@code Calendar.set(Calendar.SECOND, second)} - * @since Android 1.0 */ @Deprecated public void setSeconds(int second) { @@ -655,10 +642,9 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Sets this {@code Date} to the specified millisecond value. The value is the * number of milliseconds since Jan. 1, 1970 GMT. - * + * * @param milliseconds * the number of milliseconds since Jan. 1, 1970 GMT. - * @since Android 1.0 */ public void setTime(long milliseconds) { this.milliseconds = milliseconds; @@ -666,12 +652,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Sets the gregorian calendar year since 1900 for this {@code Date} object. - * + * * @param year * the year since 1900. - * + * * @deprecated use {@code Calendar.set(Calendar.YEAR, year + 1900)} - * @since Android 1.0 */ @Deprecated public void setYear(int year) { @@ -683,11 +668,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the string representation of this {@code Date} in GMT in the format: 22 * Jun 1999 13:02:00 GMT - * + * * @return the string representation of this {@code Date} in GMT. - * + * * @deprecated use {@link DateFormat} - * @since Android 1.0 */ @Deprecated public String toGMTString() { @@ -705,11 +689,10 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the string representation of this {@code Date} for the default {@code Locale}. - * + * * @return the string representation of this {@code Date} for the default {@code Locale}. - * + * * @deprecated use {@link DateFormat} - * @since Android 1.0 */ @Deprecated public String toLocaleString() { @@ -719,20 +702,29 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { /** * Returns the string representation of this {@code Date} in the format: Tue Jun 22 * 13:07:00 GMT 1999 - * + * * @return the string representation of this {@code Date}. - * @since Android 1.0 */ @Override public String toString() { - return new SimpleDateFormat("E MMM dd HH:mm:ss z ", Locale.US) //$NON-NLS-1$ - .format(this) - + new GregorianCalendar(milliseconds).get(Calendar.YEAR); + Calendar cal = new GregorianCalendar(milliseconds); + return dayOfWeekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " " + monthNames[cal.get(Calendar.MONTH)]//$NON-NLS-1$ + + " " + toTwoDigits(cal.get(Calendar.DAY_OF_MONTH)) + " " + toTwoDigits(cal.get(Calendar.HOUR_OF_DAY))//$NON-NLS-1$ //$NON-NLS-2$ + + ":" + toTwoDigits(cal.get(Calendar.MINUTE)) + ":" + toTwoDigits(cal.get(Calendar.SECOND))//$NON-NLS-1$ //$NON-NLS-2$ + + " " + cal.getTimeZone().getID() + " " + cal.get(Calendar.YEAR);//$NON-NLS-1$ //$NON-NLS-2$ + } + + private String toTwoDigits(int digit) { + if(digit >= 10) { + return "" + digit;//$NON-NLS-1$ + } else { + return "0" + digit;//$NON-NLS-1$ + } } /** * Returns the millisecond value of the specified date and time in GMT. - * + * * @param year * the year, 0 is 1900. * @param month @@ -746,12 +738,11 @@ public class Date implements Serializable, Cloneable, Comparable<Date> { * @param second * the second of the minute, 0 - 59. * @return the date and time in GMT in milliseconds. - * + * * @deprecated use: <code> * Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); * cal.set(year + 1900, month, day, hour, minute, second); * cal.getTime().getTime();</code> - * @since Android 1.0 */ @Deprecated public static long UTC(int year, int month, int day, int hour, int minute, diff --git a/luni/src/main/java/java/util/Dictionary.java b/luni/src/main/java/java/util/Dictionary.java index 236ddf0..c29b11b 100644 --- a/luni/src/main/java/java/util/Dictionary.java +++ b/luni/src/main/java/java/util/Dictionary.java @@ -25,14 +25,11 @@ package java.util; * associate keys with values, such as {@code Hashtable}. * * @see Hashtable - * @since Android 1.0 + * @since 1.0 */ -public abstract class Dictionary<K,V> { - +public abstract class Dictionary<K, V> { /** * Constructs a new instance of this class. - * - * @since Android 1.0 */ public Dictionary() { super(); @@ -45,7 +42,6 @@ public abstract class Dictionary<K,V> { * @see #keys * @see #size * @see Enumeration - * @since Android 1.0 */ public abstract Enumeration<V> elements(); @@ -57,7 +53,6 @@ public abstract class Dictionary<K,V> { * @return the value associated with {@code key}, or {@code null} if the * specified key does not exist. * @see #put - * @since Android 1.0 */ public abstract V get(Object key); @@ -67,7 +62,6 @@ public abstract class Dictionary<K,V> { * @return {@code true} if this dictionary has no key/value pairs, * {@code false} otherwise. * @see #size - * @since Android 1.0 */ public abstract boolean isEmpty(); @@ -78,7 +72,6 @@ public abstract class Dictionary<K,V> { * @see #elements * @see #size * @see Enumeration - * @since Android 1.0 */ public abstract Enumeration<K> keys(); @@ -96,7 +89,6 @@ public abstract class Dictionary<K,V> { * @see #elements * @see #get * @see #keys - * @since Android 1.0 */ public abstract V put(K key, V value); @@ -110,7 +102,6 @@ public abstract class Dictionary<K,V> { * {@code key} was not known to this dictionary. * @see #get * @see #put - * @since Android 1.0 */ public abstract V remove(Object key); @@ -120,7 +111,6 @@ public abstract class Dictionary<K,V> { * @return the number of key/value pairs in this dictionary. * @see #elements * @see #keys - * @since Android 1.0 */ public abstract int size(); } diff --git a/luni/src/main/java/java/util/DuplicateFormatFlagsException.java b/luni/src/main/java/java/util/DuplicateFormatFlagsException.java index 908aa36..3330dcb 100644 --- a/luni/src/main/java/java/util/DuplicateFormatFlagsException.java +++ b/luni/src/main/java/java/util/DuplicateFormatFlagsException.java @@ -19,12 +19,11 @@ package java.util; /** * The unchecked exception will be thrown out if there are duplicate flags given * out in the format specifier. - * + * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class DuplicateFormatFlagsException extends IllegalFormatException { - + private static final long serialVersionUID = 18890531L; private String flags; diff --git a/luni/src/main/java/java/util/EmptyStackException.java b/luni/src/main/java/java/util/EmptyStackException.java index 73d33ba..d8a48cc 100644 --- a/luni/src/main/java/java/util/EmptyStackException.java +++ b/luni/src/main/java/java/util/EmptyStackException.java @@ -21,9 +21,8 @@ package java.util; /** * An {@code EmptyStackException} is thrown if the pop/peek method of a stack is * executed on an empty stack. - * + * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class EmptyStackException extends RuntimeException { diff --git a/luni/src/main/java/java/util/EnumMap.java b/luni/src/main/java/java/util/EnumMap.java index 1351069..975fdad 100644 --- a/luni/src/main/java/java/util/EnumMap.java +++ b/luni/src/main/java/java/util/EnumMap.java @@ -24,11 +24,14 @@ import java.lang.reflect.Array; /** * An {@code Map} specialized for use with {@code Enum} types as keys. - * - * @since Android 1.0 */ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements - Map<K, V>, Serializable, Cloneable { + Serializable, Cloneable, Map<K, V> { + + // BEGIN android-changed + // added implements Map<K, V> for apicheck + // END android-changed + private static final long serialVersionUID = 458661240069192865L; private Class<K> keyType; @@ -57,6 +60,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements ordinal = ((Enum) theKey).ordinal(); } + @SuppressWarnings("unchecked") @Override public boolean equals(Object object) { if (!enumMap.hasMapping[ordinal]) { @@ -83,18 +87,21 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements : enumMap.values[ordinal].hashCode()); } + @SuppressWarnings("unchecked") @Override public KT getKey() { checkEntryStatus(); return (KT) enumMap.keys[ordinal]; } + @SuppressWarnings("unchecked") @Override public VT getValue() { checkEntryStatus(); return (VT) enumMap.values[ordinal]; } + @SuppressWarnings("unchecked") @Override public VT setValue(VT value) { checkEntryStatus(); @@ -285,6 +292,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements super(value, em); } + @SuppressWarnings("unchecked") @Override public E next() { if (!hasNext()) { @@ -354,6 +362,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements return toArray(entryArray); } + @SuppressWarnings("unchecked") @Override public Object[] toArray(Object[] array) { int size = enumMap.size(); @@ -378,10 +387,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Constructs an empty {@code EnumMap} using the given key type. - * + * * @param keyType * the class object giving the type of the keys used by this {@code EnumMap}. - * @since Android 1.0 + * @throws NullPointerException + * if {@code keyType} is {@code null}. */ public EnumMap(Class<K> keyType) { initialization(keyType); @@ -390,10 +400,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Constructs an {@code EnumMap} using the same key type as the given {@code EnumMap} and * initially containing the same mappings. - * + * * @param map * the {@code EnumMap} from which this {@code EnumMap} is initialized. - * @since Android 1.0 + * @throws NullPointerException + * if {@code map} is {@code null}. */ public EnumMap(EnumMap<K, ? extends V> map) { initialization(map); @@ -402,16 +413,18 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Constructs an {@code EnumMap} initialized from the given map. If the given map * is an {@code EnumMap} instance, this constructor behaves in the exactly the same - * way as {@link EnumMap#EnumMap(EnumMap)}}. Otherwise, the given map + * way as {@link EnumMap#EnumMap(EnumMap)}}. Otherwise, the given map * should contain at least one mapping. - * + * * @param map * the map from which this {@code EnumMap} is initialized. * @throws IllegalArgumentException * if {@code map} is not an {@code EnumMap} instance and does not contain * any mappings. - * @since Android 1.0 + * @throws NullPointerException + * if {@code map} is {@code null}. */ + @SuppressWarnings("unchecked") public EnumMap(Map<K, ? extends V> map) { if (map instanceof EnumMap) { initialization((EnumMap<K, V>) map); @@ -433,10 +446,9 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Removes all elements from this {@code EnumMap}, leaving it empty. - * + * * @see #isEmpty() * @see #size() - * @since Android 1.0 */ @Override public void clear() { @@ -447,10 +459,10 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Returns a shallow copy of this {@code EnumMap}. - * + * * @return a shallow copy of this {@code EnumMap}. - * @since Android 1.0 */ + @SuppressWarnings("unchecked") @Override public EnumMap<K, V> clone() { try { @@ -464,12 +476,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Returns whether this {@code EnumMap} contains the specified key. - * + * * @param key * the key to search for. * @return {@code true} if this {@code EnumMap} contains the specified key, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsKey(Object key) { @@ -482,12 +493,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Returns whether this {@code EnumMap} contains the specified value. - * + * * @param value * the value to search for. * @return {@code true} if this {@code EnumMap} contains the specified value, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsValue(Object value) { @@ -511,9 +521,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements * Returns a {@code Set} containing all of the mappings in this {@code EnumMap}. Each mapping is * an instance of {@link Map.Entry}. As the {@code Set} is backed by this {@code EnumMap}, * changes in one will be reflected in the other. - * + * <p> + * The order of the entries in the set will be the order that the enum keys + * were declared in. + * * @return a {@code Set} of the mappings. - * @since Android 1.0 */ @Override public Set<Map.Entry<K, V>> entrySet() { @@ -526,15 +538,15 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Compares the argument to the receiver, and returns {@code true} if the * specified {@code Object} is an {@code EnumMap} and both {@code EnumMap}s contain the same mappings. - * + * * @param object * the {@code Object} to compare with this {@code EnumMap}. * @return boolean {@code true} if {@code object} is the same as this {@code EnumMap}, * {@code false} otherwise. * @see #hashCode() * @see #entrySet() - * @since Android 1.0 */ + @SuppressWarnings("unchecked") @Override public boolean equals(Object object) { if (this == object) { @@ -553,12 +565,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Returns the value of the mapping with the specified key. - * + * * @param key * the key. * @return the value of the mapping with the specified key, or {@code null} * if no mapping for the specified key is found. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -574,9 +585,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements * Returns a set of the keys contained in this {@code EnumMap}. The {@code Set} is backed by * this {@code EnumMap} so changes to one are reflected in the other. The {@code Set} does not * support adding. - * + * <p> + * The order of the set will be the order that the enum keys were declared + * in. + * * @return a {@code Set} of the keys. - * @since Android 1.0 */ @Override public Set<K> keySet() { @@ -588,7 +601,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Maps the specified key to the specified value. - * + * * @param key * the key. * @param value @@ -605,7 +618,6 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements * @throws NullPointerException * if the key or value is {@code null} and this {@code EnumMap} does not * support {@code null} keys or values. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -615,7 +627,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Copies every mapping in the specified {@code Map} to this {@code EnumMap}. - * + * * @param map * the {@code Map} to copy mappings from. * @throws UnsupportedOperationException @@ -628,7 +640,6 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements * @throws NullPointerException * if a key or value is {@code null} and this {@code EnumMap} does not * support {@code null} keys or values. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -638,14 +649,13 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Removes a mapping with the specified key from this {@code EnumMap}. - * + * * @param key * the key of the mapping to remove. * @return the value of the removed mapping or {@code null} if no mapping * for the specified key was found. * @throws UnsupportedOperationException * if removing from this {@code EnumMap} is not supported. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -665,9 +675,8 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements /** * Returns the number of elements in this {@code EnumMap}. - * + * * @return the number of elements in this {@code EnumMap}. - * @since Android 1.0 */ @Override public int size() { @@ -680,9 +689,11 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements * {@link Map#values()}. The {@code Collection}'s {@code Iterator} will return the values * in the their corresponding keys' natural order (the {@code Enum} constants are * declared in this order). - * + * <p> + * The order of the values in the collection will be the order that their + * corresponding enum keys were declared in. + * * @return a collection of the values contained in this {@code EnumMap}. - * @since Android 1.0 */ @Override public Collection<V> values() { @@ -692,6 +703,7 @@ public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements return valuesCollection; } + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); diff --git a/luni/src/main/java/java/util/EnumSet.java b/luni/src/main/java/java/util/EnumSet.java index 4e44f2e..d49d900 100644 --- a/luni/src/main/java/java/util/EnumSet.java +++ b/luni/src/main/java/java/util/EnumSet.java @@ -23,8 +23,6 @@ import java.io.Serializable; /** * An EnumSet is a specialized Set to be used with enums as keys. - * - * @since Android 1.0 */ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, Serializable { @@ -37,7 +35,7 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> static /*package*/ LangAccess LANG_BOOTSTRAP = null; // END android-added - private static final long serialVersionUID = 4782406773684236311L; + private static final long serialVersionUID = 1009687484059888093L; final Class<E> elementClass; @@ -48,14 +46,13 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> /** * Creates an empty enum set. The permitted elements are of type * Class<E>. - * + * * @param elementType * the class object for the elements contained. * @return an empty enum set, with permitted elements of type {@code * elementType}. * @throws ClassCastException * if the specified element type is not and enum type. - * @since Android 1.0 */ public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { if (!elementType.isEnum()) { @@ -73,13 +70,12 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> /** * Creates an enum set filled with all the enum elements of the specified * {@code elementType}. - * + * * @param elementType * the class object for the elements contained. * @return an enum set with elements solely from the specified element type. * @throws ClassCastException * if the specified element type is not and enum type. - * @since Android 1.0 */ public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) { EnumSet<E> set = noneOf(elementType); @@ -91,13 +87,12 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> * Creates an enum set. All the contained elements are of type * Class<E>, and the contained elements are the same as those * contained in {@code s}. - * + * * @param s * the enum set from which to copy. * @return an enum set with all the elements from the specified enum set. * @throws ClassCastException * if the specified element type is not and enum type. - * @since Android 1.0 */ public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) { EnumSet<E> set = EnumSet.noneOf(s.elementClass); @@ -109,14 +104,15 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> * Creates an enum set. The contained elements are the same as those * contained in collection {@code c}. If c is an enum set, invoking this * method is the same as invoking {@link #copyOf(EnumSet)}. - * + * * @param c * the collection from which to copy. if it is not an enum set, * it must not be empty. * @return an enum set with all the elements from the specified collection. * @throws IllegalArgumentException * if c is not an enum set and contains no elements at all. - * @since Android 1.0 + * @throws NullPointerException + * if {@code c} is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) { if (c instanceof EnumSet) { @@ -138,12 +134,13 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> /** * Creates an enum set. All the contained elements complement those from the * specified enum set. - * + * * @param s * the specified enum set. * @return an enum set with all the elements complementary to those from the * specified enum set. - * @since Android 1.0 + * @throws NullPointerException + * if {@code s} is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) { EnumSet<E> set = EnumSet.noneOf(s.elementClass); @@ -159,11 +156,12 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. - * + * * @param e * the element to be initially contained. * @return an enum set containing the specified element. - * @since Android 1.0 + * @throws NullPointerException + * if {@code e} is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e) { EnumSet<E> set = EnumSet.noneOf(e.getDeclaringClass()); @@ -172,17 +170,18 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> } /** - * Creates a new enum set, containing only the specified element. There are + * Creates a new enum set, containing only the specified elements. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. - * + * * @param e1 * the initially contained element. * @param e2 * another initially contained element. - * @return an enum set containing the specified element. - * @since Android 1.0 + * @return an enum set containing the specified elements. + * @throws NullPointerException + * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) { EnumSet<E> set = of(e1); @@ -191,19 +190,20 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> } /** - * Creates a new enum set, containing only the specified element. There are + * Creates a new enum set, containing only the specified elements. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. - * + * * @param e1 * the initially contained element. * @param e2 * another initially contained element. * @param e3 * another initially contained element. - * @return an enum set containing the specified element. - * @since Android 1.0 + * @return an enum set containing the specified elements. + * @throws NullPointerException + * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) { EnumSet<E> set = of(e1, e2); @@ -212,11 +212,11 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> } /** - * Creates a new enum set, containing only the specified element. There are + * Creates a new enum set, containing only the specified elements. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. - * + * * @param e1 * the initially contained element. * @param e2 @@ -225,8 +225,9 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> * another initially contained element. * @param e4 * another initially contained element. - * @return an enum set containing the specified element. - * @since Android 1.0 + * @return an enum set containing the specified elements. + * @throws NullPointerException + * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) { EnumSet<E> set = of(e1, e2, e3); @@ -235,11 +236,11 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> } /** - * Creates a new enum set, containing only the specified element. There are + * Creates a new enum set, containing only the specified elements. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. - * + * * @param e1 * the initially contained element. * @param e2 @@ -250,8 +251,9 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> * another initially contained element. * @param e5 * another initially contained element. - * @return an enum set containing the specified element. - * @since Android 1.0 + * @return an enum set containing the specified elements. + * @throws NullPointerException + * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5) { EnumSet<E> set = of(e1, e2, e3, e4); @@ -263,13 +265,14 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> * Creates a new enum set, containing only the specified elements. It can * receive an arbitrary number of elements, and runs slower than those only * receiving a fixed number of elements. - * + * * @param start * the first initially contained element. * @param others * the other initially contained elements. * @return an enum set containing the specified elements. - * @since Android 1.0 + * @throws NullPointerException + * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) { EnumSet<E> set = of(start); @@ -283,15 +286,16 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> * Creates an enum set containing all the elements within the range defined * by {@code start} and {@code end} (inclusive). All the elements must be in * order. - * + * * @param start * the element used to define the beginning of the range. * @param end * the element used to define the end of the range. * @return an enum set with elements in the range from start to end. + * @throws NullPointerException + * if any one of {@code start} or {@code end} is {@code null}. * @throws IllegalArgumentException * if {@code start} is behind {@code end}. - * @since Android 1.0 */ public static <E extends Enum<E>> EnumSet<E> range(E start, E end) { if (start.compareTo(end) > 0) { @@ -307,10 +311,9 @@ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> /** * Creates a new enum set with the same elements as those contained in this * enum set. - * + * * @return a new enum set with the same elements as those contained in this * enum set. - * @since Android 1.0 */ @SuppressWarnings("unchecked") @Override diff --git a/luni/src/main/java/java/util/Enumeration.java b/luni/src/main/java/java/util/Enumeration.java index d60bdd2..8b8f7bd 100644 --- a/luni/src/main/java/java/util/Enumeration.java +++ b/luni/src/main/java/java/util/Enumeration.java @@ -17,18 +17,16 @@ package java.util; - /** * An Enumeration is used to sequence over a collection of objects. * <p> - * Preferably an Iterator should be used. Iterator replaces the Enumeration - * interface and adds a way to remove elements from a collection. - * </p> - * + * Preferably an {@link Iterator} should be used. {@code Iterator} replaces the + * enumeration interface and adds a way to remove elements from a collection. + * * @see Hashtable * @see Properties * @see Vector - * @since Android 1.0 + * @version 1.0 */ public interface Enumeration<E> { @@ -37,7 +35,6 @@ public interface Enumeration<E> { * * @return {@code true} if there are more elements, {@code false} otherwise. * @see #nextElement - * @since Android 1.0 */ public boolean hasMoreElements(); @@ -48,7 +45,6 @@ public interface Enumeration<E> { * @throws NoSuchElementException * if there are no more elements. * @see #hasMoreElements - * @since Android 1.0 */ public E nextElement(); } diff --git a/luni/src/main/java/java/util/EventListener.java b/luni/src/main/java/java/util/EventListener.java index 9ff4876..b100f0c 100644 --- a/luni/src/main/java/java/util/EventListener.java +++ b/luni/src/main/java/java/util/EventListener.java @@ -17,13 +17,11 @@ package java.util; - /** * EventListener is the superclass of all event listener interfaces. - * + * * @see EventObject - * @since Android 1.0 */ public interface EventListener { - /*empty*/ + /* empty */ } diff --git a/luni/src/main/java/java/util/EventListenerProxy.java b/luni/src/main/java/java/util/EventListenerProxy.java index a165385..1e023f6 100644 --- a/luni/src/main/java/java/util/EventListenerProxy.java +++ b/luni/src/main/java/java/util/EventListenerProxy.java @@ -20,8 +20,6 @@ package java.util; /** * This abstract class provides a simple wrapper for objects of type {@code EventListener}. - * - * @since Android 1.0 */ public abstract class EventListenerProxy implements EventListener { @@ -32,7 +30,6 @@ public abstract class EventListenerProxy implements EventListener { * * @param listener * the listener wrapped by this proxy. - * @since Android 1.0 */ public EventListenerProxy(EventListener listener) { super(); @@ -43,7 +40,6 @@ public abstract class EventListenerProxy implements EventListener { * Returns the wrapped {@code EventListener}. * * @return the wrapped {@code EventListener}. - * @since Android 1.0 */ public EventListener getListener() { return listener; diff --git a/luni/src/main/java/java/util/EventObject.java b/luni/src/main/java/java/util/EventObject.java index 61e530a..76da7e2 100644 --- a/luni/src/main/java/java/util/EventObject.java +++ b/luni/src/main/java/java/util/EventObject.java @@ -25,8 +25,6 @@ import java.io.Serializable; * add event specific information. * * @see EventListener - * - * @since Android 1.0 */ public class EventObject implements Serializable { @@ -34,8 +32,6 @@ public class EventObject implements Serializable { /** * The event source. - * - * @since Android 1.0 */ protected transient Object source; @@ -44,7 +40,6 @@ public class EventObject implements Serializable { * * @param source * the object which fired the event. - * @since Android 1.0 */ public EventObject(Object source) { if (source != null) { @@ -58,7 +53,6 @@ public class EventObject implements Serializable { * Returns the event source. * * @return the object which fired the event. - * @since Android 1.0 */ public Object getSource() { return source; @@ -68,7 +62,6 @@ public class EventObject implements Serializable { * Returns the string representation of this {@code EventObject}. * * @return the string representation of this {@code EventObject}. - * @since Android 1.0 */ @Override public String toString() { diff --git a/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java b/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java index aa0c967..e4f39d2 100644 --- a/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java +++ b/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java @@ -23,7 +23,6 @@ import java.io.Serializable; * conversion and the flags are incompatible. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class FormatFlagsConversionMismatchException extends IllegalFormatException implements Serializable { diff --git a/luni/src/main/java/java/util/Formattable.java b/luni/src/main/java/java/util/Formattable.java index 2564c04..15b66b5 100644 --- a/luni/src/main/java/java/util/Formattable.java +++ b/luni/src/main/java/java/util/Formattable.java @@ -20,16 +20,15 @@ package java.util; * Classes that handle custom formatting for the 's' specifier of {@code Formatter} * should implement the {@code Formattable} interface. It gives basic control over * formatting objects. - * + * * @see Formatter - * @since Android 1.0 */ public interface Formattable { /** * Formats the object using the specified {@code Formatter}. - * + * * @param formatter * the {@code Formatter} to use. * @param flags @@ -54,7 +53,6 @@ public interface Formattable { * is -1, then maximum length is not enforced. * @throws IllegalFormatException * if any of the parameters is not supported. - * @since Android 1.0 */ void formatTo(Formatter formatter, int flags, int width, int precision) throws IllegalFormatException; diff --git a/luni/src/main/java/java/util/FormattableFlags.java b/luni/src/main/java/java/util/FormattableFlags.java index b5078e4..b8d44d4 100644 --- a/luni/src/main/java/java/util/FormattableFlags.java +++ b/luni/src/main/java/java/util/FormattableFlags.java @@ -22,7 +22,6 @@ package java.util; * flags must be done by the implementations. * * @see Formattable - * @since Android 1.0 */ public class FormattableFlags { @@ -37,8 +36,6 @@ public class FormattableFlags { * right-justified. * * The flag corresponds to '-' ('\u002d') in the format specifier. - * - * @since Android 1.0 */ public static final int LEFT_JUSTIFY = 1; @@ -48,8 +45,6 @@ public class FormattableFlags { * effect as {@code String.toUpperCase(java.util.Locale)}. * * This flag corresponds to {@code '^' ('\u005e')} in the format specifier. - * - * @since Android 1.0 */ public static final int UPPERCASE = 2; @@ -58,8 +53,6 @@ public class FormattableFlags { * of the alternate form is determined by the {@code Formattable}. * * This flag corresponds to {@code '#' ('\u0023')} in the format specifier. - * - * @since Android 1.0 */ public static final int ALTERNATE = 4; } diff --git a/luni/src/main/java/java/util/Formatter.java b/luni/src/main/java/java/util/Formatter.java index a6f14f0..d1dd417 100644 --- a/luni/src/main/java/java/util/Formatter.java +++ b/luni/src/main/java/java/util/Formatter.java @@ -28,6 +28,7 @@ import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; +import java.math.MathContext; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.security.AccessController; @@ -37,63 +38,59 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; -// BEGIN android-note -// Added quite extensive class documentation. Almost none was present before. -// END android-note - /** * <p>The {@code Formatter} class is a String-formatting utility that is designed - * to work like the {@code printf} function of the C programming language. + * to work like the {@code printf} function of the C programming language. * Its key methods are the {@code format} methods which create a formatted - * {@code String} by replacing a set of placeholders (format tokens) with formatted + * {@code String} by replacing a set of placeholders (format tokens) with formatted * values. The style used to format each value is determined by the format * token used. For example, the call<br/> * {@code format("My decimal value is %d and my String is %s.", 3, "Hello");}<br/> * returns the {@code String}<br/> - * {@code My decimal value is 3 and my String is Hello.}</p> - * - *<p>The format token consists of a percent sign, optionally followed - * by flags and precision arguments, and then a single character that + * {@code My decimal value is 3 and my String is Hello.} + * + * <p>The format token consists of a percent sign, optionally followed + * by flags and precision arguments, and then a single character that * indicates the type of value * being formatted. If the type is a time/date, then the type character - * {@code t} is followed by an additional character that indicates how the - * date is to be formatted. The two characters {@code <$} immediately + * {@code t} is followed by an additional character that indicates how the + * date is to be formatted. The two characters {@code <$} immediately * following the % sign indicate that the previous value should be used again * instead of moving on to the next value argument. A number {@code n} * and a dollar sign immediately following the % sign make n the next argument - * to be used.</p> - * - * <p>The available choices are the following:</p> - * + * to be used. + * + * <p>The available choices are the following: + * * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY=""> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> * <B>Text value types</B></TD> * </tr> * <tr> - * <td width="5%">{@code s}</td> - * <td width="10%">String</td> - * <td width="30%">{@code format("%s, %s", "hello", "Hello");}</td> - * <td width="30%">{@code hello, Hello}</td> - * </tr> + * <td width="5%">{@code s}</td> + * <td width="10%">String</td> + * <td width="30%">{@code format("%s, %s", "hello", "Hello");}</td> + * <td width="30%">{@code hello, Hello}</td> + * </tr> * <tr> - * <td width="5%">{@code S}, {@code s}</td> - * <td width="10%">String to capitals</td> - * <td width="30%">{@code format("%S, %S", "hello", "Hello");}</td> - * <td width="30%">{@code HELLO, HELLO}</td> - * </tr> + * <td width="5%">{@code S}, {@code s}</td> + * <td width="10%">String to capitals</td> + * <td width="30%">{@code format("%S, %S", "hello", "Hello");}</td> + * <td width="30%">{@code HELLO, HELLO}</td> + * </tr> * <tr> - * <td width="5%">{@code c}</td> - * <td width="10%">Character</td> - * <td width="30%">{@code format("%c, %c", 'd', 0x65);}</td> + * <td width="5%">{@code c}</td> + * <td width="10%">Character</td> + * <td width="30%">{@code format("%c, %c", 'd', 0x65);}</td> * <td width="30%">{@code d, e}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code C}</td> - * <td width="10%">Character to capitals</td> - * <td width="30%">{@code format("%C, %C", 'd', 0x65);}</td> + * <td width="5%">{@code C}</td> + * <td width="10%">Character to capitals</td> + * <td width="30%">{@code format("%C, %C", 'd', 0x65);}</td> * <td width="30%">{@code D, E}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> * <B>Text option flags</B><br/>The value between the @@ -101,33 +98,33 @@ import java.text.NumberFormat; * characters of the formatted value </TD> * </tr> * <tr> - * <td width="5%">{@code -}</td> - * <td width="10%">Left justify (width value is required)</td> - * <td width="30%">{@code format("%-3C, %3C", 'd', 0x65);}</td> + * <td width="5%">{@code -}</td> + * <td width="10%">Left justify (width value is required)</td> + * <td width="30%">{@code format("%-3C, %3C", 'd', 0x65);}</td> * <td width="30%">{@code D , E}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> * <B>Integer types</B></TD> * </tr> * <tr> - * <td width="5%">{@code d}</td> - * <td width="10%">int, formatted as decimal</td> - * <td width="30%">{@code format("%d, %d"1$, 35, 0x10);}</td> + * <td width="5%">{@code d}</td> + * <td width="10%">int, formatted as decimal</td> + * <td width="30%">{@code format("%d, %d"1$, 35, 0x10);}</td> * <td width="30%">{@code 35, 16}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code o}</td> - * <td width="10%">int, formatted as octal</td> - * <td width="30%">{@code format("%o, %o", 8, 010);}</td> + * <td width="5%">{@code o}</td> + * <td width="10%">int, formatted as octal</td> + * <td width="30%">{@code format("%o, %o", 8, 010);}</td> * <td width="30%">{@code 10, 10}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code X}, {@code x}</td> - * <td width="10%">int, formatted as hexidecimal</td> - * <td width="30%">{@code format("%x, %X", 10, 10);}</td> + * <td width="5%">{@code X}, {@code x}</td> + * <td width="10%">int, formatted as hexidecimal</td> + * <td width="30%">{@code format("%x, %X", 10, 10);}</td> * <td width="30%">{@code a, A}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> * <B>Integer option flags</B><br/>The value between the @@ -135,43 +132,43 @@ import java.text.NumberFormat; * characters of the formatted value </TD> * </tr> * <tr> - * <td width="5%">{@code +}</td> - * <td width="10%">lead with the number's sign</td> - * <td width="30%">{@code format("%+d, %+4d", 5, 5);}</td> + * <td width="5%">{@code +}</td> + * <td width="10%">lead with the number's sign</td> + * <td width="30%">{@code format("%+d, %+4d", 5, 5);}</td> * <td width="30%">{@code +5, +5}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code -}</td> - * <td width="10%">Left justify (width value is required)</td> - * <td width="30%">{@code format("%-6dx", 5);}</td> + * <td width="5%">{@code -}</td> + * <td width="10%">Left justify (width value is required)</td> + * <td width="30%">{@code format("%-6dx", 5);}</td> * <td width="30%">{@code 5 x}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code #}</td> - * <td width="10%">Print the leading characters that indicate - * hexidecimal or octal (for use only with hex and octal types) </td> - * <td width="30%">{@code format("%#o", 010);}</td> + * <td width="5%">{@code #}</td> + * <td width="10%">Print the leading characters that indicate + * hexidecimal or octal (for use only with hex and octal types) </td> + * <td width="30%">{@code format("%#o", 010);}</td> * <td width="30%">{@code 010}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code }</td> - * <td width="10%">A space indicates that non-negative numbers - * should have a leading space. </td> - * <td width="30%">{@code format("x% d% 5d", 4, 4);}</td> + * <td width="5%">{@code }</td> + * <td width="10%">A space indicates that non-negative numbers + * should have a leading space. </td> + * <td width="30%">{@code format("x% d% 5d", 4, 4);}</td> * <td width="30%">{@code x 4 4}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code 0}</td> - * <td width="10%">Pad the number with leading zeros (width value is required)</td> - * <td width="30%">{@code format("%07d, %03d", 4, 5555);}</td> + * <td width="5%">{@code 0}</td> + * <td width="10%">Pad the number with leading zeros (width value is required)</td> + * <td width="30%">{@code format("%07d, %03d", 4, 5555);}</td> * <td width="30%">{@code 0000004, 5555}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code (}</td> - * <td width="10%">Put parentheses around negative numbers (decimal only)</td> - * <td width="30%">{@code format("%(d, %(d, %(6d", 12, -12, -12);}</td> + * <td width="5%">{@code (}</td> + * <td width="10%">Put parentheses around negative numbers (decimal only)</td> + * <td width="30%">{@code format("%(d, %(d, %(6d", 12, -12, -12);}</td> * <td width="30%">{@code 12, (12), (12)}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> * <B>Float types</B><br/>A value immediately following the % symbol @@ -180,229 +177,223 @@ import java.text.NumberFormat; * gives the precision (6 by default).</TD> * </tr> * <tr> - * <td width="5%">{@code f}</td> - * <td width="10%">float (or double) formatted as a decimal, where - * the precision indicates the number of digits after the decimal.</td> - * <td width="30%">{@code format("%f %<.1f %<1.5f %<10f %<6.0f", 123.456f);}</td> + * <td width="5%">{@code f}</td> + * <td width="10%">float (or double) formatted as a decimal, where + * the precision indicates the number of digits after the decimal.</td> + * <td width="30%">{@code format("%f %<.1f %<1.5f %<10f %<6.0f", 123.456f);}</td> * <td width="30%">{@code 123.456001 123.5 123.45600 123.456001 123}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code E}, {@code e}</td> + * <td width="5%">{@code E}, {@code e}</td> * <td width="10%">float (or double) formatted in decimal exponential - * notation, where the precision indicates the number of significant digits.</td> - * <td width="30%">{@code format("%E %<.1e %<1.5E %<10E %<6.0E", 123.456f);}</td> + * notation, where the precision indicates the number of significant digits.</td> + * <td width="30%">{@code format("%E %<.1e %<1.5E %<10E %<6.0E", 123.456f);}</td> * <td width="30%">{@code 1.234560E+02 1.2e+02 1.23456E+02 1.234560E+02 1E+02}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code G}, {@code g}</td> + * <td width="5%">{@code G}, {@code g}</td> * <td width="10%">float (or double) formatted in decimal exponential - * notation , where the precision indicates the maximum number of significant digits.</td> - * <td width="30%">{@code format("%G %<.1g %<1.5G %<10G %<6.0G", 123.456f);}</td> + * notation , where the precision indicates the maximum number of significant digits.</td> + * <td width="30%">{@code format("%G %<.1g %<1.5G %<10G %<6.0G", 123.456f);}</td> * <td width="30%">{@code 123.456 1e+02 123.46 123.456 1E+02}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code A}, {@code a}</td> + * <td width="5%">{@code A}, {@code a}</td> * <td width="10%">float (or double) formatted as a hexidecimal in exponential - * notation, where the precision indicates the number of significant digits.</td> - * <td width="30%">{@code format("%A %<.1a %<1.5A %<10A %<6.0A", 123.456f);}</td> + * notation, where the precision indicates the number of significant digits.</td> + * <td width="30%">{@code format("%A %<.1a %<1.5A %<10A %<6.0A", 123.456f);}</td> * <td width="30%">{@code 0X1.EDD2F2P6 0x1.fp6 0X1.EDD2FP6 0X1.EDD2F2P6 0X1.FP6}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> - * <B>Float-type option flags</B><br/>See the Integer-type options. + * <B>Float-type option flags</B><br/>See the Integer-type options. * The options for float-types are the * same as for integer types with one addition: </TD> * </tr> * <tr> - * <td width="5%">{@code ,}</td> + * <td width="5%">{@code ,}</td> * <td width="10%">Use a comma in place of a decimal if the locale - * requires it. </td> - * <td width="30%">{@code format(new Locale("fr"), "%,7.2f", 6.03f);}</td> + * requires it. </td> + * <td width="30%">{@code format(new Locale("fr"), "%,7.2f", 6.03f);}</td> * <td width="30%">{@code 6,03}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> * <B>Date types</B></TD> * </tr> * <tr> - * <td width="5%">{@code t}, {@code T}</td> - * <td width="10%">Date</td> - * <td width="30%">{@code format(new Locale("fr"), "%tB %TB", Calendar.getInstance(), Calendar.getInstance());}</td> + * <td width="5%">{@code t}, {@code T}</td> + * <td width="10%">Date</td> + * <td width="30%">{@code format(new Locale("fr"), "%tB %TB", Calendar.getInstance(), Calendar.getInstance());}</td> * <td width="30%">{@code avril AVRIL}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> - * <B>Date format precisions</B><br/>The format precision character + * <B>Date format precisions</B><br/>The format precision character * follows the {@code t}. </TD> * </tr> * <tr> - * <td width="5%">{@code A}, {@code a}</td> - * <td width="10%">The day of the week</td> - * <td width="30%">{@code format("%ta %tA", cal, cal);}</td> + * <td width="5%">{@code A}, {@code a}</td> + * <td width="10%">The day of the week</td> + * <td width="30%">{@code format("%ta %tA", cal, cal);}</td> * <td width="30%">{@code Tue Tuesday}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code b}, {@code B}, {@code h}</td> - * <td width="10%">The name of the month</td> - * <td width="30%">{@code format("%tb %<tB %<th", cal, cal, cal);}</td> + * <td width="5%">{@code b}, {@code B}, {@code h}</td> + * <td width="10%">The name of the month</td> + * <td width="30%">{@code format("%tb %<tB %<th", cal, cal, cal);}</td> * <td width="30%">{@code Apr April Apr}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code C}</td> - * <td width="10%">The century</td> - * <td width="30%">{@code format("%tC\n", cal);}</td> + * <td width="5%">{@code C}</td> + * <td width="10%">The century</td> + * <td width="30%">{@code format("%tC\n", cal);}</td> * <td width="30%">{@code 20}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code d}, {@code e}</td> - * <td width="10%">The day of the month (with or without leading zeros)</td> - * <td width="30%">{@code format("%td %te", cal, cal);}</td> + * <td width="5%">{@code d}, {@code e}</td> + * <td width="10%">The day of the month (with or without leading zeros)</td> + * <td width="30%">{@code format("%td %te", cal, cal);}</td> * <td width="30%">{@code 01 1}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code F}</td> - * <td width="10%">The complete date formatted as YYYY-MM-DD</td> - * <td width="30%">{@code format("%tF", cal);}</td> + * <td width="5%">{@code F}</td> + * <td width="10%">The complete date formatted as YYYY-MM-DD</td> + * <td width="30%">{@code format("%tF", cal);}</td> * <td width="30%">{@code 2008-04-01}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code D}</td> - * <td width="10%">The complete date formatted as MM/DD/YY - * (not corrected for locale) </td> - * <td width="30%">{@code format(new Locale("en_US"), "%tD", cal);<br/>format(new Locale("en_UK"), " %tD", cal);}</td> + * <td width="5%">{@code D}</td> + * <td width="10%">The complete date formatted as MM/DD/YY + * (not corrected for locale) </td> + * <td width="30%">{@code format(new Locale("en_US"), "%tD", cal);<br/>format(new Locale("en_UK"), " %tD", cal);}</td> * <td width="30%">{@code 04/01/08 04/01/08}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code j}</td> - * <td width="10%">The number of the day (from the beginning of the year).</td> - * <td width="30%">{@code format("%tj\n", cal);}</td> + * <td width="5%">{@code j}</td> + * <td width="10%">The number of the day (from the beginning of the year).</td> + * <td width="30%">{@code format("%tj\n", cal);}</td> * <td width="30%">{@code 092}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code m}</td> - * <td width="10%">The number of the month</td> - * <td width="30%">{@code format("%tm\n", cal);}</td> + * <td width="5%">{@code m}</td> + * <td width="10%">The number of the month</td> + * <td width="30%">{@code format("%tm\n", cal);}</td> * <td width="30%">{@code 04}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code y}, {@code Y}</td> - * <td width="10%">The year</td> - * <td width="30%">{@code format("%ty %tY", cal, cal);}</td> + * <td width="5%">{@code y}, {@code Y}</td> + * <td width="10%">The year</td> + * <td width="30%">{@code format("%ty %tY", cal, cal);}</td> * <td width="30%">{@code 08 2008}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code H}, {@code I}, {@code k}, {@code l}</td> + * <td width="5%">{@code H}, {@code I}, {@code k}, {@code l}</td> * <td width="10%">The hour of the day, in 12 or 24 hour format, with or - * without a leading zero</td> - * <td width="30%">{@code format("%tH %tI %tk %tl", cal, cal, cal, cal);}</td> + * without a leading zero</td> + * <td width="30%">{@code format("%tH %tI %tk %tl", cal, cal, cal, cal);}</td> * <td width="30%">{@code 16 04 16 4}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code p}</td> - * <td width="10%">a.m. or p.m.</td> - * <td width="30%">{@code format("%tp %Tp", cal, cal);}</td> + * <td width="5%">{@code p}</td> + * <td width="10%">a.m. or p.m.</td> + * <td width="30%">{@code format("%tp %Tp", cal, cal);}</td> * <td width="30%">{@code pm PM}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code M}, {@code S}, {@code L}, {@code N}</td> - * <td width="10%">The minutes, seconds, milliseconds, and nanoseconds</td> - * <td width="30%">{@code format("%tM %tS %tL %tN", cal, cal, cal, cal);}</td> + * <td width="5%">{@code M}, {@code S}, {@code L}, {@code N}</td> + * <td width="10%">The minutes, seconds, milliseconds, and nanoseconds</td> + * <td width="30%">{@code format("%tM %tS %tL %tN", cal, cal, cal, cal);}</td> * <td width="30%">{@code 08 17 359 359000000}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code Z}, {@code z}</td> - * <td width="10%">The time zone: its abbreviation or offset from GMT</td> - * <td width="30%">{@code format("%tZ %tz", cal, cal);}</td> + * <td width="5%">{@code Z}, {@code z}</td> + * <td width="10%">The time zone: its abbreviation or offset from GMT</td> + * <td width="30%">{@code format("%tZ %tz", cal, cal);}</td> * <td width="30%">{@code CEST +0100}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code R}, {@code r}, {@code T}</td> - * <td width="10%">The complete time</td> - * <td width="30%">{@code format("%tR %tr %tT", cal, cal, cal);}</td> + * <td width="5%">{@code R}, {@code r}, {@code T}</td> + * <td width="10%">The complete time</td> + * <td width="30%">{@code format("%tR %tr %tT", cal, cal, cal);}</td> * <td width="30%">{@code 16:15 04:15:32 PM 16:15:32}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code s}, {@code Q}</td> + * <td width="5%">{@code s}, {@code Q}</td> * <td width="10%">The number of seconds or milliseconds from "the epoch" - * (1 January 1970 00:00:00 UTC) </td> - * <td width="30%">{@code format("%ts %tQ", cal, cal);}</td> + * (1 January 1970 00:00:00 UTC) </td> + * <td width="30%">{@code format("%ts %tQ", cal, cal);}</td> * <td width="30%">{@code 1207059412 1207059412656}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code c}</td> - * <td width="10%">The complete time and date</td> - * <td width="30%">{@code format("%tc", cal);}</td> + * <td width="5%">{@code c}</td> + * <td width="10%">The complete time and date</td> + * <td width="30%">{@code format("%tc", cal);}</td> * <td width="30%">{@code Tue Apr 01 16:19:17 CEST 2008}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> * <B>Other data types</B></TD> * </tr> * <tr> - * <td width="5%">{@code B}, {@code b}</td> - * <td width="10%">Boolean</td> - * <td width="30%">{@code format("%b, %B", true, false);}</td> + * <td width="5%">{@code B}, {@code b}</td> + * <td width="10%">Boolean</td> + * <td width="30%">{@code format("%b, %B", true, false);}</td> * <td width="30%">{@code true, FALSE}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code H}, {@code h}</td> - * <td width="10%">Hashcode</td> - * <td width="30%">{@code format("%h, %H", obj, obj);}</td> + * <td width="5%">{@code H}, {@code h}</td> + * <td width="10%">Hashcode</td> + * <td width="30%">{@code format("%h, %H", obj, obj);}</td> * <td width="30%">{@code 190d11, 190D11}</td> - * </tr> + * </tr> * <tr> - * <td width="5%">{@code n}</td> - * <td width="10%">line separator</td> - * <td width="30%">{@code format("first%nsecond", "???");}</td> + * <td width="5%">{@code n}</td> + * <td width="10%">line separator</td> + * <td width="30%">{@code format("first%nsecond", "???");}</td> * <td width="30%">{@code first<br/>second}</td> - * </tr> + * </tr> * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"> * <TD COLSPAN=4> * <B>Escape sequences</B></TD> * </tr> * <tr> - * <td width="5%">{@code %}</td> - * <td width="10%">Escape the % character</td> - * <td width="30%">{@code format("%d%%, %d", 50, 60);}</td> + * <td width="5%">{@code %}</td> + * <td width="10%">Escape the % character</td> + * <td width="30%">{@code format("%d%%, %d", 50, 60);}</td> * <td width="30%">{@code 50%, 60}</td> - * </tr> - * </table> - * + * </tr> + * </table> + * * <p>An instance of Formatter can be created to write the formatted - * output to standard types of output streams. Its functionality can - * also be accessed through the format methods of an output stream + * output to standard types of output streams. Its functionality can + * also be accessed through the format methods of an output stream * or of {@code String}:<br/> * {@code System.out.println(String.format("%ty\n", cal));}<br/> - * {@code System.out.format("%ty\n", cal);}</p> - * - * <p>The class is not multi-threaded safe. The user is responsible for + * {@code System.out.format("%ty\n", cal);} + * + * <p>The class is not multi-threaded safe. The user is responsible for * maintaining a thread-safe design if a {@code Formatter} is - * accessed by multiple threads. </p> - * - * @since Android 1.0 + * accessed by multiple threads. + * + * @since 1.5 */ public final class Formatter implements Closeable, Flushable { - // BEGIN android-changed /** * The enumeration giving the available styles for formatting very large * decimal numbers. - * - * @since Android 1.0 - */ + */ public enum BigDecimalLayoutForm { /** * Use scientific style for BigDecimals. - * @since Android 1.0 */ - SCIENTIFIC, + SCIENTIFIC, /** * Use normal decimal/float style for BigDecimals. - * @since Android 1.0 */ DECIMAL_FLOAT } - // END android-changed private Appendable out; @@ -414,29 +405,26 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a {@code Formatter}. - * + * * The output is written to a {@code StringBuilder} which can be acquired by invoking * {@link #out()} and whose content can be obtained by calling * {@code toString()}. - * + * * The {@code Locale} for the {@code Formatter} is the default {@code Locale}. - * - * @since Android 1.0 */ public Formatter() { this(new StringBuilder(), Locale.getDefault()); } /** - * Constructs a {@code Formatter} whose output will be written to the + * Constructs a {@code Formatter} whose output will be written to the * specified {@code Appendable}. - * + * * The locale for the {@code Formatter} is the default {@code Locale}. - * + * * @param a * the output destination of the {@code Formatter}. If {@code a} is {@code null}, * then a {@code StringBuilder} will be used. - * @since Android 1.0 */ public Formatter(Appendable a) { this(a, Locale.getDefault()); @@ -444,32 +432,30 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a {@code Formatter} with the specified {@code Locale}. - * + * * The output is written to a {@code StringBuilder} which can be acquired by invoking * {@link #out()} and whose content can be obtained by calling * {@code toString()}. - * + * * @param l * the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null}, * then no localization will be used. - * @since Android 1.0 */ public Formatter(Locale l) { this(new StringBuilder(), l); } /** - * Constructs a {@code Formatter} with the specified {@code Locale} - * and whose output will be written to the + * Constructs a {@code Formatter} with the specified {@code Locale} + * and whose output will be written to the * specified {@code Appendable}. - * + * * @param a * the output destination of the {@code Formatter}. If {@code a} is {@code null}, * then a {@code StringBuilder} will be used. * @param l * the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null}, * then no localization will be used. - * @since Android 1.0 */ public Formatter(Appendable a, Locale l) { if (null == a) { @@ -482,17 +468,16 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a {@code Formatter} whose output is written to the specified file. - * + * * The charset of the {@code Formatter} is the default charset. - * + * * The {@code Locale} for the {@code Formatter} is the default {@code Locale}. - * + * * @param fileName * the filename of the file that is used as the output * destination for the {@code Formatter}. The file will be truncated to * zero size if the file exists, or else a new file will be * created. The output of the {@code Formatter} is buffered. - * * @throws FileNotFoundException * if the filename does not denote a normal and writable file, * or if a new file cannot be created, or if any error arises when @@ -500,7 +485,6 @@ public final class Formatter implements Closeable, Flushable { * @throws SecurityException * if there is a {@code SecurityManager} in place which denies permission * to write to the file in {@code checkWrite(file.getPath())}. - * @since Android 1.0 */ public Formatter(String fileName) throws FileNotFoundException { this(new File(fileName)); @@ -509,9 +493,9 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a {@code Formatter} whose output is written to the specified file. - * + * * The {@code Locale} for the {@code Formatter} is the default {@code Locale}. - * + * * @param fileName * the filename of the file that is used as the output * destination for the {@code Formatter}. The file will be truncated to @@ -519,7 +503,6 @@ public final class Formatter implements Closeable, Flushable { * created. The output of the {@code Formatter} is buffered. * @param csn * the name of the charset for the {@code Formatter}. - * * @throws FileNotFoundException * if the filename does not denote a normal and writable file, * or if a new file cannot be created, or if any error arises when @@ -529,7 +512,6 @@ public final class Formatter implements Closeable, Flushable { * to write to the file in {@code checkWrite(file.getPath())}. * @throws UnsupportedEncodingException * if the charset with the specified name is not supported. - * @since Android 1.0 */ public Formatter(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { @@ -537,9 +519,9 @@ public final class Formatter implements Closeable, Flushable { } /** - * Constructs a {@code Formatter} with the given {@code Locale} and charset, + * Constructs a {@code Formatter} with the given {@code Locale} and charset, * and whose output is written to the specified file. - * + * * @param fileName * the filename of the file that is used as the output * destination for the {@code Formatter}. The file will be truncated to @@ -550,7 +532,6 @@ public final class Formatter implements Closeable, Flushable { * @param l * the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null}, * then no localization will be used. - * * @throws FileNotFoundException * if the filename does not denote a normal and writable file, * or if a new file cannot be created, or if any error arises when @@ -560,7 +541,6 @@ public final class Formatter implements Closeable, Flushable { * to write to the file in {@code checkWrite(file.getPath())}. * @throws UnsupportedEncodingException * if the charset with the specified name is not supported. - * @since Android 1.0 */ public Formatter(String fileName, String csn, Locale l) throws FileNotFoundException, UnsupportedEncodingException { @@ -570,17 +550,16 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a {@code Formatter} whose output is written to the specified {@code File}. - * + * * The charset of the {@code Formatter} is the default charset. - * + * * The {@code Locale} for the {@code Formatter} is the default {@code Locale}. - * + * * @param file * the {@code File} that is used as the output destination for the * {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File} * exists, or else a new {@code File} will be created. The output of the * {@code Formatter} is buffered. - * * @throws FileNotFoundException * if the {@code File} is not a normal and writable {@code File}, or if a * new {@code File} cannot be created, or if any error rises when opening or @@ -588,18 +567,17 @@ public final class Formatter implements Closeable, Flushable { * @throws SecurityException * if there is a {@code SecurityManager} in place which denies permission * to write to the {@code File} in {@code checkWrite(file.getPath())}. - * @since Android 1.0 */ public Formatter(File file) throws FileNotFoundException { this(new FileOutputStream(file)); } /** - * Constructs a {@code Formatter} with the given charset, + * Constructs a {@code Formatter} with the given charset, * and whose output is written to the specified {@code File}. - * + * * The {@code Locale} for the {@code Formatter} is the default {@code Locale}. - * + * * @param file * the {@code File} that is used as the output destination for the * {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File} @@ -616,7 +594,6 @@ public final class Formatter implements Closeable, Flushable { * to write to the {@code File} in {@code checkWrite(file.getPath())}. * @throws UnsupportedEncodingException * if the charset with the specified name is not supported. - * @since Android 1.0 */ public Formatter(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { @@ -624,9 +601,9 @@ public final class Formatter implements Closeable, Flushable { } /** - * Constructs a {@code Formatter} with the given {@code Locale} and charset, + * Constructs a {@code Formatter} with the given {@code Locale} and charset, * and whose output is written to the specified {@code File}. - * + * * @param file * the {@code File} that is used as the output destination for the * {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File} @@ -646,7 +623,6 @@ public final class Formatter implements Closeable, Flushable { * to write to the {@code File} in {@code checkWrite(file.getPath())}. * @throws UnsupportedEncodingException * if the charset with the specified name is not supported. - * @since Android 1.0 */ public Formatter(File file, String csn, Locale l) throws FileNotFoundException, UnsupportedEncodingException { @@ -654,9 +630,9 @@ public final class Formatter implements Closeable, Flushable { try { fout = new FileOutputStream(file); OutputStreamWriter writer = new OutputStreamWriter(fout, csn); - // BEGIN android-modified + // BEGIN android-changed out = new BufferedWriter(writer, 8192); - // END android-modified + // END android-changed } catch (RuntimeException e) { closeOutputStream(fout); throw e; @@ -670,37 +646,35 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a {@code Formatter} whose output is written to the specified {@code OutputStream}. - * + * * The charset of the {@code Formatter} is the default charset. - * + * * The {@code Locale} for the {@code Formatter} is the default {@code Locale}. - * + * * @param os * the stream to be used as the destination of the {@code Formatter}. - * @since Android 1.0 */ public Formatter(OutputStream os) { OutputStreamWriter writer = new OutputStreamWriter(os, Charset .defaultCharset()); - // BEGIN android-modified + // BEGIN android-changed out = new BufferedWriter(writer, 8192); - // END android-modified + // END android-changed locale = Locale.getDefault(); } /** - * Constructs a {@code Formatter} with the given charset, + * Constructs a {@code Formatter} with the given charset, * and whose output is written to the specified {@code OutputStream}. - * + * * The {@code Locale} for the {@code Formatter} is the default {@code Locale}. - * + * * @param os * the stream to be used as the destination of the {@code Formatter}. * @param csn * the name of the charset for the {@code Formatter}. * @throws UnsupportedEncodingException * if the charset with the specified name is not supported. - * @since Android 1.0 */ public Formatter(OutputStream os, String csn) throws UnsupportedEncodingException { @@ -709,9 +683,9 @@ public final class Formatter implements Closeable, Flushable { } /** - * Constructs a {@code Formatter} with the given {@code Locale} and charset, + * Constructs a {@code Formatter} with the given {@code Locale} and charset, * and whose output is written to the specified {@code OutputStream}. - * + * * @param os * the stream to be used as the destination of the {@code Formatter}. * @param csn @@ -721,31 +695,29 @@ public final class Formatter implements Closeable, Flushable { * then no localization will be used. * @throws UnsupportedEncodingException * if the charset with the specified name is not supported. - * @since Android 1.0 */ public Formatter(OutputStream os, String csn, Locale l) throws UnsupportedEncodingException { OutputStreamWriter writer = new OutputStreamWriter(os, csn); - // BEGIN android-modified + // BEGIN android-changed out = new BufferedWriter(writer, 8192); - // END android-modified + // END android-changed locale = l; } /** * Constructs a {@code Formatter} whose output is written to the specified {@code PrintStream}. - * + * * The charset of the {@code Formatter} is the default charset. - * + * * The {@code Locale} for the {@code Formatter} is the default {@code Locale}. - * + * * @param ps * the {@code PrintStream} used as destination of the {@code Formatter}. If - * {@code ps} is {@code null}, then a {@ code NullPointerExcepiton} will + * {@code ps} is {@code null}, then a {@code NullPointerException} will * be raised. - * @since Android 1.0 */ public Formatter(PrintStream ps) { if (null == ps) { @@ -763,11 +735,10 @@ public final class Formatter implements Closeable, Flushable { /** * Returns the {@code Locale} of the {@code Formatter}. - * + * * @return the {@code Locale} for the {@code Formatter} or {@code null} for no {@code Locale}. * @throws FormatterClosedException * if the {@code Formatter} has been closed. - * @since Android 1.0 */ public Locale locale() { checkClosed(); @@ -776,11 +747,10 @@ public final class Formatter implements Closeable, Flushable { /** * Returns the output destination of the {@code Formatter}. - * + * * @return the output destination of the {@code Formatter}. * @throws FormatterClosedException * if the {@code Formatter} has been closed. - * @since Android 1.0 */ public Appendable out() { checkClosed(); @@ -790,12 +760,11 @@ public final class Formatter implements Closeable, Flushable { /** * Returns the content by calling the {@code toString()} method of the output * destination. - * + * * @return the content by calling the {@code toString()} method of the output * destination. * @throws FormatterClosedException * if the {@code Formatter} has been closed. - * @since Android 1.0 */ @Override public String toString() { @@ -805,11 +774,10 @@ public final class Formatter implements Closeable, Flushable { /** * Flushes the {@code Formatter}. If the output destination is {@link Flushable}, - * then the method {@ code flush()} will be called on that destination. - * + * then the method {@code flush()} will be called on that destination. + * * @throws FormatterClosedException * if the {@code Formatter} has been closed. - * @since Android 1.0 */ public void flush() { checkClosed(); @@ -825,14 +793,12 @@ public final class Formatter implements Closeable, Flushable { /** * Closes the {@code Formatter}. If the output destination is {@link Closeable}, * then the method {@code close()} will be called on that destination. - * + * * If the {@code Formatter} has been closed, then calling the this method will have no * effect. - * + * * Any method but the {@link #ioException()} that is called after the * {@code Formatter} has been closed will raise a {@code FormatterClosedException}. - * - * @since Android 1.0 */ public void close() { closed = true; @@ -850,10 +816,9 @@ public final class Formatter implements Closeable, Flushable { * Returns the last {@code IOException} thrown by the {@code Formatter}'s output * destination. If the {@code append()} method of the destination does not throw * {@code IOException}s, the {@code ioException()} method will always return {@code null}. - * + * * @return the last {@code IOException} thrown by the {@code Formatter}'s output * destination. - * @since Android 1.0 */ public IOException ioException() { return lastIOException; @@ -861,7 +826,7 @@ public final class Formatter implements Closeable, Flushable { /** * Writes a formatted string to the output destination of the {@code Formatter}. - * + * * @param format * a format string. * @param args @@ -875,23 +840,22 @@ public final class Formatter implements Closeable, Flushable { * the format string, or any other illegal situation. * @throws FormatterClosedException * if the {@code Formatter} has been closed. - * @since Android 1.0 */ public Formatter format(String format, Object... args) { return format(locale, format, args); } -// BEGIN android-changed + // BEGIN android-added /** * Cached transformer. Improves performance when format() is called multiple * times. */ private Transformer transformer; -// END android-changed + // END android-added /** * Writes a formatted string to the output destination of the {@code Formatter}. - * + * * @param l * the {@code Locale} used in the method. If {@code locale} is * {@code null}, then no localization will be applied. This @@ -910,7 +874,6 @@ public final class Formatter implements Closeable, Flushable { * the format string, or any other illegal situation. * @throws FormatterClosedException * if the {@code Formatter} has been closed. - * @since Android 1.0 */ public Formatter format(Locale l, String format, Object... args) { checkClosed(); @@ -1275,7 +1238,7 @@ public final class Formatter implements Closeable, Flushable { break; } case 'n': { - result = transfromFromLineSeparator(); + result = transformFromLineSeparator(); break; } case 't': @@ -1499,7 +1462,7 @@ public final class Formatter implements Closeable, Flushable { * Transforms line separator to a formatted string. Any flag, the width * or the precision is illegal. */ - private String transfromFromLineSeparator() { + private String transformFromLineSeparator() { if (formatToken.isPrecisionSet()) { throw new IllegalFormatPrecisionException(formatToken .getPrecision()); @@ -2121,9 +2084,18 @@ public final class Formatter implements Closeable, Flushable { boolean requireScientificRepresentation = true; double d = ((Number) argument).doubleValue(); d = Math.abs(d); - long l = Math.round(d); + if (Double.isInfinite(d)) { + precision = formatToken.getPrecision(); + precision--; + formatToken.setPrecision(precision); + transform_e(); + return; + } + BigDecimal b = new BigDecimal(d, new MathContext(precision)); + d = b.doubleValue(); + long l = b.longValue(); - if (l >= 1) { + if (d >= 1 && d < Math.pow(10, precision)) { if (l < Math.pow(10, precision)) { requireScientificRepresentation = false; precision -= String.valueOf(l).length(); @@ -2137,19 +2109,20 @@ public final class Formatter implements Closeable, Flushable { } } else { - l = Math.round(d * Math.pow(10, 4)); - if (l >= 1) { + l = b.movePointRight(4).longValue(); + b.movePointLeft(4); + if (d >= Math.pow(10, -4) && d < 1) { requireScientificRepresentation = false; precision += 4 - String.valueOf(l).length(); - l = Math.round(d * Math.pow(10, precision + 1)); + l = b.movePointRight(precision + 1).longValue(); + b.movePointLeft(precision + 1); if (String.valueOf(l).length() <= formatToken .getPrecision()) { precision++; } - l = Math.round(d * Math.pow(10, precision)); - if (l < Math.pow(10, precision - 4)) { - requireScientificRepresentation = true; - } else { + l = b.movePointRight(precision).longValue(); + b.movePointLeft(precision); + if (l >= Math.pow(10, precision - 4)) { formatToken.setPrecision(precision); } } @@ -2461,9 +2434,10 @@ public final class Formatter implements Closeable, Flushable { private void transform_Z() { TimeZone timeZone = calendar.getTimeZone(); - result - .append(timeZone.getDisplayName(true, TimeZone.SHORT, - locale)); + result.append(timeZone + .getDisplayName( + timeZone.inDaylightTime(calendar.getTime()), + TimeZone.SHORT, locale)); } private void transform_z() { diff --git a/luni/src/main/java/java/util/FormatterClosedException.java b/luni/src/main/java/java/util/FormatterClosedException.java index 63d1052..e7e57ba 100644 --- a/luni/src/main/java/java/util/FormatterClosedException.java +++ b/luni/src/main/java/java/util/FormatterClosedException.java @@ -23,7 +23,6 @@ import java.io.Serializable; * closed. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class FormatterClosedException extends IllegalStateException implements Serializable { diff --git a/luni/src/main/java/java/util/GregorianCalendar.java b/luni/src/main/java/java/util/GregorianCalendar.java index 32368ec..d8cd556 100644 --- a/luni/src/main/java/java/util/GregorianCalendar.java +++ b/luni/src/main/java/java/util/GregorianCalendar.java @@ -14,12 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2008, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ package java.util; @@ -27,24 +21,19 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -// BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. -// END android-note /** * {@code GregorianCalendar} is a concrete subclass of {@link Calendar} * and provides the standard calendar used by most of the world. - * + * * <p> * The standard (Gregorian) calendar has 2 eras, BC and AD. - * + * * <p> * This implementation handles a single discontinuity, which corresponds by * default to the date the Gregorian calendar was instituted (October 15, 1582 * in some countries, later in others). The cutover date may be changed by the * caller by calling {@code setGregorianChange()}. - * + * * <p> * Historically, in those countries which adopted the Gregorian calendar first, * October 4, 1582 was thus followed by October 15, 1582. This calendar models @@ -53,7 +42,7 @@ import java.io.ObjectOutputStream; * the Julian calendar is the leap year rule. The Julian calendar specifies leap * years every four years, whereas the Gregorian calendar omits century years * which are not divisible by 400. - * + * * <p> * {@code GregorianCalendar} implements <em>proleptic</em> Gregorian * and Julian calendars. That is, dates are computed by extrapolating the @@ -64,13 +53,13 @@ import java.io.ObjectOutputStream; * 4 AD onward, when modern Julian calendar rules were adopted. Before this * date, leap year rules were applied irregularly, and before 45 BC the Julian * calendar did not even exist. - * + * * <p> * Prior to the institution of the Gregorian calendar, New Year's Day was March * 25. To avoid confusion, this calendar always uses January 1. A manual * adjustment may be made if desired for dates that are prior to the Gregorian * changeover and which fall between January 1 and March 24. - * + * * <p> * Values calculated for the {@code WEEK_OF_YEAR} field range from 1 to * 53. Week 1 for a year is the earliest seven day period starting on @@ -80,7 +69,7 @@ import java.io.ObjectOutputStream; * {@code getFirstDayOfWeek()}, and the day of the week of January 1. * Weeks between week 1 of one year and week 1 of the following year are * numbered sequentially from 2 to 52 or 53 (as needed). - * + * * <p> * For example, January 1, 1998 was a Thursday. If * {@code getFirstDayOfWeek()} is {@code MONDAY} and @@ -90,7 +79,7 @@ import java.io.ObjectOutputStream; * {@code getFirstDayOfWeek()} is {@code SUNDAY}, then week 1 of * 1998 starts on January 4, 1998, and ends on January 10, 1998; the first three * days of 1998 then are part of week 53 of 1997. - * + * * <p> * Values calculated for the {@code WEEK_OF_MONTH} field range from 0 or * 1 to 4 or 5. Week 1 of a month (the days with <code>WEEK_OF_MONTH = @@ -102,7 +91,7 @@ import java.io.ObjectOutputStream; * {@code getFirstDayOfWeek()}, and will not include days of the * previous month. Days of a month before week 1 have a * {@code WEEK_OF_MONTH} of 0. - * + * * <p> * For example, if {@code getFirstDayOfWeek()} is {@code SUNDAY} * and {@code getMinimalDaysInFirstWeek()} is 4, then the first week of @@ -111,10 +100,10 @@ import java.io.ObjectOutputStream; * Saturday, January 3 have a {@code WEEK_OF_MONTH} of 0. If * {@code getMinimalDaysInFirstWeek()} is changed to 3, then January 1 * through January 3 have a {@code WEEK_OF_MONTH} of 1. - * + * * <p> * <strong>Example:</strong> <blockquote> - * + * * <pre> * // get the supported ids for GMT-08:00 (Pacific Standard Time) * String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000); @@ -186,13 +175,11 @@ import java.io.ObjectOutputStream; * System.out.println("DST_OFFSET: " * + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000))); // in hours * </pre> - * + * * </blockquote> - * + * * @see Calendar * @see TimeZone - * - * @since Android 1.0 */ public class GregorianCalendar extends Calendar { @@ -200,18 +187,14 @@ public class GregorianCalendar extends Calendar { /** * Value for the BC era. - * - * @since Android 1.0 */ public static final int BC = 0; /** * Value for the AD era. - * - * @since Android 1.0 */ public static final int AD = 1; - + private static final long defaultGregorianCutover = -12219292800000l; private long gregorianCutover = defaultGregorianCutover; @@ -251,8 +234,6 @@ public class GregorianCalendar extends Calendar { /** * Constructs a new {@code GregorianCalendar} initialized to the current date and * time with the default {@code Locale} and {@code TimeZone}. - * - * @since Android 1.0 */ public GregorianCalendar() { this(TimeZone.getDefault(), Locale.getDefault()); @@ -261,14 +242,13 @@ public class GregorianCalendar extends Calendar { /** * Constructs a new {@code GregorianCalendar} initialized to midnight in the default * {@code TimeZone} and {@code Locale} on the specified date. - * + * * @param year * the year. * @param month * the month. * @param day * the day of the month. - * @since Android 1.0 */ public GregorianCalendar(int year, int month, int day) { super(TimeZone.getDefault(), Locale.getDefault()); @@ -278,7 +258,7 @@ public class GregorianCalendar extends Calendar { /** * Constructs a new {@code GregorianCalendar} initialized to the specified date and * time in the default {@code TimeZone} and {@code Locale}. - * + * * @param year * the year. * @param month @@ -289,7 +269,6 @@ public class GregorianCalendar extends Calendar { * the hour. * @param minute * the minute. - * @since Android 1.0 */ public GregorianCalendar(int year, int month, int day, int hour, int minute) { super(TimeZone.getDefault(), Locale.getDefault()); @@ -299,7 +278,7 @@ public class GregorianCalendar extends Calendar { /** * Constructs a new {@code GregorianCalendar} initialized to the specified date and * time in the default {@code TimeZone} and {@code Locale}. - * + * * @param year * the year. * @param month @@ -312,7 +291,6 @@ public class GregorianCalendar extends Calendar { * the minute. * @param second * the second. - * @since Android 1.0 */ public GregorianCalendar(int year, int month, int day, int hour, int minute, int second) { @@ -328,10 +306,9 @@ public class GregorianCalendar extends Calendar { /** * Constructs a new {@code GregorianCalendar} initialized to the current date and * time and using the specified {@code Locale} and the default {@code TimeZone}. - * + * * @param locale * the {@code Locale}. - * @since Android 1.0 */ public GregorianCalendar(Locale locale) { this(TimeZone.getDefault(), locale); @@ -340,10 +317,9 @@ public class GregorianCalendar extends Calendar { /** * Constructs a new {@code GregorianCalendar} initialized to the current date and * time and using the specified {@code TimeZone} and the default {@code Locale}. - * + * * @param timezone * the {@code TimeZone}. - * @since Android 1.0 */ public GregorianCalendar(TimeZone timezone) { this(timezone, Locale.getDefault()); @@ -352,12 +328,11 @@ public class GregorianCalendar extends Calendar { /** * Constructs a new {@code GregorianCalendar} initialized to the current date and * time and using the specified {@code TimeZone} and {@code Locale}. - * + * * @param timezone * the {@code TimeZone}. * @param locale * the {@code Locale}. - * @since Android 1.0 */ public GregorianCalendar(TimeZone timezone, Locale locale) { super(timezone, locale); @@ -372,15 +347,14 @@ public class GregorianCalendar extends Calendar { /** * Adds the specified amount to a {@code Calendar} field. - * + * * @param field * the {@code Calendar} field to modify. * @param value * the amount to add to the field. - * - * @exception IllegalArgumentException - * when the specified field is DST_OFFSET or ZONE_OFFSET. - * @since Android 1.0 + * + * @throws IllegalArgumentException + * if the specified field is DST_OFFSET or ZONE_OFFSET. */ @Override public void add(int field, int value) { @@ -477,9 +451,8 @@ public class GregorianCalendar extends Calendar { /** * Creates new instance of {@code GregorianCalendar} with the same properties. - * + * * @return a shallow copy of this {@code GregorianCalendar}. - * @since Android 1.0 */ @Override public Object clone() { @@ -508,7 +481,7 @@ public class GregorianCalendar extends Calendar { int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset); fields[DAY_OF_YEAR] = dayOfYear; - if(fields[YEAR] == changeYear && gregorianCutover < timeVal + zoneOffset){ + if(fields[YEAR] == changeYear && gregorianCutover <= timeVal + zoneOffset){ dayOfYear += currentYearSkew; } int month = dayOfYear / 32; @@ -539,7 +512,7 @@ public class GregorianCalendar extends Calendar { dayOfYear = computeYearAndDay(days, timeVal - zoneOffset + dstOffset); fields[DAY_OF_YEAR] = dayOfYear; - if(fields[YEAR] == changeYear && gregorianCutover < timeVal - zoneOffset + dstOffset){ + if(fields[YEAR] == changeYear && gregorianCutover <= timeVal - zoneOffset + dstOffset){ dayOfYear += currentYearSkew; } month = dayOfYear / 32; @@ -621,7 +594,9 @@ public class GregorianCalendar extends Calendar { protected void computeFields() { int zoneOffset = getTimeZone().getRawOffset(); - fields[ZONE_OFFSET] = zoneOffset; + if(!isSet[ZONE_OFFSET]) { + fields[ZONE_OFFSET] = zoneOffset; + } int millis = (int) (time % 86400000); int savedMillis = millis; @@ -864,6 +839,9 @@ public class GregorianCalendar extends Calendar { - (days + daysInMonth(leapYear, month) - 3)) + fields[DAY_OF_WEEK_IN_MONTH] * 7; } + } else if (isSet[DAY_OF_WEEK]) { + int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1)); + days += mod7(mod7(skew + dayOfWeek - (days - 3)) - skew); } } } else { @@ -967,7 +945,7 @@ public class GregorianCalendar extends Calendar { return (year - 1970) * 365 + ((year - 1972) / 4) - ((year - 2000) / 100) + ((year - 2000) / 400); } - + private int daysInMonth() { return daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]); } @@ -1003,16 +981,15 @@ public class GregorianCalendar extends Calendar { * Compares the specified {@code Object} to this {@code GregorianCalendar} and returns whether * they are equal. To be equal, the {@code Object} must be an instance of {@code GregorianCalendar} and * have the same properties. - * + * * @param object * the {@code Object} to compare with this {@code GregorianCalendar}. * @return {@code true} if {@code object} is equal to this * {@code GregorianCalendar}, {@code false} otherwise. - * @exception IllegalArgumentException - * when the time is not set and the time cannot be computed + * @throws IllegalArgumentException + * if the time is not set and the time cannot be computed * from the current field values. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -1023,11 +1000,10 @@ public class GregorianCalendar extends Calendar { /** * Gets the maximum value of the specified field for the current date. For * example, the maximum number of days in the current month. - * + * * @param field * the field. * @return the maximum value of the specified field. - * @since Android 1.0 */ @Override public int getActualMaximum(int field) { @@ -1095,11 +1071,10 @@ public class GregorianCalendar extends Calendar { * Gets the minimum value of the specified field for the current date. For * the gregorian calendar, this value is the same as * {@code getMinimum()}. - * + * * @param field * the field. * @return the minimum value of the specified field. - * @since Android 1.0 */ @Override public int getActualMinimum(int field) { @@ -1109,11 +1084,10 @@ public class GregorianCalendar extends Calendar { /** * Gets the greatest minimum value of the specified field. For the gregorian * calendar, this value is the same as {@code getMinimum()}. - * + * * @param field * the field. * @return the greatest minimum value of the specified field. - * @since Android 1.0 */ @Override public int getGreatestMinimum(int field) { @@ -1123,9 +1097,8 @@ public class GregorianCalendar extends Calendar { /** * Returns the gregorian change date of this calendar. This is the date on * which the gregorian calendar came into effect. - * + * * @return a {@code Date} which represents the gregorian change date. - * @since Android 1.0 */ public final Date getGregorianChange() { return new Date(gregorianCutover); @@ -1134,11 +1107,10 @@ public class GregorianCalendar extends Calendar { /** * Gets the smallest maximum value of the specified field. For example, 28 * for the day of month field. - * + * * @param field * the field. * @return the smallest maximum value of the specified field. - * @since Android 1.0 */ @Override public int getLeastMaximum(int field) { @@ -1158,11 +1130,10 @@ public class GregorianCalendar extends Calendar { /** * Gets the greatest maximum value of the specified field. For example, 31 * for the day of month field. - * + * * @param field * the field. * @return the greatest maximum value of the specified field. - * @since Android 1.0 */ @Override public int getMaximum(int field) { @@ -1171,11 +1142,10 @@ public class GregorianCalendar extends Calendar { /** * Gets the smallest minimum value of the specified field. - * + * * @param field * the field. * @return the smallest minimum value of the specified field. - * @since Android 1.0 */ @Override public int getMinimum(int field) { @@ -1234,11 +1204,10 @@ public class GregorianCalendar extends Calendar { /** * Returns an integer hash code for the receiver. Objects which are equal * return the same value for this method. - * + * * @return the receiver's hash. - * + * * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -1248,12 +1217,11 @@ public class GregorianCalendar extends Calendar { /** * Returns whether the specified year is a leap year. - * + * * @param year * the year. * @return {@code true} if the specified year is a leap year, {@code false} * otherwise. - * @since Android 1.0 */ public boolean isLeapYear(int year) { if (year > changeYear) { @@ -1288,15 +1256,14 @@ public class GregorianCalendar extends Calendar { * field when it goes beyond the maximum or minimum value for the current * date. Other fields will be adjusted as required to maintain a consistent * date. - * + * * @param field * the field to roll. * @param value * the amount to add. - * - * @exception IllegalArgumentException - * when an invalid field is specified. - * @since Android 1.0 + * + * @throws IllegalArgumentException + * if an invalid field is specified. */ @Override public void roll(int field, int value) { @@ -1310,72 +1277,90 @@ public class GregorianCalendar extends Calendar { isCached = false; complete(); + int days, day, mod, maxWeeks, newWeek; int max = -1; switch (field) { - case YEAR: - max = maximums[field]; - break; - case WEEK_OF_YEAR: - case WEEK_OF_MONTH: - int days, - day; - if (field == WEEK_OF_YEAR) { - days = daysInYear(fields[YEAR]); - day = DAY_OF_YEAR; + case YEAR: + max = maximums[field]; + break; + case WEEK_OF_YEAR: + days = daysInYear(fields[YEAR]); + day = DAY_OF_YEAR; + mod = mod7(fields[DAY_OF_WEEK] - fields[day] + - (getFirstDayOfWeek() - 1)); + maxWeeks = (days - 1 + mod) / 7 + 1; + newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1; + if (newWeek == maxWeeks) { + int addDays = (newWeek - fields[field]) * 7; + if (fields[day] > addDays && fields[day] + addDays > days) { + set(field, 1); } else { - days = daysInMonth(); - day = DATE; + set(field, newWeek - 1); } - int mod = mod7(fields[DAY_OF_WEEK] - fields[day] - - (getFirstDayOfWeek() - 1)); - int maxWeeks = (days - 1 + mod) / 7 + 1; - int newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1; - if (newWeek == maxWeeks) { - if (fields[day] + (newWeek - fields[field]) * 7 > days) { - set(day, days); - } else { - set(field, newWeek); - } - } else if (newWeek == 1) { - int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1; - if (week > 1) { - set(day, 1); - } else { - set(field, newWeek); - } + } else if (newWeek == 1) { + int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1; + if (week > 1) { + set(field, 1); } else { set(field, newWeek); } - break; - case DATE: - max = daysInMonth(); - break; - case DAY_OF_YEAR: - max = daysInYear(fields[YEAR]); - break; - case DAY_OF_WEEK: - max = maximums[field]; - lastDateFieldSet = WEEK_OF_MONTH; - break; - case DAY_OF_WEEK_IN_MONTH: - max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1; - break; - - case ERA: - case MONTH: - case AM_PM: - case HOUR: - case HOUR_OF_DAY: - case MINUTE: - case SECOND: - case MILLISECOND: - set(field, mod(fields[field] + value, maximums[field] + 1)); - if (field == MONTH && fields[DATE] > daysInMonth()) { - set(DATE, daysInMonth()); - } else if (field == AM_PM) { - lastTimeFieldSet = HOUR; + } else { + set(field, newWeek); + } + break; + case WEEK_OF_MONTH: + days = daysInMonth(); + day = DATE; + mod = mod7(fields[DAY_OF_WEEK] - fields[day] + - (getFirstDayOfWeek() - 1)); + maxWeeks = (days - 1 + mod) / 7 + 1; + newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1; + if (newWeek == maxWeeks) { + if (fields[day] + (newWeek - fields[field]) * 7 > days) { + set(day, days); + } else { + set(field, newWeek); } - break; + } else if (newWeek == 1) { + int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1; + if (week > 1) { + set(day, 1); + } else { + set(field, newWeek); + } + } else { + set(field, newWeek); + } + break; + case DATE: + max = daysInMonth(); + break; + case DAY_OF_YEAR: + max = daysInYear(fields[YEAR]); + break; + case DAY_OF_WEEK: + max = maximums[field]; + lastDateFieldSet = WEEK_OF_MONTH; + break; + case DAY_OF_WEEK_IN_MONTH: + max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1; + break; + + case ERA: + case MONTH: + case AM_PM: + case HOUR: + case HOUR_OF_DAY: + case MINUTE: + case SECOND: + case MILLISECOND: + set(field, mod(fields[field] + value, maximums[field] + 1)); + if (field == MONTH && fields[DATE] > daysInMonth()) { + set(DATE, daysInMonth()); + } else if (field == AM_PM) { + lastTimeFieldSet = HOUR; + } + break; } if (max != -1) { set(field, mod(fields[field] - 1 + value, max) + 1); @@ -1389,15 +1374,14 @@ public class GregorianCalendar extends Calendar { * date. Other fields will be adjusted as required to maintain a consistent * date. For example, March 31 will roll to April 30 when rolling the month * field. - * + * * @param field * the field to roll. * @param increment * {@code true} to increment the field, {@code false} to * decrement. - * @exception IllegalArgumentException - * when an invalid field is specified. - * @since Android 1.0 + * @throws IllegalArgumentException + * if an invalid field is specified. */ @Override public void roll(int field, boolean increment) { @@ -1406,10 +1390,9 @@ public class GregorianCalendar extends Calendar { /** * Sets the gregorian change date of this calendar. - * + * * @param date * a {@code Date} which represents the gregorian change date. - * @since Android 1.0 */ public void setGregorianChange(Date date) { gregorianCutover = date.getTime(); diff --git a/luni/src/main/java/java/util/HashMap.java b/luni/src/main/java/java/util/HashMap.java index 594e8a8..4ec7a1b 100644 --- a/luni/src/main/java/java/util/HashMap.java +++ b/luni/src/main/java/java/util/HashMap.java @@ -25,25 +25,46 @@ import java.io.Serializable; /** * HashMap is an implementation of Map. All optional operations (adding and * removing) are supported. Keys and values can be any objects. - * - * @since Android 1.0 */ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable { + private static final long serialVersionUID = 362498820763181265L; + /* + * Actual count of entries + */ transient int elementCount; + /* + * The internal data structure to hold Entries + */ transient Entry<K, V>[] elementData; - final float loadFactor; - - int threshold; - + /* + * modification count, to keep track of structural modifications between the + * HashMap and the iterator + */ transient int modCount = 0; + /* + * default size that an HashMap created using the default constructor would + * have. + */ private static final int DEFAULT_SIZE = 16; + /* + * maximum ratio of (stored elements)/(storage size) which does not lead to + * rehash + */ + final float loadFactor; + + /* + * maximum number of elements that can be put in this map before having to + * rehash + */ + int threshold; + static class Entry<K, V> extends MapEntry<K, V> { final int origKeyHash; @@ -56,7 +77,7 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Entry(K theKey, V theValue) { super(theKey, theValue); - origKeyHash = (theKey == null ? 0 : theKey.hashCode()); + origKeyHash = (theKey == null ? 0 : computeHashCode(theKey)); } @Override @@ -70,33 +91,27 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, } } - static class HashMapIterator<E, KT, VT> implements Iterator<E> { + private static class AbstractMapIterator<K, V> { private int position = 0; - int expectedModCount; + Entry<K, V> futureEntry; + Entry<K, V> currentEntry; + Entry<K, V> prevEntry; - final MapEntry.Type<E, KT, VT> type; + final HashMap<K, V> associatedMap; - boolean canRemove = false; - - Entry<KT, VT> entry; - - Entry<KT, VT> lastEntry; - - final HashMap<KT, VT> associatedMap; - - HashMapIterator(MapEntry.Type<E, KT, VT> value, HashMap<KT, VT> hm) { + AbstractMapIterator(HashMap<K, V> hm) { associatedMap = hm; - type = value; expectedModCount = hm.modCount; + futureEntry = null; } public boolean hasNext() { - if (entry != null) { + if (futureEntry != null) { return true; } // BEGIN android-changed - Entry<KT, VT>[] elementData = associatedMap.elementData; + Entry<K, V>[] elementData = associatedMap.elementData; int length = elementData.length; int newPosition = position; boolean result = false; @@ -115,58 +130,88 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, // END android-changed } - void checkConcurrentMod() throws ConcurrentModificationException { + final void checkConcurrentMod() throws ConcurrentModificationException { if (expectedModCount != associatedMap.modCount) { throw new ConcurrentModificationException(); } } - public E next() { + final void makeNext() { // BEGIN android-changed // inline checkConcurrentMod() if (expectedModCount != associatedMap.modCount) { throw new ConcurrentModificationException(); } + // END android-changed if (!hasNext()) { throw new NoSuchElementException(); } - - MapEntry<KT, VT> result; - Entry<KT, VT> _entry = entry; - if (_entry == null) { - result = lastEntry = associatedMap.elementData[position++]; - entry = lastEntry.next; + if (futureEntry == null) { + currentEntry = associatedMap.elementData[position++]; + futureEntry = currentEntry.next; + prevEntry = null; } else { - if (lastEntry.next != _entry) { - lastEntry = lastEntry.next; + if(currentEntry!=null){ + prevEntry = currentEntry; } - result = _entry; - entry = _entry.next; + currentEntry = futureEntry; + futureEntry = futureEntry.next; } - canRemove = true; - return type.get(result); - // END android-changed } - public void remove() { + public final void remove() { checkConcurrentMod(); - if (!canRemove) { + if (currentEntry==null) { throw new IllegalStateException(); } - - canRemove = false; - associatedMap.modCount++; - if (lastEntry.next == entry) { - while (associatedMap.elementData[--position] == null) { - // Do nothing - } - associatedMap.elementData[position] = associatedMap.elementData[position].next; - entry = null; + if(prevEntry==null){ + int index = currentEntry.origKeyHash & (associatedMap.elementData.length - 1); + associatedMap.elementData[index] = associatedMap.elementData[index].next; } else { - lastEntry.next = entry; + prevEntry.next = currentEntry.next; } - associatedMap.elementCount--; + currentEntry = null; expectedModCount++; + associatedMap.modCount++; + associatedMap.elementCount--; + + } + } + + + private static class EntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> { + + EntryIterator (HashMap<K, V> map) { + super(map); + } + + public Map.Entry<K, V> next() { + makeNext(); + return currentEntry; + } + } + + private static class KeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> { + + KeyIterator (HashMap<K, V> map) { + super(map); + } + + public K next() { + makeNext(); + return currentEntry.key; + } + } + + private static class ValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> { + + ValueIterator (HashMap<K, V> map) { + super(map); + } + + public V next() { + makeNext(); + return currentEntry.value; } } @@ -193,9 +238,13 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, @Override public boolean remove(Object object) { - if (contains(object)) { - associatedMap.remove(((Map.Entry<?, ?>) object).getKey()); - return true; + if (object instanceof Map.Entry) { + Map.Entry<?, ?> oEntry = (Map.Entry<?, ?>) object; + Entry<KT,VT> entry = associatedMap.getEntry(oEntry.getKey()); + if(valuesEq(entry, oEntry)) { + associatedMap.removeEntry(entry); + return true; + } } return false; } @@ -203,31 +252,32 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, @Override public boolean contains(Object object) { if (object instanceof Map.Entry) { - Object key = ((Map.Entry<?, ?>) object).getKey(); - Entry entry; - if (key == null) { - entry = associatedMap.findNullKeyEntry(); - } else { - int hash = key.hashCode(); - int index = (hash & 0x7FFFFFFF) % associatedMap.elementData.length; - entry = associatedMap.findNonNullKeyEntry(key, index, hash); - } - return object.equals(entry); + Map.Entry<?, ?> oEntry = (Map.Entry<?, ?>) object; + Entry<KT, VT> entry = associatedMap.getEntry(oEntry.getKey()); + return valuesEq(entry, oEntry); } return false; } + private static boolean valuesEq(Entry entry, Map.Entry<?, ?> oEntry) { + return (entry != null) && + ((entry.value == null) ? + (oEntry.getValue() == null) : + (areEqualValues(entry.value, oEntry.getValue()))); + } + @Override public Iterator<Map.Entry<KT, VT>> iterator() { - return new HashMapIterator<Map.Entry<KT, VT>, KT, VT>( - new MapEntry.Type<Map.Entry<KT, VT>, KT, VT>() { - public Map.Entry<KT, VT> get(MapEntry<KT, VT> entry) { - return entry; - } - }, associatedMap); + return new EntryIterator<KT,VT> (associatedMap); } } + /** + * Create a new element array + * + * @param s + * @return Reference to the element array + */ @SuppressWarnings("unchecked") Entry<K, V>[] newElementArray(int s) { return new Entry[s]; @@ -235,8 +285,6 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, /** * Constructs a new empty {@code HashMap} instance. - * - * @since Android 1.0 */ public HashMap() { this(DEFAULT_SIZE); @@ -244,28 +292,47 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, /** * Constructs a new {@code HashMap} instance with the specified capacity. - * + * * @param capacity * the initial capacity of this hash map. * @throws IllegalArgumentException * when the capacity is less than zero. - * @since Android 1.0 */ public HashMap(int capacity) { - if (capacity >= 0) { - elementCount = 0; - elementData = newElementArray(capacity == 0 ? 1 : capacity); - loadFactor = 0.75f; // Default load factor of 0.75 - computeMaxSize(); - } else { - throw new IllegalArgumentException(); + this(capacity, 0.75f); // default load factor of 0.75 } + + /** + * Calculates the capacity of storage required for storing given number of + * elements + * + * @param x + * number of elements + * @return storage size + */ + private static final int calculateCapacity(int x) { + if(x >= 1 << 30){ + return 1 << 30; + } + if(x == 0){ + return 16; + } + // BEGIN android-note + // this may be better optimized as Integer.highestOneBit(x) + // END android-note + x = x -1; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x + 1; } /** * Constructs a new {@code HashMap} instance with the specified capacity and * load factor. - * + * * @param capacity * the initial capacity of this hash map. * @param loadFactor @@ -273,14 +340,14 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, * @throws IllegalArgumentException * when the capacity is less than zero or the load factor is * less or equal to zero. - * @since Android 1.0 */ public HashMap(int capacity, float loadFactor) { if (capacity >= 0 && loadFactor > 0) { + capacity = calculateCapacity(capacity); elementCount = 0; - elementData = newElementArray(capacity == 0 ? 1 : capacity); + elementData = newElementArray(capacity); this.loadFactor = loadFactor; - computeMaxSize(); + computeThreshold(); } else { throw new IllegalArgumentException(); } @@ -289,29 +356,29 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, /** * Constructs a new {@code HashMap} instance containing the mappings from * the specified map. - * + * * @param map * the mappings to add. - * @since Android 1.0 */ public HashMap(Map<? extends K, ? extends V> map) { - this(map.size() < 6 ? 11 : map.size() * 2); + this(calculateCapacity(map.size())); putAllImpl(map); } - // BEGIN android-changed /** * Removes all mappings from this hash map, leaving it empty. - * + * * @see #isEmpty * @see #size - * @since Android 1.0 */ @Override public void clear() { + // BEGIN android-changed internalClear(); + // END android-changed } + // BEGIN android-added void internalClear() { if (elementCount > 0) { elementCount = 0; @@ -319,89 +386,71 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, modCount++; } } - // END android-changed + // END android-added /** * Returns a shallow copy of this map. - * + * * @return a shallow copy of this map. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") public Object clone() { try { - // BEGIN android-changed - // copied from newer version of harmony HashMap<K, V> map = (HashMap<K, V>) super.clone(); + map.elementCount = 0; map.elementData = newElementArray(elementData.length); - map.internalClear(); - Entry<K, V> entry; - for (int i = 0; i < elementData.length; i++) { - if ((entry = elementData[i]) != null){ - map.putImpl(entry.getKey(), entry.getValue()); - while (entry.next != null){ - entry = entry.next; - map.putImpl(entry.getKey(), entry.getValue()); - } - } - // END android-changed - } + map.putAll(this); + return map; } catch (CloneNotSupportedException e) { return null; } } - private void computeMaxSize() { + /** + * Computes the threshold for rehashing + */ + private void computeThreshold() { threshold = (int) (elementData.length * loadFactor); } /** * Returns whether this map contains the specified key. - * + * * @param key * the key to search for. * @return {@code true} if this map contains the specified key, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsKey(Object key) { - Entry<K, V> m; - if (key == null) { - m = findNullKeyEntry(); - } else { - int hash = key.hashCode(); - int index = (hash & 0x7FFFFFFF) % elementData.length; - m = findNonNullKeyEntry(key, index, hash); - } + Entry<K, V> m = getEntry(key); return m != null; } /** * Returns whether this map contains the specified value. - * + * * @param value * the value to search for. * @return {@code true} if this map contains the specified value, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsValue(Object value) { if (value != null) { - for (int i = elementData.length; --i >= 0;) { + for (int i = 0; i < elementData.length; i++) { Entry<K, V> entry = elementData[i]; while (entry != null) { - if (value.equals(entry.value)) { + if (areEqualValues(value, entry.value)) { return true; } entry = entry.next; } } } else { - for (int i = elementData.length; --i >= 0;) { + for (int i = 0; i < elementData.length; i++) { Entry<K, V> entry = elementData[i]; while (entry != null) { if (entry.value == null) { @@ -418,9 +467,8 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, * Returns a set containing all of the mappings in this map. Each mapping is * an instance of {@link Map.Entry}. As the set is backed by this map, * changes in one will be reflected in the other. - * + * * @return a set of the mappings. - * @since Android 1.0 */ @Override public Set<Map.Entry<K, V>> entrySet() { @@ -429,54 +477,49 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, /** * Returns the value of the mapping with the specified key. - * + * * @param key * the key. * @return the value of the mapping with the specified key, or {@code null} * if no mapping for the specified key is found. - * @since Android 1.0 */ @Override public V get(Object key) { + Entry<K, V> m = getEntry(key); + if (m != null) { + return m.value; + } + return null; + } + + final Entry<K, V> getEntry(Object key) { Entry<K, V> m; if (key == null) { m = findNullKeyEntry(); } else { - int hash = key.hashCode(); - int index = (hash & 0x7FFFFFFF) % elementData.length; + int hash = computeHashCode(key); + int index = hash & (elementData.length - 1); m = findNonNullKeyEntry(key, index, hash); } - if (m != null) { - return m.value; - } - return null; + return m; } final Entry<K,V> findNonNullKeyEntry(Object key, int index, int keyHash) { Entry<K,V> m = elementData[index]; + // BEGIN android-changed // The VM can optimize String.equals but not Object.equals if (key instanceof String) { String keyString = (String) key; - while (m != null) { - if (m.origKeyHash == keyHash) { - if (keyString.equals(m.key)) { - return m; - } - } + while (m != null && (m.origKeyHash != keyHash || !keyString.equals(m.key))) { m = m.next; } } else { - while (m != null) { - if (m.origKeyHash == keyHash) { - if (key.equals(m.key)) { - return m; - } - } + while (m != null && (m.origKeyHash != keyHash || !areEqualKeys(key, m.key))) { m = m.next; } } - return null; + return m; // END android-changed } @@ -489,11 +532,10 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, /** * Returns whether this map is empty. - * + * * @return {@code true} if this map has no elements, {@code false} * otherwise. * @see #size() - * @since Android 1.0 */ @Override public boolean isEmpty() { @@ -504,9 +546,8 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, * Returns a set of the keys contained in this map. The set is backed by * this map so changes to one are reflected by the other. The set does not * support adding. - * + * * @return a set of the keys. - * @since Android 1.0 */ @Override public Set<K> keySet() { @@ -535,12 +576,7 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, @Override public Iterator<K> iterator() { - return new HashMapIterator<K, K, V>( - new MapEntry.Type<K, K, V>() { - public K get(MapEntry<K, V> entry) { - return entry.key; - } - }, HashMap.this); + return new KeyIterator<K,V> (HashMap.this); } }; } @@ -549,21 +585,20 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, /** * Maps the specified key to the specified value. - * + * * @param key * the key. * @param value * the value. * @return the value of any previous mapping with the specified key or * {@code null} if there was no such mapping. - * @since Android 1.0 */ @Override public V put(K key, V value) { return putImpl(key, value); } - private V putImpl(K key, V value) { + V putImpl(K key, V value) { Entry<K,V> entry; if(key == null) { entry = findNullKeyEntry(); @@ -572,17 +607,17 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, if (++elementCount > threshold) { rehash(); } - entry = createHashedEntry(key, 0, 0); + entry = createHashedEntry(null, 0, 0); } } else { - int hash = key.hashCode(); - int index = (hash & 0x7FFFFFFF) % elementData.length; + int hash = computeHashCode(key); + int index = hash & (elementData.length - 1); entry = findNonNullKeyEntry(key, index, hash); if (entry == null) { modCount++; if (++elementCount > threshold) { rehash(); - index = (hash & 0x7FFFFFFF) % elementData.length; + index = hash & (elementData.length - 1); } entry = createHashedEntry(key, index, hash); } @@ -611,10 +646,11 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, * Copies all the mappings in the specified map to this map. These mappings * will replace all mappings that this map had for any of the keys currently * in the given map. - * + * * @param map * the map to copy mappings from. - * @since Android 1.0 + * @throws NullPointerException + * if {@code map} is {@code null}. */ @Override public void putAll(Map<? extends K, ? extends V> map) { @@ -634,13 +670,13 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, } void rehash(int capacity) { - int length = (capacity == 0 ? 1 : capacity << 1); + int length = calculateCapacity((capacity == 0 ? 1 : capacity << 1)); Entry<K, V>[] newData = newElementArray(length); for (int i = 0; i < elementData.length; i++) { Entry<K, V> entry = elementData[i]; while (entry != null) { - int index = (entry.origKeyHash & 0x7FFFFFFF) % length; + int index = entry.origKeyHash & (length - 1); Entry<K, V> next = entry.next; entry.next = newData[index]; newData[index] = entry; @@ -648,7 +684,7 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, } } elementData = newData; - computeMaxSize(); + computeThreshold(); } void rehash() { @@ -657,12 +693,11 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, /** * Removes the mapping with the specified key from this map. - * + * * @param key * the key of the mapping to remove. * @return the value of the removed mapping or {@code null} if no mapping * for the specified key was found. - * @since Android 1.0 */ @Override public V remove(Object key) { @@ -673,15 +708,35 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, return null; } - Entry<K, V> removeEntry(Object key) { + /* + * Remove the given entry from the hashmap. + * Assumes that the entry is in the map. + */ + final void removeEntry(Entry<K, V> entry) { + int index = entry.origKeyHash & (elementData.length - 1); + Entry<K, V> m = elementData[index]; + if (m == entry) { + elementData[index] = entry.next; + } else { + while (m.next != entry) { + m = m.next; + } + m.next = entry.next; + + } + modCount++; + elementCount--; + } + + final Entry<K, V> removeEntry(Object key) { int index = 0; Entry<K, V> entry; Entry<K, V> last = null; if (key != null) { - int hash = key.hashCode(); - index = (hash & 0x7FFFFFFF) % elementData.length; + int hash = computeHashCode(key); + index = hash & (elementData.length - 1); entry = elementData[index]; - while (entry != null && !(entry.origKeyHash == hash && key.equals(entry.key))) { + while (entry != null && !(entry.origKeyHash == hash && areEqualKeys(key, entry.key))) { last = entry; entry = entry.next; } @@ -707,9 +762,8 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, /** * Returns the number of elements in this map. - * + * * @return the number of elements in this map. - * @since Android 1.0 */ @Override public int size() { @@ -727,16 +781,13 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, * "wrapper object" over the iterator of map's entrySet(). The {@code size} * method wraps the map's size method and the {@code contains} method wraps * the map's containsValue method. - * </p> * <p> * The collection is created when this method is called for the first time * and returned in response to all subsequent calls. This method may return * different collections when multiple concurrent calls occur, since no * synchronization is performed. - * </p> - * + * * @return a collection of the values contained in this map. - * @since Android 1.0 */ @Override public Collection<V> values() { @@ -759,12 +810,7 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, @Override public Iterator<V> iterator() { - return new HashMapIterator<V, K, V>( - new MapEntry.Type<V, K, V>() { - public V get(MapEntry<K, V> entry) { - return entry.value; - } - }, HashMap.this); + return new ValueIterator<K,V> (HashMap.this); } }; } @@ -793,10 +839,25 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, elementCount = stream.readInt(); for (int i = elementCount; --i >= 0;) { K key = (K) stream.readObject(); - int index = (null == key) ? 0 : (key.hashCode() & 0x7FFFFFFF) - % length; + int index = (null == key) ? 0 : (computeHashCode(key) & (length - 1)); createEntry(key, index, (V) stream.readObject()); } } + /* + * Contract-related functionality + */ + static int computeHashCode(Object key) { + return key.hashCode(); +} + + static boolean areEqualKeys(Object key1, Object key2) { + return key1.equals(key2); + } + + static boolean areEqualValues(Object value1, Object value2) { + return value1.equals(value2); + } + + } diff --git a/luni/src/main/java/java/util/HashSet.java b/luni/src/main/java/java/util/HashSet.java index fe89109..dca764f 100644 --- a/luni/src/main/java/java/util/HashSet.java +++ b/luni/src/main/java/java/util/HashSet.java @@ -17,7 +17,6 @@ package java.util; - import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -26,8 +25,6 @@ import java.io.Serializable; /** * HashSet is an implementation of a Set. All optional operations (adding and * removing) are supported. The elements can be any objects. - * - * @since Android 1.0 */ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable { @@ -38,8 +35,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, /** * Constructs a new empty instance of {@code HashSet}. - * - * @since Android 1.0 */ public HashSet() { this(new HashMap<E, HashSet<E>>()); @@ -50,7 +45,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * * @param capacity * the initial capacity of this {@code HashSet}. - * @since Android 1.0 */ public HashSet(int capacity) { this(new HashMap<E, HashSet<E>>(capacity)); @@ -64,7 +58,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * the initial capacity. * @param loadFactor * the initial load factor. - * @since Android 1.0 */ public HashSet(int capacity, float loadFactor) { this(new HashMap<E, HashSet<E>>(capacity, loadFactor)); @@ -76,10 +69,10 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * * @param collection * the collection of elements to add. - * @since Android 1.0 */ public HashSet(Collection<? extends E> collection) { - this(new HashMap<E, HashSet<E>>(collection.size() < 6 ? 11 : collection.size() * 2)); + this(new HashMap<E, HashSet<E>>(collection.size() < 6 ? 11 : collection + .size() * 2)); for (E e : collection) { add(e); } @@ -96,7 +89,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * the object to add. * @return {@code true} when this {@code HashSet} did not already contain * the object, {@code false} otherwise - * @since Android 1.0 */ @Override public boolean add(E object) { @@ -108,7 +100,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * * @see #isEmpty * @see #size - * @since Android 1.0 */ @Override public void clear() { @@ -121,7 +112,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * * @return a shallow copy of this {@code HashSet}. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -142,7 +132,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * the object to search for. * @return {@code true} if {@code object} is an element of this * {@code HashSet}, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean contains(Object object) { @@ -155,7 +144,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * @return {@code true} if this {@code HashSet} has no elements, * {@code false} otherwise. * @see #size - * @since Android 1.0 */ @Override public boolean isEmpty() { @@ -167,7 +155,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * * @return an Iterator on the elements of this {@code HashSet}. * @see Iterator - * @since Android 1.0 */ @Override public Iterator<E> iterator() { @@ -180,7 +167,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * @param object * the object to remove. * @return {@code true} if the object was removed, {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean remove(Object object) { @@ -191,7 +177,6 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, * Returns the number of elements in this {@code HashSet}. * * @return the number of elements in this {@code HashSet}. - * @since Android 1.0 */ @Override public int size() { @@ -221,7 +206,7 @@ public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, backingMap = createBackingMap(length, loadFactor); int elementCount = stream.readInt(); for (int i = elementCount; --i >= 0;) { - E key = (E)stream.readObject(); + E key = (E) stream.readObject(); backingMap.put(key, this); } } diff --git a/luni/src/main/java/java/util/Hashtable.java b/luni/src/main/java/java/util/Hashtable.java index abede2d..f1c1f74 100644 --- a/luni/src/main/java/java/util/Hashtable.java +++ b/luni/src/main/java/java/util/Hashtable.java @@ -31,12 +31,11 @@ import org.apache.harmony.luni.internal.nls.Messages; * factor is a float value which determines how full the Hashtable gets before * expanding the capacity. If the load factor of the Hashtable is exceeded, the * capacity is doubled. - * + * * @see Enumeration * @see java.io.Serializable * @see java.lang.Object#equals * @see java.lang.Object#hashCode - * @since Android 1.0 */ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, @@ -68,6 +67,21 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, } }; + private static final Iterator<?> EMPTY_ITERATOR = new Iterator<Object>() { + + public boolean hasNext() { + return false; + } + + public Object next() { + throw new NoSuchElementException(); + } + + public void remove() { + throw new IllegalStateException(); + } + }; + private static <K, V> Entry<K, V> newEntry(K key, V value, int hash) { return new Entry<K, V>(key, value); } @@ -121,16 +135,16 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, } } - private final class HashIterator<E> implements Iterator<E> { - private int position, expectedModCount; + private class HashIterator<E> implements Iterator<E> { + int position, expectedModCount; - private final MapEntry.Type<E, K, V> type; + final MapEntry.Type<E, K, V> type; - private Entry<K, V> lastEntry; + Entry<K, V> lastEntry; - private int lastPosition; + int lastPosition; - private boolean canRemove = false; + boolean canRemove = false; HashIterator(MapEntry.Type<E, K, V> value) { type = value; @@ -218,47 +232,9 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, } } - private final class HashEnumerator<E> implements Enumeration<E> { - boolean key; - - int start; - - Entry<K, V> entry; - - HashEnumerator(boolean isKey) { - key = isKey; - start = lastSlot + 1; - } - - public boolean hasMoreElements() { - if (entry != null) { - return true; - } - while (--start >= firstSlot) { - if (elementData[start] != null) { - entry = elementData[start]; - return true; - } - } - return false; - } - - @SuppressWarnings("unchecked") - public E nextElement() { - if (hasMoreElements()) { - Object result = key ? entry.key : entry.value; - entry = entry.next; - return (E) result; - } - throw new NoSuchElementException(); - } - } - /** * Constructs a new {@code Hashtable} using the default capacity and load * factor. - * - * @since Android 1.0 */ public Hashtable() { this(11); @@ -267,10 +243,9 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Constructs a new {@code Hashtable} using the specified capacity and the * default load factor. - * + * * @param capacity * the initial capacity. - * @since Android 1.0 */ public Hashtable(int capacity) { if (capacity >= 0) { @@ -287,12 +262,11 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Constructs a new {@code Hashtable} using the specified capacity and load * factor. - * + * * @param capacity * the initial capacity. * @param loadFactor * the initial load factor. - * @since Android 1.0 */ public Hashtable(int capacity, float loadFactor) { if (capacity >= 0 && loadFactor > 0) { @@ -309,10 +283,9 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Constructs a new instance of {@code Hashtable} containing the mappings * from the specified map. - * + * * @param map * the mappings to add. - * @since Android 1.0 */ public Hashtable(Map<? extends K, ? extends V> map) { this(map.size() < 6 ? 11 : (map.size() * 4 / 3) + 11); @@ -327,10 +300,9 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Removes all key/value pairs from this {@code Hashtable}, leaving the * size zero and the capacity unchanged. - * + * * @see #isEmpty * @see #size - * @since Android 1.0 */ public synchronized void clear() { elementCount = 0; @@ -341,17 +313,16 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Returns a new {@code Hashtable} with the same key/value pairs, capacity * and load factor. - * + * * @return a shallow copy of this {@code Hashtable}. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") public synchronized Object clone() { try { Hashtable<K, V> hashtable = (Hashtable<K, V>) super.clone(); - hashtable.elementData = elementData.clone(); + hashtable.elementData = new Entry[elementData.length]; Entry<K, V> entry; for (int i = elementData.length; --i >= 0;) { if ((entry = elementData[i]) != null) { @@ -371,14 +342,13 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Returns true if this {@code Hashtable} contains the specified object as * the value of at least one of the key/value pairs. - * + * * @param value * the object to look for as a value in this {@code Hashtable}. * @return {@code true} if object is a value in this {@code Hashtable}, * {@code false} otherwise. * @see #containsKey * @see java.lang.Object#equals - * @since Android 1.0 */ public synchronized boolean contains(Object value) { if (value == null) { @@ -388,7 +358,7 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, for (int i = elementData.length; --i >= 0;) { Entry<K, V> entry = elementData[i]; while (entry != null) { - if (value.equals(entry.value)) { + if (entry.value.equals(value)) { return true; } entry = entry.next; @@ -400,14 +370,13 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Returns true if this {@code Hashtable} contains the specified object as a * key of one of the key/value pairs. - * + * * @param key * the object to look for as a key in this {@code Hashtable}. * @return {@code true} if object is a key in this {@code Hashtable}, * {@code false} otherwise. * @see #contains * @see java.lang.Object#equals - * @since Android 1.0 */ public synchronized boolean containsKey(Object key) { return getEntry(key) != null; @@ -415,12 +384,11 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Searches this {@code Hashtable} for the specified value. - * + * * @param value * the object to search for. * @return {@code true} if {@code value} is a value of this * {@code Hashtable}, {@code false} otherwise. - * @since Android 1.0 */ public boolean containsValue(Object value) { return contains(value); @@ -430,12 +398,11 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, * Returns an enumeration on the values of this {@code Hashtable}. The * results of the Enumeration may be affected if the contents of this * {@code Hashtable} are modified. - * + * * @return an enumeration of the values of this {@code Hashtable}. * @see #keys * @see #size * @see Enumeration - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -443,7 +410,11 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, if (elementCount == 0) { return (Enumeration<V>) EMPTY_ENUMERATION; } - return new HashEnumerator<V>(false); + return new HashEnumIterator<V>(new MapEntry.Type<V, K, V>() { + public V get(MapEntry<K, V> entry) { + return entry.value; + } + }, true); } /** @@ -451,18 +422,15 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, * element in the set is a {@link Map.Entry}. The set is backed by this * {@code Hashtable} so changes to one are reflected by the other. The set * does not support adding. - * + * * @return a set of the mappings. - * @since Android 1.0 */ public Set<Map.Entry<K, V>> entrySet() { return new Collections.SynchronizedSet<Map.Entry<K, V>>( new AbstractSet<Map.Entry<K, V>>() { @Override public int size() { - synchronized (Hashtable.this) { - return elementCount; - } + return elementCount; } @Override @@ -473,25 +441,20 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, @Override @SuppressWarnings("unchecked") public boolean remove(Object object) { - synchronized (Hashtable.this) { - if (contains(object)) { - Hashtable.this - .remove(((Map.Entry<K, V>) object) - .getKey()); - return true; - } - return false; + if (contains(object)) { + Hashtable.this.remove(((Map.Entry<K, V>) object) + .getKey()); + return true; } + return false; } @Override @SuppressWarnings("unchecked") public boolean contains(Object object) { - synchronized (Hashtable.this) { - Entry<K, V> entry = getEntry(((Map.Entry<K, V>) object) - .getKey()); - return object.equals(entry); - } + Entry<K, V> entry = getEntry(((Map.Entry<K, V>) object) + .getKey()); + return object.equals(entry); } @Override @@ -511,13 +474,12 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, * Compares this {@code Hashtable} with the specified object and indicates * if they are equal. In order to be equal, {@code object} must be an * instance of Map and contain the same key/value pairs. - * + * * @param object * the object to compare with this object. * @return {@code true} if the specified object is equal to this Map, * {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public synchronized boolean equals(Object object) { @@ -544,13 +506,12 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Returns the value associated with the specified key in this * {@code Hashtable}. - * + * * @param key * the key of the value returned. * @return the value associated with the specified key, or {@code null} if * the specified key does not exist. * @see #put - * @since Android 1.0 */ @Override public synchronized V get(Object key) { @@ -597,11 +558,10 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Returns true if this {@code Hashtable} has no key/value pairs. - * + * * @return {@code true} if this {@code Hashtable} has no key/value pairs, * {@code false} otherwise. * @see #size - * @since Android 1.0 */ @Override public synchronized boolean isEmpty() { @@ -612,12 +572,11 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, * Returns an enumeration on the keys of this {@code Hashtable} instance. * The results of the enumeration may be affected if the contents of this * {@code Hashtable} are modified. - * + * * @return an enumeration of the keys of this {@code Hashtable}. * @see #elements * @see #size * @see Enumeration - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -625,31 +584,30 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, if (elementCount == 0) { return (Enumeration<K>) EMPTY_ENUMERATION; } - return new HashEnumerator<K>(true); + return new HashEnumIterator<K>(new MapEntry.Type<K, K, V>() { + public K get(MapEntry<K, V> entry) { + return entry.key; + } + }, true); } /** * Returns a set of the keys contained in this {@code Hashtable}. The set * is backed by this {@code Hashtable} so changes to one are reflected by * the other. The set does not support adding. - * + * * @return a set of the keys. - * @since Android 1.0 */ public Set<K> keySet() { return new Collections.SynchronizedSet<K>(new AbstractSet<K>() { @Override public boolean contains(Object object) { - synchronized (Hashtable.this) { - return containsKey(object); - } + return containsKey(object); } @Override public int size() { - synchronized (Hashtable.this) { - return elementCount; - } + return elementCount; } @Override @@ -659,18 +617,19 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, @Override public boolean remove(Object key) { - synchronized (Hashtable.this) { - if (containsKey(key)) { - Hashtable.this.remove(key); - return true; - } - return false; + if (containsKey(key)) { + Hashtable.this.remove(key); + return true; } + return false; } @Override public Iterator<K> iterator() { - return new HashIterator<K>(new MapEntry.Type<K, K, V>() { + if (this.size() == 0) { + return (Iterator<K>) EMPTY_ITERATOR; + } + return new HashEnumIterator<K>(new MapEntry.Type<K, K, V>() { public K get(MapEntry<K, V> entry) { return entry.key; } @@ -679,11 +638,89 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, }, this); } + class HashEnumIterator<E> extends HashIterator<E> implements Enumeration<E> { + + private boolean isEnumeration = false; + + int start; + + Entry<K, V> entry; + + HashEnumIterator(MapEntry.Type<E, K, V> value) { + super(value); + } + + HashEnumIterator(MapEntry.Type<E, K, V> value, boolean isEnumeration) { + super(value); + this.isEnumeration = isEnumeration; + start = lastSlot + 1; + } + + public boolean hasMoreElements() { + if (isEnumeration) { + if (entry != null) { + return true; + } + while (start > firstSlot) { + if (elementData[--start] != null) { + entry = elementData[start]; + return true; + } + } + return false; + } + // iterator + return super.hasNext(); + } + + public boolean hasNext() { + if (isEnumeration) { + return hasMoreElements(); + } + // iterator + return super.hasNext(); + } + + public E next() { + if (isEnumeration) { + if (expectedModCount == modCount) { + return nextElement(); + } else { + throw new ConcurrentModificationException(); + } + } + // iterator + return super.next(); + } + + @SuppressWarnings("unchecked") + public E nextElement() { + if (isEnumeration) { + if (hasMoreElements()) { + Object result = type.get(entry); + entry = entry.next; + return (E) result; + } + throw new NoSuchElementException(); + } + // iterator + return super.next(); + } + + public void remove() { + if (isEnumeration) { + throw new UnsupportedOperationException(); + } else { + super.remove(); + } + } + } + /** * Associate the specified value with the specified key in this * {@code Hashtable}. If the key already exists, the old value is replaced. * The key and value cannot be null. - * + * * @param key * the key to add. * @param value @@ -694,7 +731,6 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, * @see #get * @see #keys * @see java.lang.Object#equals - * @since Android 1.0 */ @Override public synchronized V put(K key, V value) { @@ -731,10 +767,9 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Copies every mapping to this {@code Hashtable} from the specified map. - * + * * @param map * the map to copy mappings from. - * @since Android 1.0 */ public synchronized void putAll(Map<? extends K, ? extends V> map) { for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) { @@ -745,8 +780,6 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Increases the capacity of this {@code Hashtable}. This method is called * when the size of this {@code Hashtable} exceeds the load factor. - * - * @since Android 1.0 */ protected void rehash() { int length = (elementData.length << 1) + 1; @@ -781,14 +814,13 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Removes the key/value pair with the specified key from this * {@code Hashtable}. - * + * * @param key * the key to remove. * @return the value associated with the specified key, or {@code null} if * the specified key did not exist. * @see #get * @see #put - * @since Android 1.0 */ @Override public synchronized V remove(Object key) { @@ -817,11 +849,10 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Returns the number of key/value pairs in this {@code Hashtable}. - * + * * @return the number of key/value pairs in this {@code Hashtable}. * @see #elements * @see #keys - * @since Android 1.0 */ @Override public synchronized int size() { @@ -830,9 +861,8 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, /** * Returns the string representation of this {@code Hashtable}. - * + * * @return the string representation of this {@code Hashtable}. - * @since Android 1.0 */ @Override public synchronized String toString() { @@ -874,25 +904,20 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, * Returns a collection of the values contained in this {@code Hashtable}. * The collection is backed by this {@code Hashtable} so changes to one are * reflected by the other. The collection does not support adding. - * + * * @return a collection of the values. - * @since Android 1.0 */ public Collection<V> values() { return new Collections.SynchronizedCollection<V>( new AbstractCollection<V>() { @Override public boolean contains(Object object) { - synchronized (Hashtable.this) { - return Hashtable.this.contains(object); - } + return Hashtable.this.contains(object); } @Override public int size() { - synchronized (Hashtable.this) { - return elementCount; - } + return elementCount; } @Override diff --git a/luni/src/main/java/java/util/HugeEnumSet.java b/luni/src/main/java/java/util/HugeEnumSet.java index 1d43360..fd3e1bd 100644 --- a/luni/src/main/java/java/util/HugeEnumSet.java +++ b/luni/src/main/java/java/util/HugeEnumSet.java @@ -92,6 +92,8 @@ final class HugeEnumSet<E extends Enum<E>> extends EnumSet<E> { currentElementMask = unProcessedBits[bitsPosition] & (-unProcessedBits[bitsPosition]); unProcessedBits[bitsPosition] -= currentElementMask; + int index = Long.numberOfTrailingZeros(currentElementMask) + + bitsPosition * BIT_IN_LONG; if (0 == unProcessedBits[bitsPosition]) { int oldBitsPosition = bitsPosition; findNextNoneZeroPosition(bitsPosition + 1); @@ -99,8 +101,7 @@ final class HugeEnumSet<E extends Enum<E>> extends EnumSet<E> { canProcess = false; } } - return enums[Long.numberOfTrailingZeros(currentElementMask) - + bitsPosition * BIT_IN_LONG]; + return enums[index]; } public void remove() { @@ -185,6 +186,7 @@ final class HugeEnumSet<E extends Enum<E>> extends EnumSet<E> { } } + @SuppressWarnings("unchecked") @Override public boolean contains(Object object) { if (null == object) { @@ -329,7 +331,7 @@ final class HugeEnumSet<E extends Enum<E>> extends EnumSet<E> { // endElementInBits + 1 is the number of consecutive ones. // 63 - endElementInBits is the following zeros of the right most one. - range = -1l >>> (BIT_IN_LONG - (endElementInBits + 1)) << (63 - endElementInBits); + range = -1l >>> (BIT_IN_LONG - (endElementInBits + 1)); size -= Long.bitCount(bits[endBitsIndex]); bits[endBitsIndex] |= range; size += Long.bitCount(bits[endBitsIndex]); diff --git a/luni/src/main/java/java/util/IdentityHashMap.java b/luni/src/main/java/java/util/IdentityHashMap.java index 3301a99..30330b5 100644 --- a/luni/src/main/java/java/util/IdentityHashMap.java +++ b/luni/src/main/java/java/util/IdentityHashMap.java @@ -30,16 +30,15 @@ import java.io.Serializable; * <p> * <b>Note: This class intentionally violates the general contract of {@code * Map}'s on comparing objects by their {@code equals} method.</b> - * </p> * <p> * IdentityHashMap uses open addressing (linear probing in particular) for * collision resolution. This is different from HashMap which uses Chaining. - * </p> + * <p> * Like HashMap, IdentityHashMap is not thread safe, so access by multiple * threads must be synchronized by an external mechanism such as * Collections.synchronizedMap. * - * @since Android 1.0 + * @since 1.4 */ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Serializable, Cloneable { @@ -239,8 +238,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements /** * Creates an IdentityHashMap with default expected maximum size. - * - * @since Android 1.0 */ public IdentityHashMap() { this(DEFAULT_MAX_SIZE); @@ -252,7 +249,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * @param maxSize * The estimated maximum number of entries that will be put in * this map. - * @since Android 1.0 */ public IdentityHashMap(int maxSize) { if (maxSize >= 0) { @@ -274,6 +270,13 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements return (int) (((long) threshold * 10000) / loadFactor) * 2; } + /** + * Create a new element array + * + * @param s + * the number of elements + * @return Reference to the element array + */ private Object[] newElementArray(int s) { return new Object[s]; } @@ -283,7 +286,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * * @param map * A map of (key,value) pairs to copy into the IdentityHashMap. - * @since Android 1.0 */ public IdentityHashMap(Map<? extends K, ? extends V> map) { this(map.size() < 6 ? 11 : map.size() * 2); @@ -300,7 +302,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * * @see #isEmpty() * @see #size() - * @since Android 1.0 */ @Override public void clear() { @@ -318,7 +319,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * the key to search for. * @return {@code true} if this map contains the specified key, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsKey(Object key) { @@ -337,7 +337,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * the value to search for. * @return {@code true} if this map contains the specified value, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsValue(Object value) { @@ -359,7 +358,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * @param key * the key. * @return the value of the mapping with the specified key. - * @since Android 1.0 */ @Override public V get(Object key) { @@ -390,6 +388,10 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements return null; } + /** + * Convenience method for getting the IdentityHashMapEntry without the + * NULL_OBJECT elements + */ @SuppressWarnings("unchecked") private IdentityHashMapEntry<K, V> getEntry(int index) { Object key = elementData[index]; @@ -405,6 +407,10 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements return new IdentityHashMapEntry<K, V>((K) key, (V) value); } + /** + * Returns the index where the key is found at, or the index of the next + * empty spot if the key is not found in this table. + */ private int findIndex(Object key, Object[] array) { int length = array.length; int index = getModuloHash(key, length); @@ -435,7 +441,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * the value. * @return the value of any previous mapping with the specified key or * {@code null} if there was no such mapping. - * @since Android 1.0 */ @Override public V put(K key, V value) { @@ -478,7 +483,8 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * * @param map * the map to copy mappings from. - * @since Android 1.0 + * @throws NullPointerException + * if {@code map} is {@code null}. */ @Override public void putAll(Map<? extends K, ? extends V> map) { @@ -515,7 +521,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * the key of the mapping to remove. * @return the value of the removed mapping, or {@code null} if no mapping * for the specified key was found. - * @since Android 1.0 */ @Override public V remove(Object key) { @@ -575,7 +580,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * changes in one will be reflected in the other. * * @return a set of the mappings. - * @since Android 1.0 */ @Override public Set<Map.Entry<K, V>> entrySet() { @@ -588,7 +592,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * support adding. * * @return a set of the keys. - * @since Android 1.0 */ @Override public Set<K> keySet() { @@ -643,16 +646,13 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * "wrapper object" over the iterator of map's entrySet(). The {@code size} * method wraps the map's size method and the {@code contains} method wraps * the map's containsValue method. - * </p> * <p> * The collection is created when this method is called for the first time * and returned in response to all subsequent calls. This method may return * different collections when multiple concurrent calls occur, since no * synchronization is performed. - * </p> * * @return a collection of the values contained in this map. - * @since Android 1.0 */ @Override public Collection<V> values() { @@ -710,7 +710,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * @param object * the object to compare to. * @return whether the argument object is equal to this object. - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -745,7 +744,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * * @return a shallow copy of this IdentityHashMap. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -762,7 +760,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * @return {@code true} if this IdentityHashMap has no elements, * {@code false} otherwise. * @see #size() - * @since Android 1.0 */ @Override public boolean isEmpty() { @@ -773,7 +770,6 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements * Returns the number of mappings in this IdentityHashMap. * * @return the number of mappings in this IdentityHashMap. - * @since Android 1.0 */ @Override public int size() { diff --git a/luni/src/main/java/java/util/IllegalFormatCodePointException.java b/luni/src/main/java/java/util/IllegalFormatCodePointException.java index e04eeba..c0d6b6f 100644 --- a/luni/src/main/java/java/util/IllegalFormatCodePointException.java +++ b/luni/src/main/java/java/util/IllegalFormatCodePointException.java @@ -24,7 +24,6 @@ import java.io.Serializable; * passed as a parameter to a Formatter. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class IllegalFormatCodePointException extends IllegalFormatException implements Serializable { diff --git a/luni/src/main/java/java/util/IllegalFormatConversionException.java b/luni/src/main/java/java/util/IllegalFormatConversionException.java index 769381b..696f4f2 100644 --- a/luni/src/main/java/java/util/IllegalFormatConversionException.java +++ b/luni/src/main/java/java/util/IllegalFormatConversionException.java @@ -23,7 +23,8 @@ import java.io.Serializable; * is incompatible with the corresponding format specifier. * * @see java.lang.RuntimeException - * @since Android 1.0 + * + * @since 1.5 */ public class IllegalFormatConversionException extends IllegalFormatException implements Serializable { diff --git a/luni/src/main/java/java/util/IllegalFormatException.java b/luni/src/main/java/java/util/IllegalFormatException.java index 2c1f2d7..3d37cd0 100644 --- a/luni/src/main/java/java/util/IllegalFormatException.java +++ b/luni/src/main/java/java/util/IllegalFormatException.java @@ -24,7 +24,6 @@ import java.io.Serializable; * allowed to be instantiated. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class IllegalFormatException extends IllegalArgumentException implements Serializable { diff --git a/luni/src/main/java/java/util/IllegalFormatFlagsException.java b/luni/src/main/java/java/util/IllegalFormatFlagsException.java index 6b27c74..4fa2d9c 100644 --- a/luni/src/main/java/java/util/IllegalFormatFlagsException.java +++ b/luni/src/main/java/java/util/IllegalFormatFlagsException.java @@ -23,7 +23,6 @@ import java.io.Serializable; * the format flags is illegal. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class IllegalFormatFlagsException extends IllegalFormatException implements Serializable { diff --git a/luni/src/main/java/java/util/IllegalFormatPrecisionException.java b/luni/src/main/java/java/util/IllegalFormatPrecisionException.java index 6ccf5d2..5d5113f 100644 --- a/luni/src/main/java/java/util/IllegalFormatPrecisionException.java +++ b/luni/src/main/java/java/util/IllegalFormatPrecisionException.java @@ -21,7 +21,6 @@ package java.util; * a negative other than -1 or in other cases where precision is not supported. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class IllegalFormatPrecisionException extends IllegalFormatException { diff --git a/luni/src/main/java/java/util/IllegalFormatWidthException.java b/luni/src/main/java/java/util/IllegalFormatWidthException.java index 8348ec7..01904f8 100644 --- a/luni/src/main/java/java/util/IllegalFormatWidthException.java +++ b/luni/src/main/java/java/util/IllegalFormatWidthException.java @@ -22,7 +22,6 @@ package java.util; * supported. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class IllegalFormatWidthException extends IllegalFormatException { diff --git a/luni/src/main/java/java/util/InputMismatchException.java b/luni/src/main/java/java/util/InputMismatchException.java index 0fc5385..eed0b83 100644 --- a/luni/src/main/java/java/util/InputMismatchException.java +++ b/luni/src/main/java/java/util/InputMismatchException.java @@ -24,13 +24,12 @@ import java.io.Serializable; * * @see Scanner * @see java.lang.RuntimeException - * @since Android 1.0 */ public class InputMismatchException extends NoSuchElementException implements Serializable { - static final long serialVersionUID = 8811230760997066428L; - + private static final long serialVersionUID = 8811230760997066428L; + /** * Constructs a new {@code InputMismatchException} with the current stack * trace filled in. diff --git a/luni/src/main/java/java/util/InvalidPropertiesFormatException.java b/luni/src/main/java/java/util/InvalidPropertiesFormatException.java index 4e8a3e3..015c3d0 100644 --- a/luni/src/main/java/java/util/InvalidPropertiesFormatException.java +++ b/luni/src/main/java/java/util/InvalidPropertiesFormatException.java @@ -30,8 +30,6 @@ import java.io.IOException; * Even though this Exception inherits the {@code Serializable} interface, it is not * serializable. The methods used for serialization throw * {@code NotSerializableException}s. - * - * @since Android 1.0 */ public class InvalidPropertiesFormatException extends IOException { diff --git a/luni/src/main/java/java/util/Iterator.java b/luni/src/main/java/java/util/Iterator.java index 9f20dc5..6ebae04 100644 --- a/luni/src/main/java/java/util/Iterator.java +++ b/luni/src/main/java/java/util/Iterator.java @@ -17,17 +17,18 @@ package java.util; - /** - * An Iterator is used to sequence over a collection of objects. Conceptual, an - * iterator is always positioned between two elements of a collection. A fresh - * iterator is always positioned in front of the first element. + * An {@code Iterator} is used to sequence over a collection of objects. + * Conceptually, an iterator is always positioned between two elements of a + * collection. A fresh iterator is always positioned in front of the first + * element. * * If a collection has been changed since its creation, methods {@code next} and * {@code hasNext()} may throw a {@code ConcurrentModificationException}. * Iterators with this behavior are called fail-fast iterators. * - * @since Android 1.0 + * @param <E> + * the type of object returned by the iterator. */ public interface Iterator<E> { /** @@ -36,7 +37,6 @@ public interface Iterator<E> { * * @return {@code true} if there are more elements, {@code false} otherwise. * @see #next - * @since Android 1.0 */ public boolean hasNext(); @@ -48,7 +48,6 @@ public interface Iterator<E> { * @throws NoSuchElementException * if there are no more elements. * @see #hasNext - * @since Android 1.0 */ public E next(); @@ -62,7 +61,6 @@ public interface Iterator<E> { * @throws IllegalStateException * if {@code next} has not been called, or {@code remove} has * already been called after the last call to {@code next}. - * @since Android 1.0 */ public void remove(); } diff --git a/luni/src/main/java/java/util/LinkedHashMap.java b/luni/src/main/java/java/util/LinkedHashMap.java index a32a28b..ed526d8 100644 --- a/luni/src/main/java/java/util/LinkedHashMap.java +++ b/luni/src/main/java/java/util/LinkedHashMap.java @@ -17,7 +17,6 @@ package java.util; - /** * LinkedHashMap is a variant of HashMap. Its entries are kept in a * doubly-linked list. The iteration order is, by default, the order in which @@ -46,8 +45,8 @@ package java.util; * elements during iteration. It is not possible to guarantee that this * mechanism works in all cases of unsynchronized concurrent modification. It * should only be used for debugging purposes. - * - * @since Android 1.0 + * + * @since 1.4 */ public class LinkedHashMap<K, V> extends HashMap<K, V> { @@ -59,8 +58,6 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { /** * Constructs a new empty {@code LinkedHashMap} instance. - * - * @since Android 1.0 */ public LinkedHashMap() { super(); @@ -71,12 +68,11 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { /** * Constructs a new {@code LinkedHashMap} instance with the specified * capacity. - * + * * @param s * the initial capacity of this map. - * @exception IllegalArgumentException - * when the capacity is less than zero. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the capacity is less than zero. */ public LinkedHashMap(int s) { super(s); @@ -87,7 +83,7 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { /** * Constructs a new {@code LinkedHashMap} instance with the specified * capacity and load factor. - * + * * @param s * the initial capacity of this map. * @param lf @@ -95,7 +91,6 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { * @throws IllegalArgumentException * when the capacity is less than zero or the load factor is * less or equal to zero. - * @since Android 1.0 */ public LinkedHashMap(int s, float lf) { super(s, lf); @@ -107,7 +102,7 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { /** * Constructs a new {@code LinkedHashMap} instance with the specified * capacity, load factor and a flag specifying the ordering behavior. - * + * * @param s * the initial capacity of this hash map. * @param lf @@ -120,7 +115,6 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { * @throws IllegalArgumentException * when the capacity is less than zero or the load factor is * less or equal to zero. - * @since Android 1.0 */ public LinkedHashMap(int s, float lf, boolean order) { super(s, lf); @@ -132,10 +126,9 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { /** * Constructs a new {@code LinkedHashMap} instance containing the mappings * from the specified map. The order of the elements is preserved. - * + * * @param m * the mappings to add. - * @since Android 1.0 */ public LinkedHashMap(Map<? extends K, ? extends V> m) { accessOrder = false; @@ -144,58 +137,47 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { putAll(m); } - static final class LinkedHashIterator<E, KT, VT> extends HashMapIterator<E, KT, VT> { - LinkedHashIterator(MapEntry.Type<E, KT, VT> value, LinkedHashMap<KT, VT> hm) { - super(value, hm); - entry = hm.head; + private static class AbstractMapIterator<K, V> { + int expectedModCount; + LinkedHashMapEntry<K, V> futureEntry; + LinkedHashMapEntry<K, V> currentEntry; + final LinkedHashMap<K, V> associatedMap; + + AbstractMapIterator(LinkedHashMap<K, V> map) { + expectedModCount = map.modCount; + futureEntry = map.head; + associatedMap = map; } - @Override public boolean hasNext() { - return (entry != null); + return (futureEntry != null); } - @Override - public E next() { + final void checkConcurrentMod() throws ConcurrentModificationException { + if (expectedModCount != associatedMap.modCount) { + throw new ConcurrentModificationException(); + } + } + + final void makeNext() { checkConcurrentMod(); if (!hasNext()) { throw new NoSuchElementException(); } - E result = type.get(entry); - lastEntry = entry; - entry = ((LinkedHashMapEntry<KT, VT>)entry).chainForward; - canRemove = true; - return result; + currentEntry = futureEntry; + futureEntry = futureEntry.chainForward; } - @Override public void remove() { checkConcurrentMod(); - if (!canRemove) { + if (currentEntry==null) { throw new IllegalStateException(); } - - canRemove = false; - associatedMap.modCount++; - - int index = (lastEntry.key == null)? 0 : (lastEntry.key.hashCode() & 0x7FFFFFFF) % associatedMap.elementData.length; - LinkedHashMapEntry<KT, VT> m = (LinkedHashMapEntry<KT, VT>) associatedMap.elementData[index]; - if (m == lastEntry) { - associatedMap.elementData[index] = lastEntry.next; - } else { - while (m.next != null) { - if (m.next == lastEntry) { - break; - } - m = (LinkedHashMapEntry<KT, VT>) m.next; - } - // assert m.next == entry - m.next = lastEntry.next; - } - LinkedHashMapEntry<KT, VT> lhme = (LinkedHashMapEntry<KT, VT>) lastEntry; - LinkedHashMapEntry<KT, VT> p = lhme.chainBackward; - LinkedHashMapEntry<KT, VT> n = lhme.chainForward; - LinkedHashMap<KT, VT> lhm = (LinkedHashMap<KT, VT>) associatedMap; + associatedMap.removeEntry(currentEntry); + LinkedHashMapEntry<K, V> lhme = currentEntry; + LinkedHashMapEntry<K, V> p = lhme.chainBackward; + LinkedHashMapEntry<K, V> n = lhme.chainForward; + LinkedHashMap<K, V> lhm = associatedMap; if (p != null) { p.chainForward = n; if (n != null) { @@ -211,23 +193,56 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { lhm.tail = null; } } - associatedMap.elementCount--; + currentEntry = null; expectedModCount++; } } - static final class LinkedHashMapEntrySet<KT, VT> extends HashMapEntrySet<KT, VT> { + private static class EntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> { + + EntryIterator (LinkedHashMap<K, V> map) { + super(map); + } + + public Map.Entry<K, V> next() { + makeNext(); + return currentEntry; + } + } + + private static class KeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> { + + KeyIterator (LinkedHashMap<K, V> map) { + super(map); + } + + public K next() { + makeNext(); + return currentEntry.key; + } + } + + private static class ValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> { + + ValueIterator (LinkedHashMap<K, V> map) { + super(map); + } + + public V next() { + makeNext(); + return currentEntry.value; + } + } + + static final class LinkedHashMapEntrySet<KT, VT> extends + HashMapEntrySet<KT, VT> { public LinkedHashMapEntrySet(LinkedHashMap<KT, VT> lhm) { super(lhm); } @Override - public Iterator<Map.Entry<KT,VT>> iterator() { - return new LinkedHashIterator<Map.Entry<KT,VT>,KT,VT>(new MapEntry.Type<Map.Entry<KT,VT>, KT, VT>() { - public Map.Entry<KT,VT> get(MapEntry<KT,VT> entry) { - return entry; - } - }, (LinkedHashMap<KT, VT>) hashMap()); + public Iterator<Map.Entry<KT, VT>> iterator() { + return new EntryIterator<KT,VT>((LinkedHashMap<KT, VT>) hashMap()); } } @@ -246,11 +261,11 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { chainBackward = null; } - @Override @SuppressWarnings("unchecked") public Object clone() { - LinkedHashMapEntry<K, V> entry = (LinkedHashMapEntry<K, V>) super.clone(); + LinkedHashMapEntry<K, V> entry = (LinkedHashMapEntry<K, V>) super + .clone(); entry.chainBackward = chainBackward; entry.chainForward = chainForward; LinkedHashMapEntry<K, V> lnext = (LinkedHashMapEntry<K, V>) entry.next; @@ -262,6 +277,33 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { } @Override + public boolean containsValue(Object value) { + LinkedHashMapEntry<K, V> entry = head; + if (null == value) { + while (null != entry) { + if (null == entry.value) { + return true; + } + entry = entry.chainForward; + } + } else { + while (null != entry) { + if (value.equals(entry.value)) { + return true; + } + entry = entry.chainForward; + } + } + return false; + } + + /** + * Create a new element array + * + * @param s + * @return Reference to the element array + */ + @Override @SuppressWarnings("unchecked") Entry<K, V>[] newElementArray(int s) { return new LinkedHashMapEntry[s]; @@ -269,22 +311,21 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { /** * Returns the value of the mapping with the specified key. - * + * * @param key * the key. * @return the value of the mapping with the specified key, or {@code null} * if no mapping for the specified key is found. - * @since Android 1.0 */ @Override public V get(Object key) { LinkedHashMapEntry<K, V> m; if (key == null) { - m = (LinkedHashMapEntry<K, V>)findNullKeyEntry(); + m = (LinkedHashMapEntry<K, V>) findNullKeyEntry(); } else { int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % elementData.length; - m = (LinkedHashMapEntry<K, V>)findNonNullKeyEntry(key, index, hash); + m = (LinkedHashMapEntry<K, V>) findNonNullKeyEntry(key, index, hash); } if (m == null) { return null; @@ -321,7 +362,7 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { return m; } - Entry<K,V> createHashedEntry(K key, int index, int hash) { + Entry<K, V> createHashedEntry(K key, int index, int hash) { LinkedHashMapEntry<K, V> m = new LinkedHashMapEntry<K, V>(key, hash); m.next = elementData[index]; elementData[index] = m; @@ -329,22 +370,19 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { return m; } - // BEGIN android-changed - // copied from newer version of harmony /** * Maps the specified key to the specified value. - * + * * @param key * the key. * @param value * the value. * @return the value of any previous mapping with the specified key or * {@code null} if there was no such mapping. - * @since Android 1.0 */ @Override public V put(K key, V value) { - V result = putImpl(key,value); + V result = putImpl(key, value); if (removeEldestEntry(head)) { remove(head.key); @@ -352,38 +390,38 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { return result; } - - V putImpl(K key, V value){ + + V putImpl(K key, V value) { LinkedHashMapEntry<K, V> m; - if (elementCount == 0){ + if (elementCount == 0) { head = tail = null; } if (key == null) { - m = (LinkedHashMapEntry<K, V>)findNullKeyEntry(); + m = (LinkedHashMapEntry<K, V>) findNullKeyEntry(); if (m == null) { modCount++; - // Check if we need to remove the oldest entry - // The check includes accessOrder since an accessOrder LinkedHashMap - // does not record - // the oldest member in 'head'. + // Check if we need to remove the oldest entry. The check + // includes accessOrder since an accessOrder LinkedHashMap does + // not record the oldest member in 'head'. if (++elementCount > threshold) { rehash(); } - m = (LinkedHashMapEntry<K, V>) createHashedEntry(null, 0, 0); + m = (LinkedHashMapEntry<K, V>) createHashedEntry(null, 0, 0); } else { linkEntry(m); } } else { int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % elementData.length; - m = (LinkedHashMapEntry<K, V>)findNonNullKeyEntry(key, index, hash); + m = (LinkedHashMapEntry<K, V>) findNonNullKeyEntry(key, index, hash); if (m == null) { modCount++; if (++elementCount > threshold) { rehash(); index = (hash & 0x7FFFFFFF) % elementData.length; } - m = (LinkedHashMapEntry<K, V>) createHashedEntry(key, index, hash); + m = (LinkedHashMapEntry<K, V>) createHashedEntry(key, index, + hash); } else { linkEntry(m); } @@ -393,7 +431,6 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { m.value = value; return result; } - // END android-changed /* * @param m @@ -448,16 +485,14 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { tail.chainForward = m; tail = m; } - } /** * Returns a set containing all of the mappings in this map. Each mapping is * an instance of {@link Map.Entry}. As the set is backed by this map, * changes in one will be reflected in the other. - * + * * @return a set of the mappings. - * @since Android 1.0 */ @Override public Set<Map.Entry<K, V>> entrySet() { @@ -468,9 +503,8 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { * Returns a set of the keys contained in this map. The set is backed by * this map so changes to one are reflected by the other. The set does not * support adding. - * + * * @return a set of the keys. - * @since Android 1.0 */ @Override public Set<K> keySet() { @@ -502,11 +536,7 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { @Override public Iterator<K> iterator() { - return new LinkedHashIterator<K,K,V>(new MapEntry.Type<K,K,V>() { - public K get(MapEntry<K,V> entry) { - return entry.key; - } - }, LinkedHashMap.this); + return new KeyIterator<K,V>(LinkedHashMap.this); } }; } @@ -524,16 +554,13 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { * "wrapper object" over the iterator of map's entrySet(). The size method * wraps the map's size method and the contains method wraps the map's * containsValue method. - * </p> * <p> * The collection is created when this method is called for the first time * and returned in response to all subsequent calls. This method may return * different collections when multiple concurrent calls occur, since no * synchronization is performed. - * </p> - * + * * @return a collection of the values contained in this map. - * @since Android 1.0 */ @Override public Collection<V> values() { @@ -556,11 +583,7 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { @Override public Iterator<V> iterator() { - return new LinkedHashIterator<V,K,V>(new MapEntry.Type<V,K,V>() { - public V get(MapEntry<K,V> entry) { - return entry.value; - } - }, LinkedHashMap.this); + return new ValueIterator<K,V>(LinkedHashMap.this); } }; } @@ -569,12 +592,11 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { /** * Removes the mapping with the specified key from this map. - * + * * @param key * the key of the mapping to remove. * @return the value of the removed mapping or {@code null} if no mapping * for the specified key was found. - * @since Android 1.0 */ @Override public V remove(Object key) { @@ -602,23 +624,21 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { * eldest member of the map should be deleted before adding the new member. * If this map was created with accessOrder = true, then the result of * removeEldestEntry is assumed to be false. - * + * * @param eldest * the entry to check if it should be removed. * @return {@code true} if the eldest member should be removed. - * @since Android 1.0 */ - protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { + protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return false; } // BEGIN android-changed /** * Removes all elements from this map, leaving it empty. - * + * * @see #isEmpty() * @see #size() - * @since Android 1.0 */ @Override public void clear() { @@ -631,25 +651,4 @@ public class LinkedHashMap<K, V> extends HashMap<K, V> { head = tail = null; } // END android-changed - - // BEGIN android-removed - // copied from newer version of harmony - // /** - // * Answers a new HashMap with the same mappings and size as this HashMap. - // * - // * @return a shallow copy of this HashMap - // * - // * @see java.lang.Cloneable - // */ - // @Override - // @SuppressWarnings("unchecked") - // public Object clone() { - // LinkedHashMap<K, V> map = (LinkedHashMap<K, V>) super.clone(); - // map.clear(); - // for (Map.Entry<K, V> entry : entrySet()) { - // map.put(entry.getKey(), entry.getValue()); - // } - // return map; - // } - // END android-removed } diff --git a/luni/src/main/java/java/util/LinkedHashSet.java b/luni/src/main/java/java/util/LinkedHashSet.java index 943e01c..3add460 100644 --- a/luni/src/main/java/java/util/LinkedHashSet.java +++ b/luni/src/main/java/java/util/LinkedHashSet.java @@ -17,7 +17,6 @@ package java.util; - import java.io.Serializable; /** @@ -30,18 +29,16 @@ import java.io.Serializable; * Like HashSet, LinkedHashSet is not thread safe, so access by multiple threads * must be synchronized by an external mechanism such as * {@link Collections#synchronizedSet(Set)}. - * - * @since Android 1.0 + * + * @since 1.4 */ public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, Serializable { - + private static final long serialVersionUID = -2851667679971038690L; /** * Constructs a new empty instance of {@code LinkedHashSet}. - * - * @since Android 1.0 */ public LinkedHashSet() { super(new LinkedHashMap<E, HashSet<E>>()); @@ -53,7 +50,6 @@ public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, * * @param capacity * the initial capacity of this {@code LinkedHashSet}. - * @since Android 1.0 */ public LinkedHashSet(int capacity) { super(new LinkedHashMap<E, HashSet<E>>(capacity)); @@ -67,7 +63,6 @@ public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, * the initial capacity. * @param loadFactor * the initial load factor. - * @since Android 1.0 */ public LinkedHashSet(int capacity, float loadFactor) { super(new LinkedHashMap<E, HashSet<E>>(capacity, loadFactor)); @@ -79,7 +74,6 @@ public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, * * @param collection * the collection of elements to add. - * @since Android 1.0 */ public LinkedHashSet(Collection<? extends E> collection) { super(new LinkedHashMap<E, HashSet<E>>(collection.size() < 6 ? 11 diff --git a/luni/src/main/java/java/util/LinkedList.java b/luni/src/main/java/java/util/LinkedList.java index 7cfefe6..64326e3 100644 --- a/luni/src/main/java/java/util/LinkedList.java +++ b/luni/src/main/java/java/util/LinkedList.java @@ -17,7 +17,6 @@ package java.util; - import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -28,12 +27,12 @@ import java.lang.reflect.Array; * LinkedList is an implementation of List, backed by a linked list. All * optional operations (adding, removing and replacing) are supported. The * elements can be any objects. - * - * @since Android 1.0 + * + * @since 1.2 */ public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Queue<E>, Cloneable, Serializable { - + private static final long serialVersionUID = 876323262645176354L; transient int size = 0; @@ -178,8 +177,6 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Constructs a new empty instance of {@code LinkedList}. - * - * @since Android 1.0 */ public LinkedList() { voidLink = new Link<E>(null, null, null); @@ -192,10 +189,9 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements * elements contained in the specified {@code collection}. The order of the * elements in this new {@code LinkedList} will be determined by the * iteration order of {@code collection}. - * + * * @param collection * the collection of elements to add. - * @since Android 1.0 */ public LinkedList(Collection<? extends E> collection) { this(); @@ -207,14 +203,13 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements * specified location. The object is inserted before any previous element at * the specified location. If the location is equal to the size of this * {@code LinkedList}, the object is added at the end. - * + * * @param location * the index at which to insert. * @param object * the object to add. * @throws IndexOutOfBoundsException * if {@code location < 0 || >= size()} - * @since Android 1.0 */ @Override public void add(int location, E object) { @@ -242,11 +237,10 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Adds the specified object at the end of this {@code LinkedList}. - * + * * @param object * the object to add. * @return always true - * @since Android 1.0 */ @Override public boolean add(E object) { @@ -264,7 +258,7 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements * Inserts the objects in the specified collection at the specified location * in this {@code LinkedList}. The objects are added in the order they are * returned from the collection's iterator. - * + * * @param location * the index at which to insert. * @param collection @@ -277,7 +271,6 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements * if an object cannot be added to this list. * @throws IndexOutOfBoundsException * if {@code location < 0 || > size()} - * @since Android 1.0 */ @Override public boolean addAll(int location, Collection<? extends E> collection) { @@ -288,6 +281,9 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements if (adding == 0) { return false; } + Collection<? extends E> elements = (collection == this) ? + new ArrayList<E>(collection) : collection; + Link<E> previous = voidLink; if (location < (size / 2)) { for (int i = 0; i < location; i++) { @@ -299,7 +295,7 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements } } Link<E> next = previous.next; - for (E e : collection) { + for (E e : elements) { Link<E> newLink = new Link<E>(e, previous, null); previous.next = newLink; previous = newLink; @@ -311,15 +307,13 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements return true; } - /** * Adds the objects in the specified Collection to this {@code LinkedList}. - * + * * @param collection * the collection of objects. * @return {@code true} if this {@code LinkedList} is modified, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean addAll(Collection<? extends E> collection) { @@ -327,8 +321,11 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements if (adding == 0) { return false; } + Collection<? extends E> elements = (collection == this) ? + new ArrayList<E>(collection) : collection; + Link<E> previous = voidLink.previous; - for (E e : collection) { + for (E e : elements) { Link<E> newLink = new Link<E>(e, previous, null); previous.next = newLink; previous = newLink; @@ -342,10 +339,9 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Adds the specified object at the beginning of this {@code LinkedList}. - * + * * @param object * the object to add. - * @since Android 1.0 */ public void addFirst(E object) { Link<E> oldFirst = voidLink.next; @@ -358,10 +354,9 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Adds the specified object at the end of this {@code LinkedList}. - * + * * @param object * the object to add. - * @since Android 1.0 */ public void addLast(E object) { Link<E> oldLast = voidLink.previous; @@ -374,10 +369,9 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Removes all elements from this {@code LinkedList}, leaving it empty. - * + * * @see List#isEmpty * @see #size - * @since Android 1.0 */ @Override public void clear() { @@ -392,10 +386,9 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Returns a new {@code LinkedList} with the same elements and size as this * {@code LinkedList}. - * + * * @return a shallow copy of this {@code LinkedList}. * @see java.lang.Cloneable - * @since Android 1.0 */ @SuppressWarnings("unchecked") @Override @@ -415,12 +408,11 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Searches this {@code LinkedList} for the specified object. - * + * * @param object * the object to search for. * @return {@code true} if {@code object} is an element of this * {@code LinkedList}, {@code false} otherwise - * @since Android 1.0 */ @Override public boolean contains(Object object) { @@ -463,11 +455,10 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Returns the first element in this {@code LinkedList}. - * + * * @return the first element. * @throws NoSuchElementException * if this {@code LinkedList} is empty. - * @since Android 1.0 */ public E getFirst() { Link<E> first = voidLink.next; @@ -479,11 +470,10 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Returns the last element in this {@code LinkedList}. - * + * * @return the last element * @throws NoSuchElementException * if this {@code LinkedList} is empty - * @since Android 1.0 */ public E getLast() { Link<E> last = voidLink.previous; @@ -520,12 +510,11 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Searches this {@code LinkedList} for the specified object and returns the * index of the last occurrence. - * + * * @param object * the object to search for * @return the index of the last occurrence of the object, or -1 if it was * not found. - * @since Android 1.0 */ @Override public int lastIndexOf(Object object) { @@ -555,14 +544,13 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements * Returns a ListIterator on the elements of this {@code LinkedList}. The * elements are iterated in the same order that they occur in the * {@code LinkedList}. The iteration starts at the specified location. - * + * * @param location * the index at which to start the iteration * @return a ListIterator on the elements of this {@code LinkedList} * @throws IndexOutOfBoundsException * if {@code location < 0 || >= size()} * @see ListIterator - * @since Android 1.0 */ @Override public ListIterator<E> listIterator(int location) { @@ -571,13 +559,12 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Removes the object at the specified location from this {@code LinkedList}. - * + * * @param location * the index of the object to remove * @return the removed object * @throws IndexOutOfBoundsException * if {@code location < 0 || >= size()} - * @since Android 1.0 */ @Override public E remove(int location) { @@ -629,11 +616,10 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Removes the first object from this {@code LinkedList}. - * + * * @return the removed object. * @throws NoSuchElementException * if this {@code LinkedList} is empty. - * @since Android 1.0 */ public E removeFirst() { Link<E> first = voidLink.next; @@ -650,11 +636,10 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Removes the last object from this {@code LinkedList}. - * + * * @return the removed object. * @throws NoSuchElementException * if this {@code LinkedList} is empty. - * @since Android 1.0 */ public E removeLast() { Link<E> last = voidLink.previous; @@ -672,7 +657,7 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Replaces the element at the specified location in this {@code LinkedList} * with the specified object. - * + * * @param location * the index at which to put the specified object. * @param object @@ -684,7 +669,6 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements * if an object cannot be added to this list. * @throws IndexOutOfBoundsException * if {@code location < 0 || >= size()} - * @since Android 1.0 */ @Override public E set(int location, E object) { @@ -708,15 +692,14 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Returns the number of elements in this {@code LinkedList}. - * + * * @return the number of elements in this {@code LinkedList}. - * @since Android 1.0 */ @Override public int size() { return size; } - + public boolean offer(E o) { add(o); return true; @@ -742,9 +725,8 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements /** * Returns a new array containing all elements contained in this * {@code LinkedList}. - * + * * @return an array of the elements from this {@code LinkedList}. - * @since Android 1.0 */ @Override public Object[] toArray() { @@ -765,14 +747,13 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements * type is created. If the specified array is used and is larger than this * {@code LinkedList}, the array element following the collection elements * is set to null. - * + * * @param contents * the array. * @return an array of the elements from this {@code LinkedList}. * @throws ArrayStoreException * if the type of an element in this {@code LinkedList} cannot * be stored in the type of the specified array. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -784,7 +765,7 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements } Link<E> link = voidLink.next; while (link != voidLink) { - contents[index++] = (T)link.data; + contents[index++] = (T) link.data; link = link.next; } if (index < contents.length) { @@ -810,7 +791,7 @@ public class LinkedList<E> extends AbstractSequentialList<E> implements voidLink = new Link<E>(null, null, null); Link<E> link = voidLink; for (int i = size; --i >= 0;) { - Link<E> nextLink = new Link<E>((E)stream.readObject(), link, null); + Link<E> nextLink = new Link<E>((E) stream.readObject(), link, null); link.next = nextLink; link = nextLink; } diff --git a/luni/src/main/java/java/util/List.java b/luni/src/main/java/java/util/List.java index d95b2d5..68e1ad9 100644 --- a/luni/src/main/java/java/util/List.java +++ b/luni/src/main/java/java/util/List.java @@ -23,8 +23,6 @@ package java.util; * element in the {@code List} has an index. Each element can thus be accessed by its * index, with the first index being zero. Normally, {@code List}s allow duplicate * elements, as compared to Sets, where elements have to be unique. - * - * @since Android 1.0 */ public interface List<E> extends Collection<E> { /** @@ -39,16 +37,15 @@ public interface List<E> extends Collection<E> { * the index at which to insert. * @param object * the object to add. - * @exception UnsupportedOperationException - * when adding to this {@code List} is not supported. - * @exception ClassCastException - * when the class of the object is inappropriate for this + * @throws UnsupportedOperationException + * if adding to this {@code List} is not supported. + * @throws ClassCastException + * if the class of the object is inappropriate for this * {@code List}. - * @exception IllegalArgumentException - * when the object cannot be added to this {@code List}. - * @exception IndexOutOfBoundsException - * when {@code location < 0 || location > size()} - * @since Android 1.0 + * @throws IllegalArgumentException + * if the object cannot be added to this {@code List}. + * @throws IndexOutOfBoundsException + * if {@code location < 0 || location > size()} */ public void add(int location, E object); @@ -58,14 +55,13 @@ public interface List<E> extends Collection<E> { * @param object * the object to add. * @return always true. - * @exception UnsupportedOperationException - * when adding to this {@code List} is not supported. - * @exception ClassCastException - * when the class of the object is inappropriate for this + * @throws UnsupportedOperationException + * if adding to this {@code List} is not supported. + * @throws ClassCastException + * if the class of the object is inappropriate for this * {@code List}. - * @exception IllegalArgumentException - * when the object cannot be added to this {@code List}. - * @since Android 1.0 + * @throws IllegalArgumentException + * if the object cannot be added to this {@code List}. */ public boolean add(E object); @@ -80,16 +76,15 @@ public interface List<E> extends Collection<E> { * the collection of objects to be inserted. * @return true if this {@code List} has been modified through the insertion, false * otherwise (i.e. if the passed collection was empty). - * @exception UnsupportedOperationException - * when adding to this {@code List} is not supported. - * @exception ClassCastException - * when the class of an object is inappropriate for this + * @throws UnsupportedOperationException + * if adding to this {@code List} is not supported. + * @throws ClassCastException + * if the class of an object is inappropriate for this * {@code List}. - * @exception IllegalArgumentException - * when an object cannot be added to this {@code List}. - * @exception IndexOutOfBoundsException - * when {@code location < 0 || > size()} - * @since Android 1.0 + * @throws IllegalArgumentException + * if an object cannot be added to this {@code List}. + * @throws IndexOutOfBoundsException + * if {@code location < 0 || > size()} */ public boolean addAll(int location, Collection<? extends E> collection); @@ -102,25 +97,23 @@ public interface List<E> extends Collection<E> { * the collection of objects. * @return {@code true} if this {@code List} is modified, {@code false} otherwise * (i.e. if the passed collection was empty). - * @exception UnsupportedOperationException - * when adding to this {@code List} is not supported. - * @exception ClassCastException - * when the class of an object is inappropriate for this + * @throws UnsupportedOperationException + * if adding to this {@code List} is not supported. + * @throws ClassCastException + * if the class of an object is inappropriate for this * {@code List}. - * @exception IllegalArgumentException - * when an object cannot be added to this {@code List}. - * @since Android 1.0 + * @throws IllegalArgumentException + * if an object cannot be added to this {@code List}. */ public boolean addAll(Collection<? extends E> collection); /** * Removes all elements from this {@code List}, leaving it empty. * - * @exception UnsupportedOperationException - * when removing from this {@code List} is not supported. + * @throws UnsupportedOperationException + * if removing from this {@code List} is not supported. * @see #isEmpty * @see #size - * @since Android 1.0 */ public void clear(); @@ -131,7 +124,6 @@ public interface List<E> extends Collection<E> { * the object to search for. * @return {@code true} if object is an element of this {@code List}, {@code false} * otherwise - * @since Android 1.0 */ public boolean contains(Object object); @@ -143,7 +135,6 @@ public interface List<E> extends Collection<E> { * the collection of objects * @return {@code true} if all objects in the specified collection are * elements of this {@code List}, {@code false} otherwise. - * @since Android 1.0 */ public boolean containsAll(Collection<?> collection); @@ -158,7 +149,6 @@ public interface List<E> extends Collection<E> { * @return boolean {@code true} if the object is the same as this object, * and {@code false} if it is different from this object. * @see #hashCode - * @since Android 1.0 */ public boolean equals(Object object); @@ -168,9 +158,8 @@ public interface List<E> extends Collection<E> { * @param location * the index of the element to return. * @return the element at the specified location. - * @exception IndexOutOfBoundsException - * when {@code location < 0 || >= size()} - * @since Android 1.0 + * @throws IndexOutOfBoundsException + * if {@code location < 0 || >= size()} */ public E get(int location); @@ -179,7 +168,6 @@ public interface List<E> extends Collection<E> { * element' hashcode and its position in the {@code List} into account. * * @return the hash code of the {@code List}. - * @since Android 1.0 */ public int hashCode(); @@ -191,7 +179,6 @@ public interface List<E> extends Collection<E> { * the object to search for. * @return the index of the first occurrence of the object or -1 if the * object was not found. - * @since Android 1.0 */ public int indexOf(Object object); @@ -201,7 +188,6 @@ public interface List<E> extends Collection<E> { * @return {@code true} if this {@code List} has no elements, {@code false} * otherwise. * @see #size - * @since Android 1.0 */ public boolean isEmpty(); @@ -211,7 +197,6 @@ public interface List<E> extends Collection<E> { * * @return an iterator on the elements of this {@code List}. * @see Iterator - * @since Android 1.0 */ public Iterator<E> iterator(); @@ -223,7 +208,6 @@ public interface List<E> extends Collection<E> { * the object to search for. * @return the index of the last occurrence of the object, or -1 if the * object was not found. - * @since Android 1.0 */ public int lastIndexOf(Object object); @@ -234,7 +218,6 @@ public interface List<E> extends Collection<E> { * @return a {@code List} iterator on the elements of this {@code List} * * @see ListIterator - * @since Android 1.0 */ public ListIterator<E> listIterator(); @@ -246,10 +229,9 @@ public interface List<E> extends Collection<E> { * @param location * the index at which to start the iteration. * @return a list iterator on the elements of this {@code List}. - * @exception IndexOutOfBoundsException - * when {@code location < 0 || location > size()} + * @throws IndexOutOfBoundsException + * if {@code location < 0 || location > size()} * @see ListIterator - * @since Android 1.0 */ public ListIterator<E> listIterator(int location); @@ -259,11 +241,10 @@ public interface List<E> extends Collection<E> { * @param location * the index of the object to remove. * @return the removed object. - * @exception UnsupportedOperationException - * when removing from this {@code List} is not supported. - * @exception IndexOutOfBoundsException - * when {@code location < 0 || >= size()} - * @since Android 1.0 + * @throws UnsupportedOperationException + * if removing from this {@code List} is not supported. + * @throws IndexOutOfBoundsException + * if {@code location < 0 || >= size()} */ public E remove(int location); @@ -274,9 +255,8 @@ public interface List<E> extends Collection<E> { * the object to remove. * @return true if this {@code List} was modified by this operation, false * otherwise. - * @exception UnsupportedOperationException - * when removing from this {@code List} is not supported. - * @since Android 1.0 + * @throws UnsupportedOperationException + * if removing from this {@code List} is not supported. */ public boolean remove(Object object); @@ -287,9 +267,8 @@ public interface List<E> extends Collection<E> { * @param collection * the collection of objects to remove. * @return {@code true} if this {@code List} is modified, {@code false} otherwise. - * @exception UnsupportedOperationException - * when removing from this {@code List} is not supported. - * @since Android 1.0 + * @throws UnsupportedOperationException + * if removing from this {@code List} is not supported. */ public boolean removeAll(Collection<?> collection); @@ -300,9 +279,8 @@ public interface List<E> extends Collection<E> { * @param collection * the collection of objects to retain. * @return {@code true} if this {@code List} is modified, {@code false} otherwise. - * @exception UnsupportedOperationException - * when removing from this {@code List} is not supported. - * @since Android 1.0 + * @throws UnsupportedOperationException + * if removing from this {@code List} is not supported. */ public boolean retainAll(Collection<?> collection); @@ -315,16 +293,15 @@ public interface List<E> extends Collection<E> { * @param object * the object to insert. * @return the previous element at the index. - * @exception UnsupportedOperationException - * when replacing elements in this {@code List} is not supported. - * @exception ClassCastException - * when the class of an object is inappropriate for this + * @throws UnsupportedOperationException + * if replacing elements in this {@code List} is not supported. + * @throws ClassCastException + * if the class of an object is inappropriate for this * {@code List}. - * @exception IllegalArgumentException - * when an object cannot be added to this {@code List}. - * @exception IndexOutOfBoundsException - * when {@code location < 0 || >= size()} - * @since Android 1.0 + * @throws IllegalArgumentException + * if an object cannot be added to this {@code List}. + * @throws IndexOutOfBoundsException + * if {@code location < 0 || >= size()} */ public E set(int location, E object); @@ -332,7 +309,6 @@ public interface List<E> extends Collection<E> { * Returns the number of elements in this {@code List}. * * @return the number of elements in this {@code List}. - * @since Android 1.0 */ public int size(); @@ -346,10 +322,9 @@ public interface List<E> extends Collection<E> { * @param end * the index one past the end of the sublist. * @return a list of a portion of this {@code List}. - * @exception IndexOutOfBoundsException - * when {@code start < 0, start > end} or {@code end > + * @throws IndexOutOfBoundsException + * if {@code start < 0, start > end} or {@code end > * size()} - * @since Android 1.0 */ public List<E> subList(int start, int end); @@ -357,7 +332,6 @@ public interface List<E> extends Collection<E> { * Returns an array containing all elements contained in this {@code List}. * * @return an array of the elements from this {@code List}. - * @since Android 1.0 */ public Object[] toArray(); @@ -371,10 +345,9 @@ public interface List<E> extends Collection<E> { * @param array * the array. * @return an array of the elements from this {@code List}. - * @exception ArrayStoreException - * when the type of an element in this {@code List} cannot be stored + * @throws ArrayStoreException + * if the type of an element in this {@code List} cannot be stored * in the type of the specified array. - * @since Android 1.0 */ public <T> T[] toArray(T[] array); } diff --git a/luni/src/main/java/java/util/ListIterator.java b/luni/src/main/java/java/util/ListIterator.java index 6ce94c3..1c62a22 100644 --- a/luni/src/main/java/java/util/ListIterator.java +++ b/luni/src/main/java/java/util/ListIterator.java @@ -21,8 +21,6 @@ package java.util; /** * An ListIterator is used to sequence over a List of objects. ListIterator can * move backwards or forwards through the list. - * - * @since Android 1.0 */ public interface ListIterator<E> extends Iterator<E> { @@ -38,7 +36,6 @@ public interface ListIterator<E> extends Iterator<E> { * if the class of the object is inappropriate for the list. * @throws IllegalArgumentException * if the object cannot be added to the list. - * @since Android 1.0 */ void add(E object); @@ -47,7 +44,6 @@ public interface ListIterator<E> extends Iterator<E> { * * @return {@code true} if there are more elements, {@code false} otherwise. * @see #next - * @since Android 1.0 */ public boolean hasNext(); @@ -57,7 +53,6 @@ public interface ListIterator<E> extends Iterator<E> { * @return {@code true} if there are previous elements, {@code false} * otherwise. * @see #previous - * @since Android 1.0 */ public boolean hasPrevious(); @@ -68,7 +63,6 @@ public interface ListIterator<E> extends Iterator<E> { * @throws NoSuchElementException * if there are no more elements. * @see #hasNext - * @since Android 1.0 */ public E next(); @@ -80,7 +74,6 @@ public interface ListIterator<E> extends Iterator<E> { * @throws NoSuchElementException * if there are no more elements. * @see #next - * @since Android 1.0 */ public int nextIndex(); @@ -91,7 +84,6 @@ public interface ListIterator<E> extends Iterator<E> { * @throws NoSuchElementException * if there are no previous elements. * @see #hasPrevious - * @since Android 1.0 */ public E previous(); @@ -103,7 +95,6 @@ public interface ListIterator<E> extends Iterator<E> { * @throws NoSuchElementException * if there are no previous elements. * @see #previous - * @since Android 1.0 */ public int previousIndex(); @@ -117,7 +108,6 @@ public interface ListIterator<E> extends Iterator<E> { * if {@code next} or {@code previous} have not been called, or * {@code remove} or {@code add} have already been called after * the last call to {@code next} or {@code previous}. - * @since Android 1.0 */ public void remove(); @@ -137,7 +127,6 @@ public interface ListIterator<E> extends Iterator<E> { * if {@code next} or {@code previous} have not been called, or * {@code remove} or {@code add} have already been called after * the last call to {@code next} or {@code previous}. - * @since Android 1.0 */ void set(E object); } diff --git a/luni/src/main/java/java/util/ListResourceBundle.java b/luni/src/main/java/java/util/ListResourceBundle.java index 20d64ac..6206ee6 100644 --- a/luni/src/main/java/java/util/ListResourceBundle.java +++ b/luni/src/main/java/java/util/ListResourceBundle.java @@ -17,22 +17,19 @@ package java.util; - /** * {@code ListResourceBundle} is the abstract superclass of classes which provide * resources by implementing the {@code getContents()} method to return * the list of resources. - * + * * @see ResourceBundle - * @since Android 1.0 + * @since 1.1 */ public abstract class ListResourceBundle extends ResourceBundle { - Hashtable<String, Object> table; + HashMap<String, Object> table; /** * Constructs a new instance of this class. - * - * @since Android 1.0 */ public ListResourceBundle() { super(); @@ -43,73 +40,81 @@ public abstract class ListResourceBundle extends ResourceBundle { * {@code ListResourceBundle}. Each element in the array is an array of two * elements, the first is the resource key string and the second is the * resource. - * + * * @return a {@code Object} array containing the resources. - * @since Android 1.0 */ protected abstract Object[][] getContents(); /** * Returns the names of the resources contained in this {@code ListResourceBundle}. - * + * * @return an {@code Enumeration} of the resource names. - * @since Android 1.0 */ @Override public Enumeration<String> getKeys() { - if (table == null) { - initializeTable(); - } - if (parent == null) { - return table.keys(); - } - return new Enumeration<String>() { - Enumeration<String> local = table.keys(); + initializeTable(); + if (parent != null) { + return new Enumeration<String>() { + Iterator<String> local = table.keySet().iterator(); - Enumeration<String> pEnum = parent.getKeys(); + Enumeration<String> pEnum = parent.getKeys(); - String nextElement; + String nextElement; - private boolean findNext() { - if (nextElement != null) { - return true; + private boolean findNext() { + if (nextElement != null) { + return true; + } + while (pEnum.hasMoreElements()) { + String next = pEnum.nextElement(); + if (!table.containsKey(next)) { + nextElement = next; + return true; + } + } + return false; } - while (pEnum.hasMoreElements()) { - String next = pEnum.nextElement(); - if (!table.containsKey(next)) { - nextElement = next; + + public boolean hasMoreElements() { + if (local.hasNext()) { return true; } + return findNext(); } - return false; - } - public boolean hasMoreElements() { - if (local.hasMoreElements()) { - return true; + public String nextElement() { + if (local.hasNext()) { + return local.next(); + } + if (findNext()) { + String result = nextElement; + nextElement = null; + return result; + } + // Cause an exception + return pEnum.nextElement(); } - return findNext(); - } + }; + } else { + return new Enumeration<String>() { + Iterator<String> it = table.keySet().iterator(); - public String nextElement() { - if (local.hasMoreElements()) { - return local.nextElement(); + public boolean hasMoreElements() { + return it.hasNext(); } - if (findNext()) { - String result = nextElement; - nextElement = null; - return result; + + public String nextElement() { + return it.next(); } - // Cause an exception - return pEnum.nextElement(); - } - }; + }; + } } @Override public final Object handleGetObject(String key) { - if (table == null) { - initializeTable(); + initializeTable(); + if (key == null) { + throw new NullPointerException(); } return table.get(key); } @@ -117,9 +122,12 @@ public abstract class ListResourceBundle extends ResourceBundle { private synchronized void initializeTable() { if (table == null) { Object[][] contents = getContents(); - table = new Hashtable<String, Object>(contents.length / 3 * 4 + 3); - for (int i = 0; i < contents.length; i++) { - table.put((String)contents[i][0], contents[i][1]); + table = new HashMap<String, Object>(contents.length / 3 * 4 + 3); + for (Object[] content : contents) { + if (content[0] == null || content[1] == null) { + throw new NullPointerException(); + } + table.put((String) content[0], content[1]); } } } diff --git a/luni/src/main/java/java/util/Locale.java b/luni/src/main/java/java/util/Locale.java index bbf7239..b4558aa 100644 --- a/luni/src/main/java/java/util/Locale.java +++ b/luni/src/main/java/java/util/Locale.java @@ -17,7 +17,8 @@ package java.util; -import java.io.File; +// BEGIN android-changed +// import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -25,19 +26,14 @@ import java.io.ObjectStreamField; import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; +// import java.util.zip.ZipEntry; +// import java.util.zip.ZipFile; -// BEGIN android-removed -//import org.apache.harmony.luni.internal.locale.Country; -//import org.apache.harmony.luni.internal.locale.Language; -// END android-removed import org.apache.harmony.luni.util.PriviAction; import org.apache.harmony.luni.util.Util; -//BEGIN android-added import com.ibm.icu4jni.util.Resources; -// END android-added +// END android-changed /** * {@code Locale} represents a language/country/variant combination. It is an identifier @@ -45,15 +41,14 @@ import com.ibm.icu4jni.util.Resources; * The language codes are two letter lowercase codes as defined by ISO-639. The * country codes are three letter uppercase codes as defined by ISO-3166. The * variant codes are unspecified. - * + * * @see ResourceBundle - * @since Android 1.0 */ public final class Locale implements Cloneable, Serializable { - + private static final long serialVersionUID = 9149081749638150636L; - private static Locale[] availableLocales; + private static volatile Locale[] availableLocales; // Initialize a default which is used during static // initialization of the default for the platform. @@ -61,200 +56,159 @@ public final class Locale implements Cloneable, Serializable { /** * Locale constant for en_CA. - * - * @since Android 1.0 */ public static final Locale CANADA = new Locale("en", "CA"); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for fr_CA. - * - * @since Android 1.0 */ public static final Locale CANADA_FRENCH = new Locale("fr", "CA"); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for zh_CN. - * - * @since Android 1.0 */ public static final Locale CHINA = new Locale("zh", "CN"); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for zh. - * - * @since Android 1.0 */ - public static final Locale CHINESE = new Locale("zh", ""); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale CHINESE = new Locale("zh", ""); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for en. - * - * @since Android 1.0 */ public static final Locale ENGLISH = new Locale("en", ""); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for fr_FR. - * - * @since Android 1.0 */ - public static final Locale FRANCE = new Locale("fr", "FR"); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale FRANCE = new Locale("fr", "FR"); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for fr. - * - * @since Android 1.0 */ - public static final Locale FRENCH = new Locale("fr", ""); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale FRENCH = new Locale("fr", ""); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for de. - * - * @since Android 1.0 */ public static final Locale GERMAN = new Locale("de", ""); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for de_DE. - * - * @since Android 1.0 */ public static final Locale GERMANY = new Locale("de", "DE"); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for it. - * - * @since Android 1.0 */ public static final Locale ITALIAN = new Locale("it", ""); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for it_IT. - * - * @since Android 1.0 */ public static final Locale ITALY = new Locale("it", "IT"); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for ja_JP. - * - * @since Android 1.0 */ - public static final Locale JAPAN = new Locale("ja", "JP"); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale JAPAN = new Locale("ja", "JP"); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for ja. - * - * @since Android 1.0 */ - public static final Locale JAPANESE = new Locale("ja", ""); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale JAPANESE = new Locale("ja", ""); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for ko_KR. - * - * @since Android 1.0 */ - public static final Locale KOREA = new Locale("ko", "KR"); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale KOREA = new Locale("ko", "KR"); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for ko. - * - * @since Android 1.0 */ - public static final Locale KOREAN = new Locale("ko", ""); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale KOREAN = new Locale("ko", ""); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for zh_CN. - * - * @since Android 1.0 */ - public static final Locale PRC = new Locale("zh", "CN"); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale PRC = new Locale("zh", "CN"); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for zh_CN. - * - * @since Android 1.0 */ - public static final Locale SIMPLIFIED_CHINESE = new Locale("zh", "CN"); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale SIMPLIFIED_CHINESE = new Locale("zh", "CN"); //$NON-NLS-1$//$NON-NLS-2$ /** * Locale constant for zh_TW. - * - * @since Android 1.0 */ public static final Locale TAIWAN = new Locale("zh", "TW"); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for zh_TW. - * - * @since Android 1.0 */ public static final Locale TRADITIONAL_CHINESE = new Locale("zh", "TW"); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for en_GB. - * - * @since Android 1.0 */ public static final Locale UK = new Locale("en", "GB"); //$NON-NLS-1$ //$NON-NLS-2$ /** * Locale constant for en_US. - * - * @since Android 1.0 */ - public static final Locale US = new Locale("en", "US"); //$NON-NLS-1$//$NON-NLS-2$ + public static final Locale US = new Locale("en", "US"); //$NON-NLS-1$//$NON-NLS-2$ private static final PropertyPermission setLocalePermission = new PropertyPermission( - "user.language", "write"); //$NON-NLS-1$//$NON-NLS-2$ + "user.language", "write"); //$NON-NLS-1$//$NON-NLS-2$ static { String language = AccessController .doPrivileged(new PriviAction<String>("user.language", "en")); //$NON-NLS-1$ //$NON-NLS-2$ // BEGIN android-changed - String region = AccessController - .doPrivileged(new PriviAction<String>("user.region", "US")); //$NON-NLS-1$ //$NON-NLS-2$ + String region = AccessController.doPrivileged(new PriviAction<String>( + "user.region", "US")); //$NON-NLS-1$ //$NON-NLS-2$ // END android-changed - String variant = AccessController - .doPrivileged(new PriviAction<String>("user.variant", "")); //$NON-NLS-1$ //$NON-NLS-2$ + String variant = AccessController.doPrivileged(new PriviAction<String>( + "user.variant", "")); //$NON-NLS-1$ //$NON-NLS-2$ defaultLocale = new Locale(language, region, variant); } - + private transient String countryCode; private transient String languageCode; private transient String variantCode; - /** - * Constructs a default which is used during static initialization of the - * default for the platform. - */ - private Locale() { - languageCode = "en"; //$NON-NLS-1$ - countryCode = "US"; //$NON-NLS-1$ - variantCode = ""; //$NON-NLS-1$ - } + // BEGIN android-removed + // private transient ULocale uLocale; + // END android-removed + + /** + * Constructs a default which is used during static initialization of the + * default for the platform. + */ + private Locale() { + languageCode = "en"; //$NON-NLS-1$ + countryCode = "US"; //$NON-NLS-1$ + variantCode = ""; //$NON-NLS-1$ + } /** * Constructs a new {@code Locale} using the specified language. - * + * * @param language * the language this {@code Locale} represents. - * - * @since Android 1.0 */ public Locale(String language) { - this(language, "", ""); //$NON-NLS-1$//$NON-NLS-2$ + this(language, "", ""); //$NON-NLS-1$//$NON-NLS-2$ } /** * Constructs a new {@code Locale} using the specified language and country codes. - * + * * @param language * the language this {@code Locale} represents. * @param country * the country this {@code Locale} represents. - * @since Android 1.0 */ public Locale(String language, String country) { this(language, country, ""); //$NON-NLS-1$ @@ -263,7 +217,7 @@ public final class Locale implements Cloneable, Serializable { /** * Constructs a new {@code Locale} using the specified language, country, and * variant codes. - * + * * @param language * the language this {@code Locale} represents. * @param country @@ -273,13 +227,22 @@ public final class Locale implements Cloneable, Serializable { * @throws NullPointerException * if {@code language}, {@code country}, or * {@code variant} is {@code null}. - * @since Android 1.0 */ public Locale(String language, String country, String variant) { if (language == null || country == null || variant == null) { throw new NullPointerException(); } + if(language.length() == 0 && country.length() == 0){ + languageCode = ""; + countryCode = ""; + variantCode = variant; + return; + } + // BEGIN android-changed + // this.uLocale = new ULocale(language, country, variant); + // languageCode = uLocale.getLanguage(); languageCode = Util.toASCIILowerCase(language); + // END android-changed // Map new language codes to the obsolete language // codes so the correct resource bundles will be used. if (languageCode.equals("he")) {//$NON-NLS-1$ @@ -291,18 +254,21 @@ public final class Locale implements Cloneable, Serializable { } // countryCode is defined in ASCII character set + // BEGIN android-changed + // countryCode = country.length()!=0?uLocale.getCountry():""; countryCode = Util.toASCIIUpperCase(country); + // END android-changed + // Work around for be compatible with RI variantCode = variant; } /** * Returns a new {@code Locale} with the same language, country and variant codes as * this {@code Locale}. - * + * * @return a shallow copy of this {@code Locale}. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -317,13 +283,12 @@ public final class Locale implements Cloneable, Serializable { * Compares the specified object to this {@code Locale} and returns whether they are * equal. The object must be an instance of {@code Locale} and have the same * language, country and variant. - * + * * @param object * the object to compare with this object. * @return {@code true} if the specified object is equal to this {@code Locale}, * {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -347,13 +312,8 @@ public final class Locale implements Cloneable, Serializable { // final String classPrefix = prefix.substring(last + 1, length); // Set<String> result = new HashSet<String>(); // StringTokenizer paths = new StringTokenizer(System.getProperty( - // // BEGIN android-removed - // // "org.apache.harmony.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$ - // // END android-removed - // // BEGIN android-added - // "java.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$ - // // END android-added - // "path.separator", ";")); //$NON-NLS-1$//$NON-NLS-2$ + // "org.apache.harmony.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$ + // "path.separator", ";")); //$NON-NLS-1$//$NON-NLS-2$ // while (paths.hasMoreTokens()) { // String nextToken = paths.nextToken(); // File directory = new File(nextToken); @@ -378,12 +338,13 @@ public final class Locale implements Cloneable, Serializable { // String name = list[i]; // if (name.startsWith(classPrefix) // && name.endsWith(".class")) { //$NON-NLS-1$ - // result.add(name.substring(0, + // result + // .add(name.substring(0, // name.length() - 6)); // } // } // } - // + // // } else { // // Handle ZIP/JAR files. // try { @@ -394,25 +355,26 @@ public final class Locale implements Cloneable, Serializable { // String name = e.getName(); // if (name.startsWith(prefix) // && name.endsWith(".class")) {//$NON-NLS-1$ - // result.add(name.substring(last+1, name.length() - 6)); + // result.add(name.substring(last + 1, name + // .length() - 6)); // } // } // zip.close(); // } catch (IOException e) { - // // Empty + // // Empty // } // } // } // } // Locale[] locales = new Locale[result.size()]; // int i = 0; - // for (String name: result) { + // for (String name : result) { // int index = name.indexOf('_'); // int nextIndex = name.indexOf('_', index + 1); // if (nextIndex == -1) { - // locales[i++] = new Locale(name - // .substring(index + 1, name.length()), ""); //$NON-NLS-1$ - // }else{ + // locales[i++] = new Locale(name.substring(index + 1, name + // .length()), ""); //$NON-NLS-1$ + // } else { // String language = name.substring(index + 1, nextIndex); // String variant; // if ((index = name.indexOf('_', nextIndex + 1)) == -1) { @@ -437,7 +399,7 @@ public final class Locale implements Cloneable, Serializable { String s = locales[i]; int first = s.indexOf('_'); int second = s.indexOf('_', first + 1); - + if (first == -1) { // Language only temp.add(new Locale(s)); @@ -454,37 +416,32 @@ public final class Locale implements Cloneable, Serializable { } // END android-added - /** + /** * Gets the list of installed {@code Locale}. At least a {@code Locale} that is equal to * {@code Locale.US} must be contained in this array. - * + * * @return an array of {@code Locale}s. - * @since Android 1.0 - */ - public static Locale[] getAvailableLocales() { + */ + public static Locale[] getAvailableLocales() { + // BEGIN android-changed + // ULocale[] ulocales = ULocale.getAvailableLocales(); + // Locale[] locales = new Locale[ulocales.length]; + // for (int i = 0; i < locales.length; i++) { + // locales[i] = ulocales[i].toLocale(); + // } + // return locales; if (availableLocales == null) { - // BEGIN android-removed - // availableLocales = AccessController - // .doPrivileged(new PrivilegedAction<Locale[]>() { - // public Locale[] run() { - // return find("org/apache/harmony/luni/internal/locale/Locale_"); //$NON-NLS-1$ - // } - // }); - // END android-removed - - // BEGIN android-added availableLocales = find(); - // END android-added } return availableLocales.clone(); - } + // END android-changed + } /** * Gets the country code for this {@code Locale} or an empty string of no country * was set. - * + * * @return a country code. - * @since Android 1.0 */ public String getCountry() { return countryCode; @@ -492,9 +449,8 @@ public final class Locale implements Cloneable, Serializable { /** * Gets the default {@code Locale}. - * + * * @return the default {@code Locale}. - * @since Android 1.0 */ public static Locale getDefault() { return defaultLocale; @@ -504,9 +460,8 @@ public final class Locale implements Cloneable, Serializable { * Gets the full country name in the default {@code Locale} for the country code of * this {@code Locale}. If there is no matching country name, the country code is * returned. - * + * * @return a country name. - * @since Android 1.0 */ public final String getDisplayCountry() { return getDisplayCountry(getDefault()); @@ -516,22 +471,21 @@ public final class Locale implements Cloneable, Serializable { * Gets the full country name in the specified {@code Locale} for the country code * of this {@code Locale}. If there is no matching country name, the country code is * returned. - * + * * @param locale * the {@code Locale} for which the display name is retrieved. * @return a country name. - * @since Android 1.0 */ - public String getDisplayCountry(Locale locale) { + public String getDisplayCountry(Locale locale) { + // BEGIN android-changed + // return ULocale.forLocale(this).getDisplayCountry(ULocale.forLocale(locale)); if (countryCode.length() == 0) { return countryCode; } try { // First try the specified locale ResourceBundle bundle = getBundle("Country", locale); //$NON-NLS-1$ - // BEGIN android-changed String result = bundle.getString(this.toString()); - // END android-changed if (result != null) { return result; } @@ -543,15 +497,15 @@ public final class Locale implements Cloneable, Serializable { } catch (MissingResourceException e) { return countryCode; } - } + // END android-changed + } /** * Gets the full language name in the default {@code Locale} for the language code * of this {@code Locale}. If there is no matching language name, the language code * is returned. - * + * * @return a language name. - * @since Android 1.0 */ public final String getDisplayLanguage() { return getDisplayLanguage(getDefault()); @@ -561,22 +515,21 @@ public final class Locale implements Cloneable, Serializable { * Gets the full language name in the specified {@code Locale} for the language code * of this {@code Locale}. If there is no matching language name, the language code * is returned. - * + * * @param locale * the {@code Locale} for which the display name is retrieved. * @return a language name. - * @since Android 1.0 */ - public String getDisplayLanguage(Locale locale) { + public String getDisplayLanguage(Locale locale) { + // BEGIN android-changed + // return ULocale.forLocale(this).getDisplayLanguage(ULocale.forLocale(locale)); if (languageCode.length() == 0) { return languageCode; } try { // First try the specified locale ResourceBundle bundle = getBundle("Language", locale); //$NON-NLS-1$ - // BEGIN android-changed String result = bundle.getString(this.toString()); - // END android-changed if (result != null) { return result; } @@ -588,14 +541,14 @@ public final class Locale implements Cloneable, Serializable { } catch (MissingResourceException e) { return languageCode; } - } + // END android-changed + } /** * Gets the full language, country, and variant names in the default {@code Locale} * for the codes of this {@code Locale}. - * + * * @return a {@code Locale} name. - * @since Android 1.0 */ public final String getDisplayName() { return getDisplayName(getDefault()); @@ -604,11 +557,10 @@ public final class Locale implements Cloneable, Serializable { /** * Gets the full language, country, and variant names in the specified * Locale for the codes of this {@code Locale}. - * + * * @param locale * the {@code Locale} for which the display name is retrieved. * @return a {@code Locale} name. - * @since Android 1.0 */ public String getDisplayName(Locale locale) { int count = 0; @@ -643,9 +595,8 @@ public final class Locale implements Cloneable, Serializable { * Gets the full variant name in the default {@code Locale} for the variant code of * this {@code Locale}. If there is no matching variant name, the variant code is * returned. - * + * * @return a variant name. - * @since Android 1.0 */ public final String getDisplayVariant() { return getDisplayVariant(getDefault()); @@ -655,41 +606,17 @@ public final class Locale implements Cloneable, Serializable { * Gets the full variant name in the specified {@code Locale} for the variant code * of this {@code Locale}. If there is no matching variant name, the variant code is * returned. - * + * * @param locale * the {@code Locale} for which the display name is retrieved. * @return a variant name. - * @since Android 1.0 */ - public String getDisplayVariant(Locale locale) { + public String getDisplayVariant(Locale locale) { + // BEGIN android-changed + // return ULocale.forLocale(this).getDisplayVariant(ULocale.forLocale(locale)); if (variantCode.length() == 0) { return variantCode; } -// BEGIN android-removed -// ResourceBundle bundle; -// try { -// bundle = getBundle("Variant", locale); //$NON-NLS-1$ -// } catch (MissingResourceException e) { -// return variantCode.replace('_', ','); -// } -// -// StringBuffer result = new StringBuffer(); -// StringTokenizer tokens = new StringTokenizer(variantCode, "_"); //$NON-NLS-1$ -// while (tokens.hasMoreTokens()) { -// String code, variant = tokens.nextToken(); -// try { -// code = bundle.getString(variant); -// } catch (MissingResourceException e) { -// code = variant; -// } -// result.append(code); -// if (tokens.hasMoreTokens()) { -// result.append(','); -// } -// } -// return result.toString(); -// END android-removed -// BEGIN android-added try { // First try the specified locale ResourceBundle bundle = getBundle("Variant", locale); //$NON-NLS-1$ @@ -705,105 +632,78 @@ public final class Locale implements Cloneable, Serializable { } catch (MissingResourceException e) { return variantCode; } -// END android-added - } + // END android-changed + } /** * Gets the three letter ISO country code which corresponds to the country * code for this {@code Locale}. - * + * * @return a three letter ISO language code. - * @exception MissingResourceException - * when there is no matching three letter ISO country code. - * @since Android 1.0 + * @throws MissingResourceException + * if there is no matching three letter ISO country code. */ - public String getISO3Country() throws MissingResourceException { + public String getISO3Country() throws MissingResourceException { + // BEGIN android-changed + // return ULocale.forLocale(this).getISO3Country(); if (countryCode.length() == 0) { return ""; //$NON-NLS-1$ } ResourceBundle bundle = getBundle("ISO3Countries", this); //$NON-NLS-1$ - // BEGIN android-changed return bundle.getString(this.toString()); // END android-changed - } + } /** * Gets the three letter ISO language code which corresponds to the language * code for this {@code Locale}. - * + * * @return a three letter ISO language code. - * @exception MissingResourceException - * when there is no matching three letter ISO language code. - * @since Android 1.0 + * @throws MissingResourceException + * if there is no matching three letter ISO language code. */ - public String getISO3Language() throws MissingResourceException { + public String getISO3Language() throws MissingResourceException { + // BEGIN android-changed + // return ULocale.forLocale(this).getISO3Language(); if (languageCode.length() == 0) { return ""; //$NON-NLS-1$ } ResourceBundle bundle = getBundle("ISO3Languages", this); //$NON-NLS-1$ - // BEGIN android-changed return bundle.getString(this.toString()); // END android-changed - } + } /** * Gets the list of two letter ISO country codes which can be used as the * country code for a {@code Locale}. - * + * * @return an array of strings. - * @since Android 1.0 */ public static String[] getISOCountries() { - // BEGIN android-removed - // ListResourceBundle bundle = new Country(); - // - // // To initialize the table - // Enumeration<String> keys = bundle.getKeys(); - // int size = bundle.table.size(); - // String[] result = new String[size]; - // int index = 0; - // while (keys.hasMoreElements()) { - // String element = keys.nextElement(); - // result[index++] = element; - // } - // return result; - // END android-removed - - // BEGIN android-added + // BEGIN android-changed + // return ULocale.getISOCountries(); return Resources.getISOCountries(); - // END android-added + // END android-changed } /** * Gets the list of two letter ISO language codes which can be used as the * language code for a {@code Locale}. - * + * * @return an array of strings. - * @since Android 1.0 - */ - public static String[] getISOLanguages() { - // BEGIN android-removed - // ListResourceBundle bundle = new Language(); - // Enumeration<String> keys = bundle.getKeys(); // to initialize the table - // String[] result = new String[bundle.table.size()]; - // int index = 0; - // while (keys.hasMoreElements()) { - // result[index++] = keys.nextElement(); - // } - // return result; - // END android-removed - - // BEGIN android-added + */ + public static String[] getISOLanguages() { + // BEGIN android-changed + // return ULocale.getISOLanguages(); return Resources.getISOLanguages(); - // END android-added - } + // END android-changed + } /** * Gets the language code for this {@code Locale} or the empty string of no language * was set. - * + * * @return a language code. - * @since Android 1.0 */ public String getLanguage() { return languageCode; @@ -812,9 +712,8 @@ public final class Locale implements Cloneable, Serializable { /** * Gets the variant code for this {@code Locale} or an empty {@code String} of no variant * was set. - * + * * @return a variant code. - * @since Android 1.0 */ public String getVariant() { return variantCode; @@ -823,10 +722,9 @@ public final class Locale implements Cloneable, Serializable { /** * Returns an integer hash code for the receiver. Objects which are equal * return the same value for this method. - * + * * @return the receiver's hash. * @see #equals - * @since Android 1.0 */ @Override public synchronized int hashCode() { @@ -836,13 +734,12 @@ public final class Locale implements Cloneable, Serializable { /** * Sets the default {@code Locale} to the specified {@code Locale}. - * + * * @param locale * the new default {@code Locale}. - * @exception SecurityException + * @throws SecurityException * if there is a {@code SecurityManager} in place which does not allow this * operation. - * @since Android 1.0 */ public synchronized static void setDefault(Locale locale) { if (locale != null) { @@ -864,11 +761,10 @@ public final class Locale implements Cloneable, Serializable { * between the language and the variant. the variant alone canot be defined * without a language and/or a country (in this case this method would * return the empty string). - * + * * Examples: "en", "en_US", "_US", "en__POSIX", "en_US_POSIX" - * + * * @return the string representation of this {@code Locale}. - * @since Android 1.0 */ @Override public final String toString() { @@ -878,7 +774,7 @@ public final class Locale implements Cloneable, Serializable { result.append('_'); result.append(countryCode); } - if (variantCode.length() > 0 && result.length() > 0 ) { + if (variantCode.length() > 0 && result.length() > 0) { if (0 == countryCode.length()) { result.append("__"); //$NON-NLS-1$ } else { @@ -889,14 +785,16 @@ public final class Locale implements Cloneable, Serializable { return result.toString(); } + // BEGIN android-added static ResourceBundle getBundle(final String clName, final Locale locale) { return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() { - public ResourceBundle run() { - return ResourceBundle.getBundle("org.apache.harmony.luni.internal.locale." //$NON-NLS-1$ - + clName, locale); - } - }); + public ResourceBundle run() { + return ResourceBundle.getBundle("org.apache.harmony.luni.internal.locale." //$NON-NLS-1$ + + clName, locale); + } + }); } + // END android-added private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("country", String.class), //$NON-NLS-1$ @@ -916,9 +814,8 @@ public final class Locale implements Cloneable, Serializable { private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { ObjectInputStream.GetField fields = stream.readFields(); - countryCode = (String) fields.get("country", ""); //$NON-NLS-1$//$NON-NLS-2$ - languageCode = (String) fields.get("language", ""); //$NON-NLS-1$//$NON-NLS-2$ - variantCode = (String) fields.get("variant", ""); //$NON-NLS-1$//$NON-NLS-2$ + countryCode = (String) fields.get("country", ""); //$NON-NLS-1$//$NON-NLS-2$ + languageCode = (String) fields.get("language", ""); //$NON-NLS-1$//$NON-NLS-2$ + variantCode = (String) fields.get("variant", ""); //$NON-NLS-1$//$NON-NLS-2$ } } - diff --git a/luni/src/main/java/java/util/Map.java b/luni/src/main/java/java/util/Map.java index d8b1e62..7509d1a 100644 --- a/luni/src/main/java/java/util/Map.java +++ b/luni/src/main/java/java/util/Map.java @@ -23,19 +23,15 @@ package java.util; * in which each key is mapped to a single value. The class of the objects * used as keys is declared when the {@code Map} is declared, as is the * class of the corresponding values. - * <p>A {@code Map} provides helper methods to iterate through all of the + * <p> + * A {@code Map} provides helper methods to iterate through all of the * keys contained in it, as well as various methods to access and update * the key/value pairs. - * </p> - * - * @since Android 1.0 */ public interface Map<K,V> { /** * {@code Map.Entry} is a key/value mapping contained in a {@code Map}. - * - * @since Android 1.0 */ public static interface Entry<K,V> { /** @@ -48,7 +44,6 @@ public interface Map<K,V> { * @return {@code true} if the specified {@code Object} is equal to this * {@code Map.Entry}, {@code false} otherwise. * @see #hashCode() - * @since Android 1.0 */ public boolean equals(Object object); @@ -56,7 +51,6 @@ public interface Map<K,V> { * Returns the key. * * @return the key - * @since Android 1.0 */ public K getKey(); @@ -64,7 +58,6 @@ public interface Map<K,V> { * Returns the value. * * @return the value - * @since Android 1.0 */ public V getValue(); @@ -74,7 +67,6 @@ public interface Map<K,V> { * * @return the receiver's hash code. * @see #equals(Object) - * @since Android 1.0 */ public int hashCode(); @@ -85,7 +77,6 @@ public interface Map<K,V> { * @param object * the new value to set. * @return object the replaced value of this entry. - * @since Android 1.0 */ public V setValue(V object); }; @@ -97,7 +88,6 @@ public interface Map<K,V> { * if removing elements from this {@code Map} is not supported. * @see #isEmpty() * @see #size() - * @since Android 1.0 */ public void clear(); @@ -108,7 +98,6 @@ public interface Map<K,V> { * the key to search for. * @return {@code true} if this map contains the specified key, * {@code false} otherwise. - * @since Android 1.0 */ public boolean containsKey(Object key); @@ -119,7 +108,6 @@ public interface Map<K,V> { * the value to search for. * @return {@code true} if this map contains the specified value, * {@code false} otherwise. - * @since Android 1.0 */ public boolean containsValue(Object value); @@ -129,7 +117,6 @@ public interface Map<K,V> { * changes in one will be reflected in the other. * * @return a set of the mappings - * @since Android 1.0 */ public Set<Map.Entry<K,V>> entrySet(); @@ -143,7 +130,6 @@ public interface Map<K,V> { * {@code false} if it is different from this {@code Object}. * @see #hashCode() * @see #entrySet() - * @since Android 1.0 */ public boolean equals(Object object); @@ -154,7 +140,6 @@ public interface Map<K,V> { * the key. * @return the value of the mapping with the specified key, or {@code null} * if no mapping for the specified key is found. - * @since Android 1.0 */ public V get(Object key); @@ -164,7 +149,6 @@ public interface Map<K,V> { * * @return the receiver's hash. * @see #equals(Object) - * @since Android 1.0 */ public int hashCode(); @@ -174,7 +158,6 @@ public interface Map<K,V> { * @return {@code true} if this map has no elements, {@code false} * otherwise. * @see #size() - * @since Android 1.0 */ public boolean isEmpty(); @@ -184,7 +167,6 @@ public interface Map<K,V> { * support adding. * * @return a set of the keys. - * @since Android 1.0 */ public Set<K> keySet(); @@ -207,7 +189,6 @@ public interface Map<K,V> { * @throws NullPointerException * if the key or value is {@code null} and this {@code Map} does * not support {@code null} keys or values. - * @since Android 1.0 */ public V put(K key, V value); @@ -226,7 +207,6 @@ public interface Map<K,V> { * @throws NullPointerException * if a key or value is {@code null} and this {@code Map} does not * support {@code null} keys or values. - * @since Android 1.0 */ public void putAll(Map<? extends K,? extends V> map); @@ -239,7 +219,6 @@ public interface Map<K,V> { * for the specified key was found. * @throws UnsupportedOperationException * if removing from this {@code Map} is not supported. - * @since Android 1.0 */ public V remove(Object key); @@ -247,7 +226,6 @@ public interface Map<K,V> { * Returns the number of mappings in this {@code Map}. * * @return the number of mappings in this {@code Map}. - * @since Android 1.0 */ public int size(); @@ -263,16 +241,13 @@ public interface Map<K,V> { * "wrapper object" over the iterator of this {@code Map}'s {@link #entrySet()}. The {@link AbstractCollection#size} method * wraps this {@code Map}'s {@link #size} method and the {@link AbstractCollection#contains} method wraps this {@code Map}'s * {@link #containsValue} method. - * </p> * <p> * The collection is created when this method is called at first time and * returned in response to all subsequent calls. This method may return * different Collection when multiple calls to this method, since it has no * synchronization performed. - * </p> * * @return a collection of the values contained in this map. - * @since Android 1.0 */ public Collection<V> values(); } diff --git a/luni/src/main/java/java/util/MapEntry.java b/luni/src/main/java/java/util/MapEntry.java index a63f2fd..6a5bf0f 100644 --- a/luni/src/main/java/java/util/MapEntry.java +++ b/luni/src/main/java/java/util/MapEntry.java @@ -17,17 +17,16 @@ package java.util; - /** * MapEntry is an internal class which provides an implementation of Map.Entry. */ -class MapEntry<K,V> implements Map.Entry<K,V>, Cloneable { - +class MapEntry<K, V> implements Map.Entry<K, V>, Cloneable { + K key; V value; - interface Type<RT,KT,VT> { - RT get(MapEntry<KT,VT> entry); + interface Type<RT, KT, VT> { + RT get(MapEntry<KT, VT> entry); } MapEntry(K theKey) { @@ -82,7 +81,7 @@ class MapEntry<K,V> implements Map.Entry<K,V>, Cloneable { value = object; return result; } - + @Override public String toString() { return key + "=" + value; diff --git a/luni/src/main/java/java/util/MissingFormatArgumentException.java b/luni/src/main/java/java/util/MissingFormatArgumentException.java index bcd240c..dfa0c73 100644 --- a/luni/src/main/java/java/util/MissingFormatArgumentException.java +++ b/luni/src/main/java/java/util/MissingFormatArgumentException.java @@ -24,7 +24,6 @@ import org.apache.harmony.luni.util.Msg; * that refers to a missing argument. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class MissingFormatArgumentException extends IllegalFormatException { private static final long serialVersionUID = 19190115L; diff --git a/luni/src/main/java/java/util/MissingFormatWidthException.java b/luni/src/main/java/java/util/MissingFormatWidthException.java index 19af7d7..8b4e1f8 100644 --- a/luni/src/main/java/java/util/MissingFormatWidthException.java +++ b/luni/src/main/java/java/util/MissingFormatWidthException.java @@ -21,7 +21,6 @@ package java.util; * missing but is required. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class MissingFormatWidthException extends IllegalFormatException { private static final long serialVersionUID = 15560123L; diff --git a/luni/src/main/java/java/util/MissingResourceException.java b/luni/src/main/java/java/util/MissingResourceException.java index c3a7efe..9a0cbbb 100644 --- a/luni/src/main/java/java/util/MissingResourceException.java +++ b/luni/src/main/java/java/util/MissingResourceException.java @@ -25,7 +25,6 @@ package java.util; * * @see ResourceBundle * @see java.lang.RuntimeException - * @since Android 1.0 */ public class MissingResourceException extends RuntimeException { diff --git a/luni/src/main/java/java/util/Observable.java b/luni/src/main/java/java/util/Observable.java index a4c0333..5ed4563 100644 --- a/luni/src/main/java/java/util/Observable.java +++ b/luni/src/main/java/java/util/Observable.java @@ -17,7 +17,6 @@ package java.util; - /** * Observable is used to notify a group of Observer objects when a change * occurs. On creation, the set of observers is empty. After a change occurred, @@ -26,21 +25,17 @@ package java.util; * Observers. The order of invocation is not specified. This implementation will * call the Observers in the order they registered. Subclasses are completely * free in what order they call the update methods. - * + * * @see Observer - * - * @since Android 1.0 */ public class Observable { - - Vector<Observer> observers = new Vector<Observer>(); + + List<Observer> observers = new ArrayList<Observer>(); boolean changed = false; /** * Constructs a new {@code Observable} object. - * - * @since Android 1.0 */ public Observable() { super(); @@ -49,68 +44,62 @@ public class Observable { /** * Adds the specified observer to the list of observers. If it is already * registered, it is not added a second time. - * + * * @param observer * the Observer to add. - * @since Android 1.0 */ - public synchronized void addObserver(Observer observer) { + public void addObserver(Observer observer) { if (observer == null) { throw new NullPointerException(); } - if (!observers.contains(observer)) - observers.addElement(observer); + synchronized (this) { + if (!observers.contains(observer)) + observers.add(observer); + } } /** * Clears the changed flag for this {@code Observable}. After calling * {@code clearChanged()}, {@code hasChanged()} will return {@code false}. - * - * @since Android 1.0 */ - protected synchronized void clearChanged() { + protected void clearChanged() { changed = false; } /** * Returns the number of observers registered to this {@code Observable}. - * + * * @return the number of observers. - * @since Android 1.0 */ - public synchronized int countObservers() { + public int countObservers() { return observers.size(); } /** * Removes the specified observer from the list of observers. Passing null * won't do anything. - * + * * @param observer * the observer to remove. - * @since Android 1.0 */ public synchronized void deleteObserver(Observer observer) { - observers.removeElement(observer); + observers.remove(observer); } /** * Removes all observers from the list of observers. - * - * @since Android 1.0 */ public synchronized void deleteObservers() { - observers.setSize(0); + observers.clear(); } /** * Returns the changed flag for this {@code Observable}. - * + * * @return {@code true} when the changed flag for this {@code Observable} is * set, {@code false} otherwise. - * @since Android 1.0 */ - public synchronized boolean hasChanged() { + public boolean hasChanged() { return changed; } @@ -120,9 +109,6 @@ public class Observable { * argument. Afterwards, calls {@code clearChanged()}. * <p> * Equivalent to calling {@code notifyObservers(null)}. - * </p> - * - * @since Android 1.0 */ public void notifyObservers() { notifyObservers(null); @@ -132,31 +118,34 @@ public class Observable { * If {@code hasChanged()} returns {@code true}, calls the {@code update()} * method for every Observer in the list of observers using the specified * argument. Afterwards calls {@code clearChanged()}. - * + * * @param data * the argument passed to {@code update()}. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public void notifyObservers(Object data) { - if (hasChanged()) { - // Must clone the vector in case deleteObserver is called - Vector<Observer> clone = (Vector<Observer>)observers.clone(); - int size = clone.size(); - for (int i = 0; i < size; i++) { - clone.elementAt(i).update(this, data); + int size = 0; + Observer[] arrays = null; + synchronized (this) { + if (hasChanged()) { + clearChanged(); + size = observers.size(); + arrays = new Observer[size]; + observers.toArray(arrays); + } + } + if (arrays != null) { + for (Observer observer : arrays) { + observer.update(this, data); } - clearChanged(); } } /** * Sets the changed flag for this {@code Observable}. After calling * {@code setChanged()}, {@code hasChanged()} will return {@code true}. - * - * @since Android 1.0 */ - protected synchronized void setChanged() { + protected void setChanged() { changed = true; } } diff --git a/luni/src/main/java/java/util/Observer.java b/luni/src/main/java/java/util/Observer.java index 2c8417b..c398e1b 100644 --- a/luni/src/main/java/java/util/Observer.java +++ b/luni/src/main/java/java/util/Observer.java @@ -23,7 +23,6 @@ package java.util; * receive notification of updates on an {@code Observable} object. * * @see Observable - * @since Android 1.0 */ public interface Observer { @@ -36,7 +35,6 @@ public interface Observer { * the {@link Observable} object. * @param data * the data passed to {@link Observable#notifyObservers(Object)}. - * @since Android 1.0 */ void update(Observable observable, Object data); } diff --git a/luni/src/main/java/java/util/PriorityQueue.java b/luni/src/main/java/java/util/PriorityQueue.java index 544c538..c17e7f9 100644 --- a/luni/src/main/java/java/util/PriorityQueue.java +++ b/luni/src/main/java/java/util/PriorityQueue.java @@ -31,8 +31,6 @@ import java.io.Serializable; * <p> * A PriorityQueue is not synchronized. If multiple threads will have to access * it concurrently, use the {@link java.util.concurrent.PriorityBlockingQueue}. - * - * @since Android 1.0 */ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { @@ -53,8 +51,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { /** * Constructs a priority queue with an initial capacity of 11 and natural * ordering. - * - * @since Android 1.0 */ public PriorityQueue() { this(DEFAULT_CAPACITY); @@ -68,7 +64,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * the specified capacity. * @throws IllegalArgumentException * if the initialCapacity is less than 1. - * @since Android 1.0 */ public PriorityQueue(int initialCapacity) { this(initialCapacity, null); @@ -84,7 +79,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * will be used. * @throws IllegalArgumentException * if the initialCapacity is less than 1. - * @since Android 1.0 */ public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) { if (initialCapacity < 1) { @@ -107,7 +101,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * if any of the elements in the collection are not comparable. * @throws NullPointerException * if any of the elements in the collection are null. - * @since Android 1.0 */ public PriorityQueue(Collection<? extends E> c) { if (c instanceof PriorityQueue) { @@ -129,7 +122,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * @param c * the priority queue whose elements will be added to the * priority queue to be constructed. - * @since Android 1.0 */ public PriorityQueue(PriorityQueue<? extends E> c) { getFromPriorityQueue(c); @@ -144,7 +136,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * @param c * the sorted set whose elements will be added to the priority * queue to be constructed. - * @since Android 1.0 */ public PriorityQueue(SortedSet<? extends E> c) { getFromSortedSet(c); @@ -155,7 +146,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * in any specified ordering. * * @return the iterator of the priority queue. - * @since Android 1.0 */ @Override public Iterator<E> iterator() { @@ -167,7 +157,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * than the Integer.MAX, then it returns Integer.MAX. * * @return the size of the priority queue. - * @since Android 1.0 */ @Override public int size() { @@ -176,8 +165,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { /** * Removes all the elements of the priority queue. - * - * @since Android 1.0 */ @Override public void clear() { @@ -194,7 +181,8 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * @throws ClassCastException * if the element cannot be compared with the elements in the * priority queue using the ordering of the priority queue. - * @since Android 1.0 + * @throws NullPointerException + * if {@code o} is {@code null}. */ public boolean offer(E o) { if (null == o) { @@ -210,7 +198,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * Gets and removes the head of the queue. * * @return the head of the queue or null if the queue is empty. - * @since Android 1.0 */ public E poll() { if (isEmpty()) { @@ -225,7 +212,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * Gets but does not remove the head of the queue. * * @return the head of the queue or null if the queue is empty. - * @since Android 1.0 */ public E peek() { if (isEmpty()) { @@ -239,7 +225,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * * @return the comparator of the priority queue or null if the natural * ordering is used. - * @since Android 1.0 */ public Comparator<? super E> comparator() { return comparator; @@ -252,7 +237,6 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * the object to be removed. * @return true if the object was in the priority queue, false if the object * was not in the priority queue. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -282,7 +266,8 @@ public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable { * @throws ClassCastException * if the element cannot be compared with the elements in the * priority queue using the ordering of the priority queue. - * @since Android 1.0 + * @throws NullPointerException + * if {@code o} is {@code null}. */ @Override public boolean add(E o) { diff --git a/luni/src/main/java/java/util/Properties.java b/luni/src/main/java/java/util/Properties.java index 15b74ee..b1fa938 100644 --- a/luni/src/main/java/java/util/Properties.java +++ b/luni/src/main/java/java/util/Properties.java @@ -17,9 +17,9 @@ package java.util; - import java.io.IOException; import java.io.InputStream; +import java.io.BufferedInputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintStream; @@ -48,45 +48,37 @@ import org.w3c.dom.Node; import org.w3c.dom.Text; // END android-added -// BEGIN android-added -// copied from newer version of Haromny import org.apache.harmony.luni.internal.nls.Messages; -// END android-added import org.apache.harmony.luni.util.PriviAction; /** - * A {@code Properties} object is a {@code Hashtable} where the keys and values - * must be {@code String}s. Each property can have a default + * A {@code Properties} object is a {@code Hashtable} where the keys and values + * must be {@code String}s. Each property can have a default * {@code Properties} list which specifies the default * values to be used when a given key is not found in this {@code Properties} * instance. - * + * * @see Hashtable * @see java.lang.System#getProperties - * @since Android 1.0 */ -public class Properties extends Hashtable<Object,Object> { - +public class Properties extends Hashtable<Object, Object> { + private static final long serialVersionUID = 4112578634029874840L; private transient DocumentBuilder builder = null; - private static final String PROP_DTD_NAME - = "http://java.sun.com/dtd/properties.dtd"; + private static final String PROP_DTD_NAME = "http://java.sun.com/dtd/properties.dtd"; - private static final String PROP_DTD - = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + private static final String PROP_DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + " <!ELEMENT properties (comment?, entry*) >" + " <!ATTLIST properties version CDATA #FIXED \"1.0\" >" + " <!ELEMENT comment (#PCDATA) >" + " <!ELEMENT entry (#PCDATA) >" + " <!ATTLIST entry key CDATA #REQUIRED >"; - + /** * The default values for keys not found in this {@code Properties} * instance. - * - * @since Android 1.0 */ protected Properties defaults; @@ -95,8 +87,6 @@ public class Properties extends Hashtable<Object,Object> { /** * Constructs a new {@code Properties} object. - * - * @since Android 1.0 */ public Properties() { super(); @@ -105,10 +95,9 @@ public class Properties extends Hashtable<Object,Object> { /** * Constructs a new {@code Properties} object using the specified default * {@code Properties}. - * + * * @param properties * the default {@code Properties}. - * @since Android 1.0 */ public Properties(Properties properties) { defaults = properties; @@ -158,11 +147,10 @@ public class Properties extends Hashtable<Object,Object> { * Searches for the property with the specified name. If the property is not * found, the default {@code Properties} are checked. If the property is not * found in the default {@code Properties}, {@code null} is returned. - * + * * @param name * the name of the property to find. * @return the named property value, or {@code null} if it can't be found. - * @since Android 1.0 */ public String getProperty(String name) { Object result = super.get(name); @@ -178,13 +166,12 @@ public class Properties extends Hashtable<Object,Object> { * found, it looks in the default {@code Properties}. If the property is not * found in the default {@code Properties}, it returns the specified * default. - * + * * @param name * the name of the property to find. * @param defaultValue * the default value. * @return the named property value. - * @since Android 1.0 */ public String getProperty(String name, String defaultValue) { Object result = super.get(name); @@ -202,11 +189,10 @@ public class Properties extends Hashtable<Object,Object> { * Lists the mappings in this {@code Properties} to the specified * {@code PrintStream} in a * human readable form. - * + * * @param out * the {@code PrintStream} to write the content to in human readable * form. - * @since Android 1.0 */ public void list(PrintStream out) { if (out == null) { @@ -239,11 +225,10 @@ public class Properties extends Hashtable<Object,Object> { * Lists the mappings in this {@code Properties} to the specified * {@code PrintWriter} in a * human readable form. - * + * * @param writer * the {@code PrintWriter} to write the content to in human * readable form. - * @since Android 1.0 */ public void list(PrintWriter writer) { if (writer == null) { @@ -293,29 +278,40 @@ public class Properties extends Hashtable<Object,Object> { * <li>Following escape sequences are recognized: "\ ", "\\", "\r", "\n", * "\!", "\#", "\t", "\b", "\f", and "\uXXXX" (unicode character).</li> * </ul> - * + * * @param in * the {@code InputStream}. * @throws IOException * if error occurs during reading from the {@code InputStream}. - * @since Android 1.0 */ + @SuppressWarnings("fallthrough") public synchronized void load(InputStream in) throws IOException { + if (in == null) { + throw new NullPointerException(); + } int mode = NONE, unicode = 0, count = 0; char nextChar, buf[] = new char[40]; - int offset = 0, keyLength = -1; + int offset = 0, keyLength = -1, intVal; boolean firstChar = true; - byte[] inbuf = new byte[256]; - int inbufCount = 0, inbufPos = 0; + BufferedInputStream bis = new BufferedInputStream(in); while (true) { - if (inbufPos == inbufCount) { - if ((inbufCount = in.read(inbuf)) == -1) { - break; + intVal = bis.read(); + if (intVal == -1) { + // if mode is UNICODE but has less than 4 hex digits, should + // throw an IllegalArgumentException + // luni.08=Invalid Unicode sequence: expected format \\uxxxx + if (mode == UNICODE && count < 4) { + throw new IllegalArgumentException(Messages.getString("luni.08")); //$NON-NLS-1$ } - inbufPos = 0; + // if mode is SLASH and no data is read, should append '\u0000' + // to buf + if (mode == SLASH) { + buf[offset++] = '\u0000'; + } + break; } - nextChar = (char) (inbuf[inbufPos++] & 0xff); + nextChar = (char) (intVal & 0xff); if (offset == buf.length) { char[] newBuf = new char[buf.length * 2]; @@ -324,8 +320,6 @@ public class Properties extends Hashtable<Object,Object> { } if (mode == UNICODE) { int digit = Character.digit(nextChar, 16); - // BEGIN android-changed - // copied from newer version of Harmony if (digit >= 0) { unicode = (unicode << 4) + digit; if (++count < 4) { @@ -333,9 +327,8 @@ public class Properties extends Hashtable<Object,Object> { } } else if (count <= 4) { // luni.09=Invalid Unicode sequence: illegal character - throw new IllegalArgumentException(Messages.getString("luni.09")); + throw new IllegalArgumentException(Messages.getString("luni.09")); //$NON-NLS-1$ } - // END android-changed mode = NONE; buf[offset++] = (char) unicode; if (nextChar != '\n') { @@ -377,16 +370,12 @@ public class Properties extends Hashtable<Object,Object> { case '!': if (firstChar) { while (true) { - if (inbufPos == inbufCount) { - if ((inbufCount = in.read(inbuf)) == -1) { - inbufPos = -1; - break; - } - inbufPos = 0; + intVal = bis.read(); + if (intVal == -1) { + break; } - nextChar = (char) inbuf[inbufPos++]; // & 0xff - // not - // required + // & 0xff not required + nextChar = (char) intVal; if (nextChar == '\r' || nextChar == '\n') { break; } @@ -399,7 +388,7 @@ public class Properties extends Hashtable<Object,Object> { mode = IGNORE; // Ignore whitespace on the next line continue; } - // fall into the next case + // fall into the next case case '\r': mode = NONE; firstChar = true; @@ -453,13 +442,9 @@ public class Properties extends Hashtable<Object,Object> { } buf[offset++] = nextChar; } - // BEGIN android-added - // copied from a newer version of Harmony - if (mode == UNICODE && count <= 4) { - // luni.08=Invalid Unicode sequence: expected format \\uxxxx - throw new IllegalArgumentException(Messages.getString("luni.08")); + if (keyLength == -1 && offset > 0) { + keyLength = offset; } - // END android-added if (keyLength >= 0) { String temp = new String(buf, 0, offset); put(temp.substring(0, keyLength), temp.substring(keyLength)); @@ -469,17 +454,18 @@ public class Properties extends Hashtable<Object,Object> { /** * Returns all of the property names that this {@code Properties} object * contains. - * + * * @return an {@code Enumeration} containing the names of all properties * that this {@code Properties} object contains. - * @since Android 1.0 */ public Enumeration<?> propertyNames() { if (defaults == null) { return keys(); } - Hashtable<Object, Object> set = new Hashtable<Object, Object>(defaults.size() + size()); + Hashtable<Object, Object> set = new Hashtable<Object, Object>(defaults + .size() + + size()); Enumeration<?> keys = defaults.propertyNames(); while (keys.hasMoreElements()) { set.put(keys.nextElement(), set); @@ -496,15 +482,14 @@ public class Properties extends Hashtable<Object,Object> { * OutputStream}, putting the specified comment at the beginning. The output * from this method is suitable for being read by the * {@link #load(InputStream)} method. - * + * * @param out the {@code OutputStream} to write to. * @param comment the comment to add at the beginning. - * @exception ClassCastException when the key or value of a mapping is not a + * @throws ClassCastException if the key or value of a mapping is not a * String. * @deprecated This method ignores any {@code IOException} thrown while * writing -- use {@link #store} instead for better exception * handling. - * @since Android 1.0 */ @Deprecated public void save(OutputStream out, String comment) { @@ -517,13 +502,12 @@ public class Properties extends Hashtable<Object,Object> { /** * Maps the specified key to the specified value. If the key already exists, * the old value is replaced. The key and value cannot be {@code null}. - * + * * @param name * the key. * @param value * the value. * @return the old value mapped to the key, or {@code null}. - * @since Android 1.0 */ public Object setProperty(String name, String value) { return put(name, value); @@ -536,14 +520,13 @@ public class Properties extends Hashtable<Object,Object> { * OutputStream}, putting the specified comment at the beginning. The output * from this method is suitable for being read by the * {@link #load(InputStream)} method. - * + * * @param out the {@code OutputStream} to write to. * @param comment the comment to put at the beginning. * @throws IOException if an error occurs during the write to the {@code * OutputStream}. - * @exception ClassCastException when the key or value of a mapping is not a + * @throws ClassCastException if the key or value of a mapping is not a * {@code String}. - * @since Android 1.0 */ public synchronized void store(OutputStream out, String comment) throws IOException { @@ -557,11 +540,11 @@ public class Properties extends Hashtable<Object,Object> { if (comment != null) { writer.write("#"); //$NON-NLS-1$ writer.write(comment); - writer.write(lineSeparator); + writer.write(lineSeparator); } writer.write("#"); //$NON-NLS-1$ writer.write(new Date().toString()); - writer.write(lineSeparator); + writer.write(lineSeparator); for (Map.Entry<Object, Object> entry : entrySet()) { String key = (String) entry.getKey(); @@ -579,39 +562,38 @@ public class Properties extends Hashtable<Object,Object> { * Loads the properties from an {@code InputStream} containing the * properties in XML form. The XML document must begin with (and conform to) * following DOCTYPE: - * + * * <pre> * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> * </pre> - * + * * Also the content of the XML data must satisfy the DTD but the xml is not * validated against it. The DTD is not loaded from the SYSTEM ID. After * this method returns the InputStream is not closed. - * + * * @param in the InputStream containing the XML document. * @throws IOException in case an error occurs during a read operation. * @throws InvalidPropertiesFormatException if the XML data is not a valid * properties file. - * @since Android 1.0 */ - public synchronized void loadFromXML(InputStream in) - throws IOException, InvalidPropertiesFormatException { + public synchronized void loadFromXML(InputStream in) throws IOException, + InvalidPropertiesFormatException { if (in == null) { throw new NullPointerException(); } - + if (builder == null) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // BEGIN android-removed // factory.setValidating(true); // END android-removed - + try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new Error(e); } - + builder.setErrorHandler(new ErrorHandler() { public void warning(SAXParseException e) throws SAXException { throw e; @@ -625,30 +607,30 @@ public class Properties extends Hashtable<Object,Object> { throw e; } }); - + builder.setEntityResolver(new EntityResolver() { - public InputSource resolveEntity(String publicId, String systemId) - throws SAXException, IOException { + public InputSource resolveEntity(String publicId, + String systemId) throws SAXException, IOException { if (systemId.equals(PROP_DTD_NAME)) { InputSource result = new InputSource(new StringReader( PROP_DTD)); result.setSystemId(PROP_DTD_NAME); return result; } - throw new SAXException( - "Invalid DOCTYPE declaration: " + systemId); + throw new SAXException("Invalid DOCTYPE declaration: " + + systemId); } }); } - + try { Document doc = builder.parse(in); - NodeList entries = doc.getElementsByTagName("entry"); + NodeList entries = doc.getElementsByTagName("entry"); if (entries == null) { return; } int entriesListLength = entries.getLength(); - + for (int i = 0; i < entriesListLength; i++) { Element entry = (Element) entries.item(i); String key = entry.getAttribute("key"); @@ -658,10 +640,10 @@ public class Properties extends Hashtable<Object,Object> { // BEGIN android-added String value = getTextContent(entry); // END android-added - + /* - * key != null & value != null - * but key or(and) value can be empty String + * key != null & value != null but key or(and) value can be + * empty String */ put(key, value); } @@ -675,44 +657,41 @@ public class Properties extends Hashtable<Object,Object> { /** * Writes all properties stored in this instance into the {@code * OutputStream} in XML representation. The DOCTYPE is - * + * * <pre> * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> * </pre> - * + * * If the comment is null, no comment is added to the output. UTF-8 is used * as the encoding. The {@code OutputStream} is not closed at the end. A * call to this method is the same as a call to {@code storeToXML(os, * comment, "UTF-8")}. - * + * * @param os the {@code OutputStream} to write to. * @param comment the comment to add. If null, no comment is added. * @throws IOException if an error occurs during writing to the output. - * @since Android 1.0 */ - public void storeToXML(OutputStream os, String comment) - throws IOException { - storeToXML(os, comment, "UTF-8"); + public void storeToXML(OutputStream os, String comment) throws IOException { + storeToXML(os, comment, "UTF-8"); //$NON-NLS-1$ } /** * Writes all properties stored in this instance into the {@code * OutputStream} in XML representation. The DOCTYPE is - * + * * <pre> * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> * </pre> - * + * * If the comment is null, no comment is added to the output. The parameter * {@code encoding} defines which encoding should be used. The {@code * OutputStream} is not closed at the end. - * + * * @param os the {@code OutputStream} to write to. * @param comment the comment to add. If null, no comment is added. * @param encoding the code identifying the encoding that should be used to * write into the {@code OutputStream}. * @throws IOException if an error occurs during writing to the output. - * @since Android 1.0 */ public synchronized void storeToXML(OutputStream os, String comment, String encoding) throws IOException { @@ -720,14 +699,14 @@ public class Properties extends Hashtable<Object,Object> { if (os == null || encoding == null) { throw new NullPointerException(); } - + /* * We can write to XML file using encoding parameter but note that some * aliases for encodings are not supported by the XML parser. Thus we * have to know canonical name for encoding used to store data in XML * since the XML parser must recognize encoding name used to store data. */ - + String encodingCanonicalName; try { encodingCanonicalName = Charset.forName(encoding).name(); @@ -741,18 +720,19 @@ public class Properties extends Hashtable<Object,Object> { encodingCanonicalName = "UTF-8"; } - PrintStream printStream = new PrintStream(os, false, encodingCanonicalName); - + PrintStream printStream = new PrintStream(os, false, + encodingCanonicalName); + printStream.print("<?xml version=\"1.0\" encoding=\""); printStream.print(encodingCanonicalName); printStream.println("\"?>"); - + printStream.print("<!DOCTYPE properties SYSTEM \""); printStream.print(PROP_DTD_NAME); printStream.println("\">"); - + printStream.println("<properties>"); - + if (comment != null) { printStream.print("<comment>"); printStream.print(substitutePredefinedEntries(comment)); @@ -771,18 +751,16 @@ public class Properties extends Hashtable<Object,Object> { printStream.println("</properties>"); printStream.flush(); } - + private String substitutePredefinedEntries(String s) { - + /* - * substitution for predefined character entities - * to use them safely in XML + * substitution for predefined character entities to use them safely in + * XML */ - return s.replaceAll("&", "&") - .replaceAll("<", "<") - .replaceAll(">", ">") - .replaceAll("\u0027", "'") - .replaceAll("\"", """); + return s.replaceAll("&", "&").replaceAll("<", "<").replaceAll( + ">", ">").replaceAll("\u0027", "'").replaceAll("\"", + """); } // BEGIN android-added diff --git a/luni/src/main/java/java/util/PropertyPermission.java b/luni/src/main/java/java/util/PropertyPermission.java index cdbfe34..1cd7143 100644 --- a/luni/src/main/java/java/util/PropertyPermission.java +++ b/luni/src/main/java/java/util/PropertyPermission.java @@ -39,8 +39,6 @@ import org.apache.harmony.luni.util.Util; * <p> * There are two possible permission action types: read and write. Possible * actions are "read", "write", or "read,write"/"write,read". - * - * @since Android 1.0 */ public final class PropertyPermission extends BasicPermission { private static final long serialVersionUID = 885438825399942851L; @@ -56,7 +54,6 @@ public final class PropertyPermission extends BasicPermission { * the actions which are applicable to it. Possible actions are * "read", "write", or "read,write"/"write,read". Anything else * will result in an {@code IllegalArgumentException}. - * @since Android 1.0 */ public PropertyPermission(String name, String actions) { super(name); @@ -84,17 +81,16 @@ public final class PropertyPermission extends BasicPermission { /** * Compares the argument to the receiver, and returns true if they represent * the <em>same</em> object using a class specific comparison. In this - * case, the receiver must be a {@code PropertyPermission} for the same + * case, the receiver must be a {@code PropertyPermission} for the same * property as the argument, and must have the same actions. * If {@code o} is a permission that is not a {@code PropertyPermission}, - * this method may throw a {@code ClassCastException}. - * + * this method may throw a {@code ClassCastException}. + * * @param o * the {@code Object} to compare with this {@code Object}. * @return {@code true} if the {@code Object} is the same as this {@code Object}, * {@code false} if it is different from this {@code Object}. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object o) { @@ -110,7 +106,6 @@ public final class PropertyPermission extends BasicPermission { * either "read", "write", or "read,write". * * @return the actions associated with the receiver. - * @since Android 1.0 */ @Override public String getActions() { @@ -124,7 +119,6 @@ public final class PropertyPermission extends BasicPermission { * * @return the receiver's hash. * @see #equals - * @since Android 1.0 */ @Override public int hashCode() { @@ -138,7 +132,6 @@ public final class PropertyPermission extends BasicPermission { * receiver, and {@code false} if it is not. * @param permission * the permission to check. - * @since Android 1.0 */ @Override public boolean implies(Permission permission) { @@ -155,7 +148,6 @@ public final class PropertyPermission extends BasicPermission { * * @return a new {@code PermissionCollection} or {@code null}. * @see java.security.PermissionCollection - * @since Android 1.0 */ @Override public PermissionCollection newPermissionCollection() { diff --git a/luni/src/main/java/java/util/PropertyPermissionCollection.java b/luni/src/main/java/java/util/PropertyPermissionCollection.java index 45e89d9..bf88534 100644 --- a/luni/src/main/java/java/util/PropertyPermissionCollection.java +++ b/luni/src/main/java/java/util/PropertyPermissionCollection.java @@ -26,8 +26,6 @@ import java.security.PermissionCollection; /** * A {@code PermissionCollection} for holding {@code PropertyPermission}s. - * - * @since Android 1.0 */ class PropertyPermissionCollection extends PermissionCollection { diff --git a/luni/src/main/java/java/util/PropertyResourceBundle.java b/luni/src/main/java/java/util/PropertyResourceBundle.java index acc3263..835e892 100644 --- a/luni/src/main/java/java/util/PropertyResourceBundle.java +++ b/luni/src/main/java/java/util/PropertyResourceBundle.java @@ -17,7 +17,6 @@ package java.util; - import java.io.IOException; import java.io.InputStream; @@ -28,9 +27,10 @@ import java.io.InputStream; * * @see ResourceBundle * @see Properties - * @since Android 1.0 + * @since 1.1 */ public class PropertyResourceBundle extends ResourceBundle { + Properties resources; /** @@ -42,18 +42,23 @@ public class PropertyResourceBundle extends ResourceBundle { * @throws IOException * if an error occurs during a read operation on the * {@code InputStream}. - * @since Android 1.0 */ public PropertyResourceBundle(InputStream stream) throws IOException { resources = new Properties(); resources.load(stream); } - + @SuppressWarnings("unchecked") private Enumeration<String> getLocalKeys() { - return (Enumeration<String>)resources.propertyNames(); + return (Enumeration<String>) resources.propertyNames(); } + /** + * Returns the names of the resources contained in this + * PropertyResourceBundle. + * + * @return an Enumeration of the resource names + */ @Override public Enumeration<String> getKeys() { if (parent == null) { @@ -102,6 +107,14 @@ public class PropertyResourceBundle extends ResourceBundle { }; } + /** + * Returns the named resource from this PropertyResourceBundle, or null if + * the resource is not found. + * + * @param key + * the name of the resource + * @return the resource object + */ @Override public Object handleGetObject(String key) { return resources.get(key); diff --git a/luni/src/main/java/java/util/Queue.java b/luni/src/main/java/java/util/Queue.java index 5035ce7..6ef776a 100644 --- a/luni/src/main/java/java/util/Queue.java +++ b/luni/src/main/java/java/util/Queue.java @@ -24,22 +24,17 @@ package java.util; * However, a priority queue orders its elements according to a comparator * specified or the elements' natural order. Furthermore, a stack orders its * elements last-in-first out. - * </p> * <p> * A typical queue does not allow {@code null} to be inserted as its element, * while some implementations such as {@code LinkedList} allow it. But {@code * null} should not be inserted even in these implementations, since the method * {@code poll} returns {@code null} to indicate that there is no element left * in the queue. - * </p> * <p> * {@code Queue} does not provide blocking queue methods, which would block * until the operation of the method is allowed. See the * {@link java.util.concurrent.BlockingQueue} interface for information about * blocking queue methods. - * </p> - * - * @since Android 1.0 */ public interface Queue<E> extends Collection<E> { @@ -53,7 +48,6 @@ public interface Queue<E> extends Collection<E> { * the specified element to insert into the queue. * @return {@code true} if the operation succeeds and {@code false} if it * fails. - * @since Android 1.0 */ public boolean offer(E o); @@ -63,7 +57,6 @@ public interface Queue<E> extends Collection<E> { * * @return the element at the head of the queue or {@code null} if there is * no element in the queue. - * @since Android 1.0 */ public E poll(); @@ -74,7 +67,6 @@ public interface Queue<E> extends Collection<E> { * @return the element at the head of the queue. * @throws NoSuchElementException * if there is no element in the queue. - * @since Android 1.0 */ public E remove(); @@ -83,7 +75,6 @@ public interface Queue<E> extends Collection<E> { * * @return the element at the head of the queue or {@code null} if there is * no element in the queue. - * @since Android 1.0 */ public E peek(); @@ -94,7 +85,6 @@ public interface Queue<E> extends Collection<E> { * @return the element at the head of the queue. * @throws NoSuchElementException * if there is no element in the queue. - * @since Android 1.0 */ public E element(); diff --git a/luni/src/main/java/java/util/Random.java b/luni/src/main/java/java/util/Random.java index f92c3ee..be27258 100644 --- a/luni/src/main/java/java/util/Random.java +++ b/luni/src/main/java/java/util/Random.java @@ -26,44 +26,40 @@ import java.io.Serializable; * * @see Properties * @see PropertyResourceBundle - * @since Android 1.0 */ public class Random implements Serializable { private static final long serialVersionUID = 3905348978240129619L; - static final long multiplier = 0x5deece66dL; + private static final long multiplier = 0x5deece66dL; /** * The boolean value indicating if the second Gaussian number is available. * * @serial */ - boolean haveNextNextGaussian = false; + private boolean haveNextNextGaussian; /** - * It is associated with the internal state of this generator. - * - * @serial + * @serial It is associated with the internal state of this generator. */ - long seed; + private long seed; /** * The second Gaussian generated number. * * @serial */ - double nextNextGaussian = 0; + private double nextNextGaussian; /** * Construct a random generator with the current time of day in milliseconds * as the initial state. * * @see #setSeed - * @since Android 1.0 */ public Random() { - setSeed(System.currentTimeMillis()); + setSeed(System.currentTimeMillis() + hashCode()); } /** @@ -74,7 +70,6 @@ public class Random implements Serializable { * the seed that will determine the initial state of this random * number generator. * @see #setSeed - * @since Android 1.0 */ public Random(long seed) { setSeed(seed); @@ -89,7 +84,6 @@ public class Random implements Serializable { * @param bits * number of bits of the returned value. * @return a pseudo-random generated int number. - * @since Android 1.0 * @see #nextBytes * @see #nextDouble * @see #nextFloat @@ -97,7 +91,6 @@ public class Random implements Serializable { * @see #nextInt(int) * @see #nextGaussian * @see #nextLong - * @since Android 1.0 */ protected synchronized int next(int bits) { seed = (seed * multiplier + 0xbL) & ((1L << 48) - 1); @@ -109,7 +102,6 @@ public class Random implements Serializable { * generated by this generator. * * @return a pseudo-random, uniformly distributed boolean value. - * @since Android 1.0 */ public boolean nextBoolean() { return next(1) != 0; @@ -122,7 +114,6 @@ public class Random implements Serializable { * @param buf * non-null array to contain the new random {@code byte}s. * @see #next - * @since Android 1.0 */ public void nextBytes(byte[] buf) { int rand = 0, count = 0, loop = 0; @@ -144,7 +135,6 @@ public class Random implements Serializable { * * @return a random {@code double} in the range [0.0 - 1.0) * @see #nextFloat - * @since Android 1.0 */ public double nextDouble() { return ((((long) next(26) << 27) + next(27)) / (double) (1L << 53)); @@ -156,7 +146,6 @@ public class Random implements Serializable { * * @return float a random {@code float} number between [0.0 and 1.0) * @see #nextDouble - * @since Android 1.0 */ public float nextFloat() { return (next(24) / 16777216f); @@ -172,7 +161,6 @@ public class Random implements Serializable { * * @return a random {@code double} * @see #nextDouble - * @since Android 1.0 */ public synchronized double nextGaussian() { if (haveNextNextGaussian) { // if X1 has been returned, return the @@ -205,7 +193,6 @@ public class Random implements Serializable { * @see java.lang.Integer#MIN_VALUE * @see #next * @see #nextLong - * @since Android 1.0 */ public int nextInt() { return next(32); @@ -218,7 +205,6 @@ public class Random implements Serializable { * @param n * the exclusive upper border of the range [0 - n). * @return a random {@code int}. - * @since Android 1.0 */ public int nextInt(int n) { if (n > 0) { @@ -245,7 +231,6 @@ public class Random implements Serializable { * @see #next * @see #nextInt() * @see #nextInt(int) - * @since Android 1.0 */ public long nextLong() { return ((long) next(32) << 32) + next(32); @@ -260,7 +245,6 @@ public class Random implements Serializable { * @see #next * @see #Random() * @see #Random(long) - * @since Android 1.0 */ public synchronized void setSeed(long seed) { this.seed = (seed ^ multiplier) & ((1L << 48) - 1); diff --git a/luni/src/main/java/java/util/RandomAccess.java b/luni/src/main/java/java/util/RandomAccess.java index a8a90de..7121bff 100644 --- a/luni/src/main/java/java/util/RandomAccess.java +++ b/luni/src/main/java/java/util/RandomAccess.java @@ -17,13 +17,10 @@ package java.util; - /** * RandomAccess is implemented by {@code List} implementations that support fast * (usually constant time) random access. - * - * @since Android 1.0 */ public interface RandomAccess { - /*empty*/ + /* empty */ } diff --git a/luni/src/main/java/java/util/ResourceBundle.java b/luni/src/main/java/java/util/ResourceBundle.java index 1187358..218d3f3 100644 --- a/luni/src/main/java/java/util/ResourceBundle.java +++ b/luni/src/main/java/java/util/ResourceBundle.java @@ -27,6 +27,7 @@ import java.security.PrivilegedAction; import com.ibm.icu4jni.util.Resources; import dalvik.system.VMStack; // END android-changed +import org.apache.harmony.luni.util.Msg; /** * {@code ResourceBundle} is an abstract class which is the superclass of classes which @@ -35,7 +36,7 @@ import dalvik.system.VMStack; * and when a resource is not found in a bundle, the parent bundle is searched for * the resource. If the fallback mechanism reaches the base bundle and still * can't find the resource it throws a {@code MissingResourceException}. - * + * * <ul> * <li>All bundles for the same group of resources share a common base bundle. * This base bundle acts as the root and is the last fallback in case none of @@ -53,7 +54,7 @@ import dalvik.system.VMStack; * current currency (Euro) and the {@code PREEURO} variant bundle would return the old * currency (e.g. DM for Germany).</li> * </ul> - * + * * <strong>Examples</strong> * <ul> * <li>BaseName (base bundle) @@ -67,24 +68,22 @@ import dalvik.system.VMStack; * <li>BaseName_fr_FR_PREEURO (bundle with France specific resources in french of * the time before the Euro) * </ul> - * + * * It's also possible to create variants for languages or countries. This can be * done by just skipping the country or language abbreviation: * BaseName_us__POSIX or BaseName__DE_PREEURO. But it's not allowed to * circumvent both language and country: BaseName___VARIANT is illegal. - * + * * @see Properties * @see PropertyResourceBundle * @see ListResourceBundle - * @since Android 1.0 + * @since 1.1 */ public abstract class ResourceBundle { /** * The parent of this {@code ResourceBundle} that is used if this bundle doesn't * include the requested resource. - * - * @since Android 1.0 */ protected ResourceBundle parent; @@ -114,8 +113,6 @@ public abstract class ResourceBundle { /** * Constructs a new instance of this class. - * - * @since Android 1.0 */ public ResourceBundle() { /* empty */ @@ -124,13 +121,12 @@ public abstract class ResourceBundle { /** * Finds the named resource bundle for the default {@code Locale} and the caller's * {@code ClassLoader}. - * + * * @param bundleName * the name of the {@code ResourceBundle}. * @return the requested {@code ResourceBundle}. - * @exception MissingResourceException + * @throws MissingResourceException * if the {@code ResourceBundle} cannot be found. - * @since Android 1.0 */ public static final ResourceBundle getBundle(String bundleName) throws MissingResourceException { @@ -143,15 +139,14 @@ public abstract class ResourceBundle { /** * Finds the named {@code ResourceBundle} for the specified {@code Locale} and the caller * {@code ClassLoader}. - * + * * @param bundleName * the name of the {@code ResourceBundle}. * @param locale * the {@code Locale}. * @return the requested resource bundle. - * @exception MissingResourceException + * @throws MissingResourceException * if the resource bundle cannot be found. - * @since Android 1.0 */ public static final ResourceBundle getBundle(String bundleName, Locale locale) { @@ -163,17 +158,17 @@ public abstract class ResourceBundle { /** * Finds the named resource bundle for the specified {@code Locale} and {@code ClassLoader}. - * + * * The passed base name and {@code Locale} are used to create resource bundle names. * The first name is created by concatenating the base name with the result * of {@link Locale#toString()}. From this name all parent bundle names are * derived. Then the same thing is done for the default {@code Locale}. This results * in a list of possible bundle names. - * + * * <strong>Example</strong> For the basename "BaseName", the {@code Locale} of the * German part of Switzerland (de_CH) and the default {@code Locale} en_US the list * would look something like this: - * + * * <ol> * <li>BaseName_de_CH</li> * <li>BaseName_de</li> @@ -181,11 +176,11 @@ public abstract class ResourceBundle { * <li>Basename_en</li> * <li>BaseName</li> * </ol> - * + * * This list also shows the order in which the bundles will be searched for a requested * resource in the German part of Switzerland (de_CH). - * - * As a first step, this method tries to instantiate + * + * As a first step, this method tries to instantiate * a {@code ResourceBundle} with the names provided. * If such a class can be instantiated and initialized, it is returned and * all the parent bundles are instantiated too. If no such class can be @@ -195,11 +190,11 @@ public abstract class ResourceBundle { * by calling {@link ClassLoader#getResource(String)} it is used to * initialize a {@link PropertyResourceBundle}. If this succeeds, it will * also load the parents of this {@code ResourceBundle}. - * + * * For compatibility with older code, the bundle name isn't required to be * a fully qualified class name. It's also possible to directly pass * the path to a properties file (without a file extension). - * + * * @param bundleName * the name of the {@code ResourceBundle}. * @param locale @@ -207,9 +202,8 @@ public abstract class ResourceBundle { * @param loader * the {@code ClassLoader} to use. * @return the requested {@code ResourceBundle}. - * @exception MissingResourceException + * @throws MissingResourceException * if the {@code ResourceBundle} cannot be found. - * @since Android 1.0 */ public static ResourceBundle getBundle(String bundleName, Locale locale, ClassLoader loader) throws MissingResourceException { @@ -248,7 +242,7 @@ public abstract class ResourceBundle { if ((bundle = handleGetBundle(bundleName, localeName, true, loader)) != null) { return bundle; } - throw new MissingResourceException(null, bundleName + '_' + locale, + throw new MissingResourceException(Msg.getString("KA029", bundleName, locale), bundleName + '_' + locale, //$NON-NLS-1$ ""); //$NON-NLS-1$ } throw new NullPointerException(); @@ -256,9 +250,8 @@ public abstract class ResourceBundle { /** * Returns the names of the resources contained in this {@code ResourceBundle}. - * + * * @return an {@code Enumeration} of the resource names. - * @since Android 1.0 */ public abstract Enumeration<String> getKeys(); @@ -266,9 +259,8 @@ public abstract class ResourceBundle { * Gets the {@code Locale} of this {@code ResourceBundle}. In case a bundle was not * found for the requested {@code Locale}, this will return the actual {@code Locale} of * this resource bundle that was found after doing a fallback. - * + * * @return the {@code Locale} of this {@code ResourceBundle}. - * @since Android 1.0 */ public Locale getLocale() { return locale; @@ -279,13 +271,12 @@ public abstract class ResourceBundle { * cannot be found in this bundle, it falls back to the parent bundle (if * it's not null) by calling the {@link #handleGetObject} method. If the resource still * can't be found it throws a {@code MissingResourceException}. - * + * * @param key * the name of the resource. * @return the resource object. - * @exception MissingResourceException + * @throws MissingResourceException * if the resource is not found. - * @since Android 1.0 */ public final Object getObject(String key) { ResourceBundle last, theParent = this; @@ -297,21 +288,20 @@ public abstract class ResourceBundle { last = theParent; theParent = theParent.parent; } while (theParent != null); - throw new MissingResourceException(null, last.getClass().getName(), key); + throw new MissingResourceException(Msg.getString("KA029", last.getClass().getName(), key), last.getClass().getName(), key); //$NON-NLS-1$ } /** * Returns the named string resource from this {@code ResourceBundle}. - * + * * @param key * the name of the resource. * @return the resource string. - * @exception MissingResourceException + * @throws MissingResourceException * if the resource is not found. - * @exception ClassCastException + * @throws ClassCastException * if the resource found is not a string. * @see #getObject(String) - * @since Android 1.0 */ public final String getString(String key) { return (String) getObject(key); @@ -319,16 +309,15 @@ public abstract class ResourceBundle { /** * Returns the named resource from this {@code ResourceBundle}. - * + * * @param key * the name of the resource. * @return the resource string array. - * @exception MissingResourceException + * @throws MissingResourceException * if the resource is not found. - * @exception ClassCastException + * @throws ClassCastException * if the resource found is not an array of strings. * @see #getObject(String) - * @since Android 1.0 */ public final String[] getStringArray(String key) { return (String[]) getObject(key); @@ -343,7 +332,7 @@ public abstract class ResourceBundle { synchronized (cache) { loaderCache = cache.get(cacheKey); if (loaderCache == null) { - loaderCache = new Hashtable<String, ResourceBundle>(13); + loaderCache = new Hashtable<String, ResourceBundle>(); cache.put(cacheKey, loaderCache); } } @@ -389,13 +378,9 @@ public abstract class ResourceBundle { } catch (Exception e) { } - // BEGIN android-added - // copied from newer version of Harmony if (bundle != null) { bundle.setLocale(locale); - } - // END android-added - if (bundle == null) { + } else { final String fileName = bundleName.replace('.', '/'); InputStream stream = AccessController .doPrivileged(new PrivilegedAction<InputStream>() { @@ -447,21 +432,19 @@ public abstract class ResourceBundle { /** * Returns the named resource from this {@code ResourceBundle}, or null if the * resource is not found. - * + * * @param key * the name of the resource. * @return the resource object. - * @since Android 1.0 */ protected abstract Object handleGetObject(String key); /** * Sets the parent resource bundle of this {@code ResourceBundle}. The parent is * searched for resources which are not found in this {@code ResourceBundle}. - * + * * @param bundle * the parent {@code ResourceBundle}. - * @since Android 1.0 */ protected void setParent(ResourceBundle bundle) { parent = bundle; diff --git a/luni/src/main/java/java/util/Scanner.java b/luni/src/main/java/java/util/Scanner.java index acacebb..dd5c024 100644 --- a/luni/src/main/java/java/util/Scanner.java +++ b/luni/src/main/java/java/util/Scanner.java @@ -44,7 +44,7 @@ import java.util.regex.Pattern; * next* methods. If the token is not in a valid format, an * {@code InputMismatchException} is thrown. * <p> - * For example: </p> + * For example: * <pre> * Scanner s = new Scanner("1A true"); * System.out.println(s.nextInt(16)); @@ -52,28 +52,25 @@ import java.util.regex.Pattern; * </pre> * <p> * Yields the result: {@code 26 true} - * </p> * <p>A {@code Scanner} can also find or skip specific patterns without regard for the * delimiter. All these methods and the various next* and hasNext* methods may * block. - * </p> + * <p> * The {@code Scanner} class is not thread-safe. - * @since Android 1.0 */ public final class Scanner implements Iterator<String> { - // Default delimiting pattern. + // Default delimiting pattern. private static final Pattern DEFAULT_DELIMITER = Pattern .compile("\\p{javaWhitespace}+"); //$NON-NLS-1$ - + // The boolean's pattern. private static final Pattern BOOLEAN_PATTERN = Pattern.compile( "true|false", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ - - + // Pattern used to recognize line terminator. private static final Pattern LINE_TERMINATOR; - + // Pattern used to recognize multiple line terminators. private static final Pattern MULTI_LINE_TERMINATOR; @@ -81,24 +78,22 @@ public final class Scanner implements Iterator<String> { private static final Pattern LINE_PATTERN; static { - String terminator = "\n|\r\n|\r|\u0085|\u2028|\u2029"; //$NON-NLS-1$ - + String terminator = "\n|\r\n|\r|\u0085|\u2028|\u2029"; //$NON-NLS-1$ + LINE_TERMINATOR = Pattern.compile(terminator); - + + // BEGIN android-note + // consider plain old string concatenation for better performance + // END android-note StringBuilder multiTerminator = new StringBuilder(); - MULTI_LINE_TERMINATOR = Pattern - .compile(multiTerminator.append("(") //$NON-NLS-1$ - .append(terminator) - .append(")+").toString()); //$NON-NLS-1$ + MULTI_LINE_TERMINATOR = Pattern.compile(multiTerminator.append("(") //$NON-NLS-1$ + .append(terminator).append(")+").toString()); //$NON-NLS-1$ StringBuilder line = new StringBuilder(); - LINE_PATTERN = Pattern - .compile(line.append(".*(") //$NON-NLS-1$ - .append(terminator) - .append(")|.+(") //$NON-NLS-1$ - .append(terminator) - .append(")?").toString()); //$NON-NLS-1$ - } - + LINE_PATTERN = Pattern.compile(line.append(".*(") //$NON-NLS-1$ + .append(terminator).append(")|.+(") //$NON-NLS-1$ + .append(terminator).append(")?").toString()); //$NON-NLS-1$ + } + // The pattern matches anything. private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*"); //$NON-NLS-1$ @@ -131,24 +126,24 @@ public final class Scanner implements Iterator<String> { // The length of the buffer. private int bufferLength = 0; - // Record the status of this scanner. True if the scanner + // Record the status of this scanner. True if the scanner // is closed. private boolean closed = false; private IOException lastIOException; - + private boolean matchSuccessful = false; - + private DecimalFormat decimalFormat; - + // Records whether the underlying readable has more input. private boolean inputExhausted = false; - + private Object cacheHasNextValue = null; - + private int cachehasNextIndex = -1; - - private enum DataType{ + + private enum DataType { /* * Stands for Integer */ @@ -162,12 +157,11 @@ public final class Scanner implements Iterator<String> { /** * Creates a {@code Scanner} with the specified {@code File} as input. The default charset * is applied when reading the file. - * + * * @param src * the file to be scanned. * @throws FileNotFoundException * if the specified file does not exist. - * @since Android 1.0 */ public Scanner(File src) throws FileNotFoundException { this(src, Charset.defaultCharset().name()); @@ -176,7 +170,7 @@ public final class Scanner implements Iterator<String> { /** * Creates a {@code Scanner} with the specified {@code File} as input. The specified charset * is applied when reading the file. - * + * * @param src * the file to be scanned. * @param charsetName @@ -185,7 +179,6 @@ public final class Scanner implements Iterator<String> { * if the specified file does not exist. * @throws IllegalArgumentException * if the specified coding does not exist. - * @since Android 1.0 */ public Scanner(File src, String charsetName) throws FileNotFoundException { if (null == src) { @@ -212,10 +205,9 @@ public final class Scanner implements Iterator<String> { /** * Creates a {@code Scanner} on the specified string. - * + * * @param src * the string to be scanned. - * @since Android 1.0 */ public Scanner(String src) { input = new StringReader(src); @@ -225,10 +217,9 @@ public final class Scanner implements Iterator<String> { /** * Creates a {@code Scanner} on the specified {@code InputStream}. The default charset is * applied when decoding the input. - * + * * @param src * the {@code InputStream} to be scanned. - * @since Android 1.0 */ public Scanner(InputStream src) { this(src, Charset.defaultCharset().name()); @@ -237,14 +228,13 @@ public final class Scanner implements Iterator<String> { /** * Creates a {@code Scanner} on the specified {@code InputStream}. The specified charset is * applied when decoding the input. - * + * * @param src * the {@code InputStream} to be scanned. * @param charsetName * the encoding type of the {@code InputStream}. * @throws IllegalArgumentException * if the specified character set is not found. - * @since Android 1.0 */ public Scanner(InputStream src, String charsetName) { if (null == src) { @@ -261,10 +251,9 @@ public final class Scanner implements Iterator<String> { /** * Creates a {@code Scanner} with the specified {@code Readable} as input. - * + * * @param src * the {@code Readable} to be scanned. - * @since Android 1.0 */ public Scanner(Readable src) { if (null == src) { @@ -277,10 +266,9 @@ public final class Scanner implements Iterator<String> { /** * Creates a {@code Scanner} with the specified {@code ReadableByteChannel} as * input. The default charset is applied when decoding the input. - * + * * @param src * the {@code ReadableByteChannel} to be scanned. - * @since Android 1.0 */ public Scanner(ReadableByteChannel src) { this(src, Charset.defaultCharset().name()); @@ -289,14 +277,13 @@ public final class Scanner implements Iterator<String> { /** * Creates a {@code Scanner} with the specified {@code ReadableByteChannel} as * input. The specified charset is applied when decoding the input. - * + * * @param src * the {@code ReadableByteChannel} to be scanned. * @param charsetName * the encoding type of the content. * @throws IllegalArgumentException * if the specified character set is not found. - * @since Android 1.0 */ public Scanner(ReadableByteChannel src, String charsetName) { if (null == src) { @@ -316,9 +303,8 @@ public final class Scanner implements Iterator<String> { * {@code Closeable}. If the {@code Scanner} has been closed, this method will have * no effect. Any scanning operation called after calling this method will throw * an {@code IllegalStateException}. - * + * * @see Closeable - * @since Android 1.0 */ public void close() { if (closed) { @@ -336,9 +322,8 @@ public final class Scanner implements Iterator<String> { /** * Returns the delimiter {@code Pattern} in use by this {@code Scanner}. - * + * * @return the delimiter {@code Pattern} in use by this {@code Scanner}. - * @since Android 1.0 */ public Pattern delimiter() { return delimiter; @@ -351,14 +336,13 @@ public final class Scanner implements Iterator<String> { * Otherwise, {@code null} will be returned and the {@code Scanner} will not advance. * When waiting for input, the {@code Scanner} may be blocked. All the * input may be cached if no line terminator exists in the buffer. - * + * * @param pattern * the pattern to find in the input. * @return the matched string or {@code null} if the pattern is not found * before the next line terminator. * @throws IllegalStateException * if the {@code Scanner} is closed. - * @since Android 1.0 */ public String findInLine(Pattern pattern) { checkClosed(); @@ -395,17 +379,32 @@ public final class Scanner implements Iterator<String> { * bug is fixed. */ int oldLimit = buffer.limit(); - buffer.limit(horizonLineSeparator); + // Considering the look ahead feature, the line terminator should be involved as RI + buffer.limit(horizonLineSeparator + terminatorLength); // ========== To deal with regex bug ==================== - matcher.region(findStartIndex, horizonLineSeparator); + // Considering the look ahead feature, the line terminator should be involved as RI + matcher.region(findStartIndex, horizonLineSeparator + terminatorLength); if (matcher.find()) { // The scanner advances past the input that matched findStartIndex = matcher.end(); - // If the matched pattern is immediately followed by line terminator. - if(horizonLineSeparator == matcher.end()) { + // If the matched pattern is immediately followed by line + // terminator. + if (horizonLineSeparator == matcher.end()) { findStartIndex += terminatorLength; } + // the line terminator itself should not be a part of + // the match result according to the Spec + if (horizonLineSeparator != bufferLength + && (horizonLineSeparator + terminatorLength == matcher + .end())) { + // ========== To deal with regex bug ==================== + buffer.limit(oldLimit); + // ========== To deal with regex bug ==================== + + matchSuccessful = false; + return null; + } matchSuccessful = true; // ========== To deal with regex bug ==================== @@ -427,7 +426,7 @@ public final class Scanner implements Iterator<String> { * Compiles the pattern string and tries to find a substing matching it in the input data. The * delimiter will be ignored. This is the same as invoking * {@code findInLine(Pattern.compile(pattern))}. - * + * * @param pattern * a string used to construct a pattern which is in turn used to * match a substring of the input data. @@ -436,7 +435,6 @@ public final class Scanner implements Iterator<String> { * @throws IllegalStateException * if the {@code Scanner} is closed. * @see #findInLine(Pattern) - * @since Android 1.0 */ public String findInLine(String pattern) { return findInLine(Pattern.compile(pattern)); @@ -450,7 +448,7 @@ public final class Scanner implements Iterator<String> { * advance. When waiting for input, the {@code Scanner} may be blocked. * <p> * The {@code Scanner}'s search will never go more than {@code horizon} code points from current - * position. The position of {@code horizon} does have an effect on the result of the + * position. The position of {@code horizon} does have an effect on the result of the * match. For example, when the input is "123" and current position is at zero, * {@code findWithinHorizon(Pattern.compile("\\p{Digit}{3}"), 2)} * will return {@code null}. While @@ -459,10 +457,10 @@ public final class Scanner implements Iterator<String> { * non-anchoring bound. (refer to * {@link Matcher#useTransparentBounds(boolean)} and * {@link Matcher#useAnchoringBounds(boolean)}) - * </p> + * <p> * A {@code horizon} whose value is zero will be ignored and the whole input will be * used for search. In this situation, all the input may be cached. - * + * * @param pattern * the pattern used to scan. * @param horizon @@ -473,7 +471,6 @@ public final class Scanner implements Iterator<String> { * if the {@code Scanner} is closed. * @throws IllegalArgumentException * if {@code horizon} is less than zero. - * @since Android 1.0 */ public String findWithinHorizon(Pattern pattern, int horizon) { checkClosed(); @@ -538,7 +535,7 @@ public final class Scanner implements Iterator<String> { * Tries to find the pattern in the input between the current position and the specified * {@code horizon}. Delimiters are ignored. This call is the same as invoking * {@code findWithinHorizon(Pattern.compile(pattern))}. - * + * * @param pattern * the pattern used to scan. * @param horizon @@ -550,7 +547,6 @@ public final class Scanner implements Iterator<String> { * @throws IllegalArgumentException * if {@code horizon} is less than zero. * @see #findWithinHorizon(Pattern, int) - * @since Android 1.0 */ public String findWithinHorizon(String pattern, int horizon) { return findWithinHorizon(Pattern.compile(pattern), horizon); @@ -559,12 +555,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether this {@code Scanner} has one or more tokens remaining to parse. * This method will block if the data is still being read. - * + * * @return {@code true} if this {@code Scanner} has one or more tokens remaining, * otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNext() { return hasNext(ANY_PATTERN); @@ -574,28 +569,28 @@ public final class Scanner implements Iterator<String> { * Returns whether this {@code Scanner} has one or more tokens remaining to parse * and the next token matches the given pattern. This method will block if the data is * still being read. - * + * * @param pattern * the pattern to check for. * @return {@code true} if this {@code Scanner} has more tokens and the next token * matches the pattern, {@code false} otherwise. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNext(Pattern pattern) { checkClosed(); checkNull(pattern); matchSuccessful = false; saveCurrentStatus(); - //if the next token exists, set the match region, otherwise return false + // if the next token exists, set the match region, otherwise return + // false if (!setTokenRegion()) { recoverPreviousStatus(); return false; } matcher.usePattern(pattern); boolean hasNext = false; - //check whether next token matches the specified pattern + // check whether next token matches the specified pattern if (matcher.matches()) { cachehasNextIndex = findStartIndex; matchSuccessful = true; @@ -605,20 +600,18 @@ public final class Scanner implements Iterator<String> { return hasNext; } - /** * Returns {@code true} if this {@code Scanner} has one or more tokens remaining to parse * and the next token matches a pattern compiled from the given string. This method will * block if the data is still being read. This call is equivalent to * {@code hasNext(Pattern.compile(pattern))}. - * + * * @param pattern * the string specifying the pattern to scan for * @return {@code true} if the specified pattern matches this {@code Scanner}'s * next token, {@code false} otherwise. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNext(String pattern) { return hasNext(Pattern.compile(pattern)); @@ -627,12 +620,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code BigDecimal}. - * + * * @return {@code true} if the next token can be translated into a valid * {@code BigDecimal}, otherwise {@code false.} * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextBigDecimal() { Pattern floatPattern = getFloatPattern(); @@ -653,12 +645,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code BigInteger} in the default radix. - * + * * @return {@code true} if the next token can be translated into a valid * {@code BigInteger}, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextBigInteger() { return hasNextBigInteger(integerRadix); @@ -667,7 +658,7 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code BigInteger} in the specified radix. - * + * * @param radix * the radix used to translate the token into a * {@code BigInteger}. @@ -675,7 +666,6 @@ public final class Scanner implements Iterator<String> { * {@code BigInteger}, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextBigInteger(int radix) { Pattern integerPattern = getIntegerPattern(radix); @@ -696,12 +686,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code boolean} value. - * + * * @return {@code true} if the next token can be translated into a valid * {@code boolean} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextBoolean() { return hasNext(BOOLEAN_PATTERN); @@ -710,12 +699,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code byte} value in the default radix. - * + * * @return {@code true} if the next token can be translated into a valid * {@code byte} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextByte() { return hasNextByte(integerRadix); @@ -724,7 +712,7 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code byte} value in the specified radix. - * + * * @param radix * the radix used to translate the token into a {@code byte} * value @@ -732,7 +720,6 @@ public final class Scanner implements Iterator<String> { * {@code byte} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextByte(int radix) { Pattern integerPattern = getIntegerPattern(radix); @@ -753,12 +740,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token translated into a valid {@code double} * value. - * + * * @return {@code true} if the next token can be translated into a valid * {@code double} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextDouble() { Pattern floatPattern = getFloatPattern(); @@ -779,12 +765,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code float} value. - * + * * @return {@code true} if the next token can be translated into a valid * {@code float} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextFloat() { Pattern floatPattern = getFloatPattern(); @@ -805,12 +790,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid {@code int} * value in the default radix. - * + * * @return {@code true} if the next token can be translated into a valid * {@code int} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed, - * @since Android 1.0 */ public boolean hasNextInt() { return hasNextInt(integerRadix); @@ -819,7 +803,7 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid {@code int} * value in the specified radix. - * + * * @param radix * the radix used to translate the token into an {@code int} * value. @@ -828,7 +812,6 @@ public final class Scanner implements Iterator<String> { * {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextInt(int radix) { Pattern integerPattern = getIntegerPattern(radix); @@ -849,12 +832,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether there is a line terminator in the input. * This method may block. - * + * * @return {@code true} if there is a line terminator in the input, * otherwise, {@code false}. * @throws IllegalStateException * if the {@code Scanner} is closed. - * @since Android 1.0 */ public boolean hasNextLine() { checkClosed(); @@ -886,12 +868,11 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code long} value in the default radix. - * + * * @return {@code true} if the next token can be translated into a valid * {@code long} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextLong() { return hasNextLong(integerRadix); @@ -900,7 +881,7 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code long} value in the specified radix. - * + * * @param radix * the radix used to translate the token into a {@code long} * value. @@ -908,7 +889,6 @@ public final class Scanner implements Iterator<String> { * {@code long} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextLong(int radix) { Pattern integerPattern = getIntegerPattern(radix); @@ -926,16 +906,14 @@ public final class Scanner implements Iterator<String> { return isLongValue; } - /** * Returns whether the next token can be translated into a valid * {@code short} value in the default radix. - * + * * @return {@code true} if the next token can be translated into a valid * {@code short} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextShort() { return hasNextShort(integerRadix); @@ -944,7 +922,7 @@ public final class Scanner implements Iterator<String> { /** * Returns whether the next token can be translated into a valid * {@code short} value in the specified radix. - * + * * @param radix * the radix used to translate the token into a {@code short} * value. @@ -952,7 +930,6 @@ public final class Scanner implements Iterator<String> { * {@code short} value, otherwise {@code false}. * @throws IllegalStateException * if the {@code Scanner} has been closed. - * @since Android 1.0 */ public boolean hasNextShort(int radix) { Pattern integerPattern = getIntegerPattern(radix); @@ -973,9 +950,8 @@ public final class Scanner implements Iterator<String> { /** * Returns the last {@code IOException} that was raised while reading from the underlying * input. - * + * * @return the last thrown {@code IOException}, or {@code null} if none was thrown. - * @since Android 1.0 */ public IOException ioException() { return lastIOException; @@ -983,9 +959,8 @@ public final class Scanner implements Iterator<String> { /** * Return the {@code Locale} of this {@code Scanner}. - * + * * @return the {@code Locale} of this {@code Scanner}. - * @since Android 1.0 */ public Locale locale() { return locale; @@ -996,13 +971,11 @@ public final class Scanner implements Iterator<String> { * <p> * The next* and find* methods return the match result in the case of a * successful match. - * </p> - * + * * @return the match result of the last successful match operation * @throws IllegalStateException * if the match result is not available, of if the last match * was not successful. - * @since Android 1.0 */ public MatchResult match() { if (!matchSuccessful) { @@ -1015,13 +988,12 @@ public final class Scanner implements Iterator<String> { * Returns the next token. The token will be both prefixed and postfixed by * the delimiter that is currently being used (or a string that matches the * delimiter pattern). This method will block if input is being read. - * + * * @return the next complete token. * @throws IllegalStateException * if this {@code Scanner} has been closed. * @throws NoSuchElementException * if input has been exhausted. - * @since Android 1.0 */ public String next() { return next(ANY_PATTERN); @@ -1032,7 +1004,7 @@ public final class Scanner implements Iterator<String> { * will be both prefixed and postfixed by the delimiter that is currently * being used (or a string that matches the delimiter pattern). This method will block * if input is being read. - * + * * @param pattern * the specified pattern to scan. * @return the next token. @@ -1042,7 +1014,6 @@ public final class Scanner implements Iterator<String> { * if input has been exhausted. * @throws InputMismatchException * if the next token does not match the pattern given. - * @since Android 1.0 */ public String next(Pattern pattern) { checkClosed(); @@ -1070,7 +1041,7 @@ public final class Scanner implements Iterator<String> { * being used (or a string that matches the delimiter pattern). This method will block * if input is being read. Calling this methos is equivalent to * {@code next(Pattern.compile(pattern))}. - * + * * @param pattern * the string specifying the pattern to scan for. * @return the next token. @@ -1080,7 +1051,6 @@ public final class Scanner implements Iterator<String> { * if input has been exhausted. * @throws InputMismatchException * if the next token does not match the pattern given. - * @since Android 1.0 */ public String next(String pattern) { return next(Pattern.compile(pattern)); @@ -1095,7 +1065,7 @@ public final class Scanner implements Iterator<String> { * negative sign (-) is added if the {@code Locale}-specific negative prefix or * suffix was present. Finally the resulting string is passed to * {@code BigDecimal(String) }. - * + * * @return the next token as a {@code BigDecimal}. * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1104,7 +1074,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code BigDecimal}. - * @since Android 1.0 */ public BigDecimal nextBigDecimal() { checkClosed(); @@ -1131,7 +1100,7 @@ public final class Scanner implements Iterator<String> { /** * Returns the next token as a {@code BigInteger}. This method will block if input is * being read. Equivalent to {@code nextBigInteger(DEFAULT_RADIX)}. - * + * * @return the next token as {@code BigInteger}. * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1140,7 +1109,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code BigInteger}. - * @since Android 1.0 */ public BigInteger nextBigInteger() { return nextBigInteger(integerRadix); @@ -1156,7 +1124,7 @@ public final class Scanner implements Iterator<String> { * {@code Locale}-specific negative prefix or suffix was present. Finally the * resulting String is passed to {@link BigInteger#BigInteger(String, int)}} * with the specified radix. - * + * * @param radix * the radix used to translate the token into a * {@code BigInteger}. @@ -1168,7 +1136,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code BigInteger}. - * @since Android 1.0 */ public BigInteger nextBigInteger(int radix) { checkClosed(); @@ -1195,7 +1162,7 @@ public final class Scanner implements Iterator<String> { /** * Returns the next token as a {@code boolean}. This method will block if input is * being read. - * + * * @return the next token as a {@code boolean}. * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1204,7 +1171,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code boolean} value. - * @since Android 1.0 */ public boolean nextBoolean() { return Boolean.parseBoolean(next(BOOLEAN_PATTERN)); @@ -1213,7 +1179,7 @@ public final class Scanner implements Iterator<String> { /** * Returns the next token as a {@code byte}. This method will block if input is being * read. Equivalent to {@code nextByte(DEFAULT_RADIX)}. - * + * * @return the next token as a {@code byte}. * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1222,7 +1188,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code byte} value. - * @since Android 1.0 */ public byte nextByte() { return nextByte(integerRadix); @@ -1238,7 +1203,7 @@ public final class Scanner implements Iterator<String> { * {@code Locale}-specific negative prefix or suffix was present. Finally the * resulting String is passed to {@link Byte#parseByte(String, int)}} with * the specified radix. - * + * * @param radix * the radix used to translate the token into {@code byte} value. * @return the next token as a {@code byte}. @@ -1249,7 +1214,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code byte} value. - * @since Android 1.0 */ @SuppressWarnings("boxing") public byte nextByte(int radix) { @@ -1285,7 +1249,7 @@ public final class Scanner implements Iterator<String> { * {@link Double#parseDouble(String)}}. If the token matches the localized * NaN or infinity strings, it is also passed to * {@link Double#parseDouble(String)}}. - * + * * @return the next token as a {@code double}. * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1294,7 +1258,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code double} value. - * @since Android 1.0 */ @SuppressWarnings("boxing") public double nextDouble() { @@ -1330,7 +1293,7 @@ public final class Scanner implements Iterator<String> { * {@link Float#parseFloat(String)}}.If the token matches the localized NaN * or infinity strings, it is also passed to * {@link Float#parseFloat(String)}}. - * + * * @return the next token as a {@code float}. * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1339,7 +1302,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code float} value. - * @since Android 1.0 */ @SuppressWarnings("boxing") public float nextFloat() { @@ -1367,7 +1329,7 @@ public final class Scanner implements Iterator<String> { /** * Returns the next token as an {@code int}. This method will block if input is being * read. Equivalent to {@code nextInt(DEFAULT_RADIX)}. - * + * * @return the next token as an {@code int} * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1376,7 +1338,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code int} value. - * @since Android 1.0 */ public int nextInt() { return nextInt(integerRadix); @@ -1392,7 +1353,7 @@ public final class Scanner implements Iterator<String> { * {@code Locale}-specific negative prefix or suffix was present. Finally the * resulting String is passed to {@link Integer#parseInt(String, int)} with * the specified radix. - * + * * @param radix * the radix used to translate the token into an {@code int} * value. @@ -1404,7 +1365,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code int} value. - * @since Android 1.0 */ @SuppressWarnings("boxing") public int nextInt(int radix) { @@ -1416,7 +1376,7 @@ public final class Scanner implements Iterator<String> { return (Integer) obj; } Pattern integerPattern = getIntegerPattern(radix); - String intString=next(integerPattern); + String intString = next(integerPattern); intString = removeLocaleInfo(intString, DataType.INT); int intValue = 0; try { @@ -1435,13 +1395,12 @@ public final class Scanner implements Iterator<String> { * searching, if no line terminator is found, then a large amount of input * will be cached. If no line at all can be found, a {@code NoSuchElementException} * will be thrown. - * + * * @return the skipped line. * @throws IllegalStateException * if the {@code Scanner} is closed. * @throws NoSuchElementException * if no line can be found, e.g. when input is an empty string. - * @since Android 1.0 */ public String nextLine() { checkClosed(); @@ -1451,7 +1410,8 @@ public final class Scanner implements Iterator<String> { String result = null; while (true) { if (matcher.find()) { - if (inputExhausted || matcher.end() != bufferLength) { + if (inputExhausted || matcher.end() != bufferLength + || bufferLength < buffer.capacity()) { matchSuccessful = true; findStartIndex = matcher.end(); result = matcher.group(); @@ -1466,7 +1426,7 @@ public final class Scanner implements Iterator<String> { if (!inputExhausted) { readMore(); resetMatcher(); - } + } } // Find text without line terminator here. if (null != result) { @@ -1481,7 +1441,7 @@ public final class Scanner implements Iterator<String> { /** * Returns the next token as a {@code long}. This method will block if input is being * read. Equivalent to {@code nextLong(DEFAULT_RADIX)}. - * + * * @return the next token as a {@code long}. * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1490,7 +1450,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code long} value. - * @since Android 1.0 */ public long nextLong() { return nextLong(integerRadix); @@ -1506,7 +1465,7 @@ public final class Scanner implements Iterator<String> { * {@code Locale}-specific negative prefix or suffix was present. Finally the * resulting String is passed to {@link Long#parseLong(String, int)}} with * the specified radix. - * + * * @param radix * the radix used to translate the token into a {@code long} * value. @@ -1518,7 +1477,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code long} value. - * @since Android 1.0 */ @SuppressWarnings("boxing") public long nextLong(int radix) { @@ -1546,7 +1504,7 @@ public final class Scanner implements Iterator<String> { /** * Returns the next token as a {@code short}. This method will block if input is being * read. Equivalent to {@code nextShort(DEFAULT_RADIX)}. - * + * * @return the next token as a {@code short}. * @throws IllegalStateException * if this {@code Scanner} has been closed. @@ -1555,7 +1513,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code short} value. - * @since Android 1.0 */ public short nextShort() { return nextShort(integerRadix); @@ -1571,7 +1528,7 @@ public final class Scanner implements Iterator<String> { * {@code Locale}-specific negative prefix or suffix was present. Finally the * resulting String is passed to {@link Short#parseShort(String, int)}} * with the specified radix. - * + * * @param radix * the radix used to translate the token into {@code short} * value. @@ -1583,7 +1540,6 @@ public final class Scanner implements Iterator<String> { * @throws InputMismatchException * if the next token can not be translated into a valid * {@code short} value. - * @since Android 1.0 */ @SuppressWarnings("boxing") public short nextShort(int radix) { @@ -1610,9 +1566,8 @@ public final class Scanner implements Iterator<String> { /** * Return the radix of this {@code Scanner}. - * + * * @return the radix of this {@code Scanner} - * @since Android 1.0 */ public int radix() { return integerRadix; @@ -1624,8 +1579,8 @@ public final class Scanner implements Iterator<String> { * skipped. If an anchored match of the specified pattern succeeds, the corresponding input * will also be skipped. Otherwise, a {@code NoSuchElementException} will be thrown. * Patterns that can match a lot of input may cause the {@code Scanner} to read - * in a large amount of input. - * + * in a large amount of input. + * * @param pattern * used to skip over input. * @return the {@code Scanner} itself. @@ -1633,7 +1588,6 @@ public final class Scanner implements Iterator<String> { * if the {@code Scanner} is closed. * @throws NoSuchElementException * if the specified pattern match fails. - * @since Android 1.0 */ public Scanner skip(Pattern pattern) { checkClosed(); @@ -1668,14 +1622,13 @@ public final class Scanner implements Iterator<String> { * the constructed pattern to match input starting from the current position. The * delimiter will be ignored. This call is the same as invoke * {@code skip(Pattern.compile(pattern))}. - * + * * @param pattern * the string used to construct a pattern which in turn is used to * match input. * @return the {@code Scanner} itself. * @throws IllegalStateException * if the {@code Scanner} is closed. - * @since Android 1.0 */ public Scanner skip(String pattern) { return skip(Pattern.compile(pattern)); @@ -1684,9 +1637,8 @@ public final class Scanner implements Iterator<String> { /** * Returns a string representation of this {@code Scanner}. The information * returned may be helpful for debugging. The format of the string is unspecified. - * + * * @return a string represendation of this {@code Scanner}. - * @since Android 1.0 */ @Override public String toString() { @@ -1702,11 +1654,10 @@ public final class Scanner implements Iterator<String> { /** * Sets the delimiting pattern of this {@code Scanner}. - * + * * @param pattern * the delimiting pattern to use. * @return this {@code Scanner}. - * @since Android 1.0 */ public Scanner useDelimiter(Pattern pattern) { delimiter = pattern; @@ -1716,11 +1667,10 @@ public final class Scanner implements Iterator<String> { /** * Sets the delimiting pattern of this {@code Scanner} with a pattern compiled from * the supplied string value. - * + * * @param pattern * a string from which a {@code Pattern} can be compiled. * @return this {@code Scanner}. - * @since Android 1.0 */ public Scanner useDelimiter(String pattern) { return useDelimiter(Pattern.compile(pattern)); @@ -1728,11 +1678,10 @@ public final class Scanner implements Iterator<String> { /** * Sets the {@code Locale} of this {@code Scanner} to a specified {@code Locale}. - * + * * @param l * the specified {@code Locale} to use. * @return this {@code Scanner}. - * @since Android 1.0 */ public Scanner useLocale(Locale l) { if (null == l) { @@ -1744,11 +1693,10 @@ public final class Scanner implements Iterator<String> { /** * Sets the radix of this {@code Scanner} to the specified radix. - * + * * @param radix * the specified radix to use. * @return this {@code Scanner}. - * @since Android 1.0 */ public Scanner useRadix(int radix) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { @@ -1761,10 +1709,9 @@ public final class Scanner implements Iterator<String> { /** * Remove is not a supported operation on {@code Scanner}. - * + * * @throws UnsupportedOperationException * if this method is invoked. - * @since Android 1.0 */ public void remove() { throw new UnsupportedOperationException(); @@ -1778,7 +1725,7 @@ public final class Scanner implements Iterator<String> { buffer.limit(0); matcher = delimiter.matcher(buffer); } - + /* * Check the {@code Scanner}'s state, if it is closed, IllegalStateException will be * thrown. @@ -1788,7 +1735,7 @@ public final class Scanner implements Iterator<String> { throw new IllegalStateException(); } } - + /* * Check the inputed pattern. If it is null, then a NullPointerException * will be thrown out. @@ -1824,7 +1771,7 @@ public final class Scanner implements Iterator<String> { private void recoverPreviousStatus() { findStartIndex = preStartIndex; } - + /* * Get integer's pattern */ @@ -1834,12 +1781,12 @@ public final class Scanner implements Iterator<String> { .getString("KA00e", radix)); //$NON-NLS-1$ } decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale); - - String allAvailableDigits="0123456789abcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$ - String ASCIIDigit=allAvailableDigits.substring(0, radix); - String nonZeroASCIIDigit=allAvailableDigits.substring(1, radix); - StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit) //$NON-NLS-1$ + String allAvailableDigits = "0123456789abcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$ + String ASCIIDigit = allAvailableDigits.substring(0, radix); + String nonZeroASCIIDigit = allAvailableDigits.substring(1, radix); + + StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit) //$NON-NLS-1$ .append("]|\\p{javaDigit})"); //$NON-NLS-1$ StringBuilder nonZeroDigit = new StringBuilder("((?i)[").append( //$NON-NLS-1$ nonZeroASCIIDigit).append("]|([\\p{javaDigit}&&[^0]]))"); //$NON-NLS-1$ @@ -1912,16 +1859,16 @@ public final class Scanner implements Iterator<String> { } /* - * Add the {@code Locale}-specific positive prefixes and suffixes to the pattern + * Add the locale specific positive prefixes and suffixes to the pattern */ private StringBuilder addPositiveSign(StringBuilder unSignNumeral) { String positivePrefix = ""; //$NON-NLS-1$ String positiveSuffix = ""; //$NON-NLS-1$ if (!decimalFormat.getPositivePrefix().equals("")) { //$NON-NLS-1$ - positivePrefix = "\\Q" + decimalFormat.getPositivePrefix()+"\\E"; //$NON-NLS-1$ //$NON-NLS-2$ + positivePrefix = "\\Q" + decimalFormat.getPositivePrefix() + "\\E"; //$NON-NLS-1$ //$NON-NLS-2$ } if (!decimalFormat.getPositiveSuffix().equals("")) { //$NON-NLS-1$ - positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix()+"\\E"; //$NON-NLS-1$ //$NON-NLS-2$ + positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix() + "\\E"; //$NON-NLS-1$ //$NON-NLS-2$ } StringBuilder signedNumeral = new StringBuilder() .append(positivePrefix).append(unSignNumeral).append( @@ -1930,16 +1877,16 @@ public final class Scanner implements Iterator<String> { } /* - * Add the {@code Locale} specific negative prefixes and suffixes to the pattern + * Add the locale specific negative prefixes and suffixes to the pattern */ private StringBuilder addNegativeSign(StringBuilder unSignNumeral) { String negativePrefix = ""; //$NON-NLS-1$ String negativeSuffix = ""; //$NON-NLS-1$ if (!decimalFormat.getNegativePrefix().equals("")) { //$NON-NLS-1$ - negativePrefix = "\\Q" + decimalFormat.getNegativePrefix()+"\\E"; //$NON-NLS-1$//$NON-NLS-2$ + negativePrefix = "\\Q" + decimalFormat.getNegativePrefix() + "\\E"; //$NON-NLS-1$//$NON-NLS-2$ } if (!decimalFormat.getNegativeSuffix().equals("")) { //$NON-NLS-1$ - negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix()+"\\E"; //$NON-NLS-1$//$NON-NLS-2$ + negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix() + "\\E"; //$NON-NLS-1$//$NON-NLS-2$ } StringBuilder signedNumeral = new StringBuilder() .append(negativePrefix).append(unSignNumeral).append( @@ -1948,15 +1895,14 @@ public final class Scanner implements Iterator<String> { } /* - * Remove {@code Locale} related information from float String + * Remove locale related information from float String */ private String removeLocaleInfoFromFloat(String floatString) { // If the token is HexFloat - if (-1 != floatString.indexOf('x') - || -1 != floatString.indexOf('X')) { + if (-1 != floatString.indexOf('x') || -1 != floatString.indexOf('X')) { return floatString; } - + int exponentIndex; String decimalNumeralString; String exponentString; @@ -1968,11 +1914,11 @@ public final class Scanner implements Iterator<String> { floatString.length()); decimalNumeralString = removeLocaleInfo(decimalNumeralString, DataType.FLOAT); - return decimalNumeralString + "e" + exponentString; //$NON-NLS-1$ + return decimalNumeralString + "e" + exponentString; //$NON-NLS-1$ } return removeLocaleInfo(floatString, DataType.FLOAT); } - + /* * Remove the locale specific prefixes, group separators, and locale * specific suffixes from input string @@ -2001,12 +1947,12 @@ public final class Scanner implements Iterator<String> { } } if (DataType.FLOAT == type) { - if (tokenBuilder.toString().equals(decimalFormat.getDecimalFormatSymbols() - .getNaN())) { - result.append("NaN");//$NON-NLS-1$ - } else if (tokenBuilder.toString().equals(decimalFormat - .getDecimalFormatSymbols().getInfinity())) { - result.append("Infinity");//$NON-NLS-1$ + if (tokenBuilder.toString().equals( + decimalFormat.getDecimalFormatSymbols().getNaN())) { + result.append("NaN");//$NON-NLS-1$ + } else if (tokenBuilder.toString().equals( + decimalFormat.getDecimalFormatSymbols().getInfinity())) { + result.append("Infinity");//$NON-NLS-1$ } else { for (int i = 0; i < tokenBuilder.length(); i++) { if (-1 != Character.digit(tokenBuilder.charAt(i), 10)) { @@ -2029,8 +1975,9 @@ public final class Scanner implements Iterator<String> { } return result.toString(); } + /* - * remove positive and negative sign from the parameter stringBuilder, and + * Remove positive and negative sign from the parameter stringBuilder, and * return whether the input string is negative */ private boolean removeLocaleSign(StringBuilder tokenBuilder) { @@ -2106,7 +2053,7 @@ public final class Scanner implements Iterator<String> { } /* - * Find prefixed delimiter + * Find prefix delimiter */ private int findPreDelimiter() { int tokenStartIndex; @@ -2166,7 +2113,7 @@ public final class Scanner implements Iterator<String> { } /* - * Find postfixed delimiter + * Find postfix delimiter */ private int findPostDelimiter() { int tokenEndIndex = 0; @@ -2215,7 +2162,8 @@ public final class Scanner implements Iterator<String> { } } catch (IOException e) { // Consider the scenario: readable puts 4 chars into - // buffer and then an IOException is thrown out. In this case, buffer is + // buffer and then an IOException is thrown out. In this case, + // buffer is // actually grown, but readable.read() will never return. bufferLength = buffer.position(); /* @@ -2226,7 +2174,6 @@ public final class Scanner implements Iterator<String> { lastIOException = e; } - buffer.flip(); buffer.position(oldPosition); if (-1 == readCount) { diff --git a/luni/src/main/java/java/util/Set.java b/luni/src/main/java/java/util/Set.java index f52666d..109c8df 100644 --- a/luni/src/main/java/java/util/Set.java +++ b/luni/src/main/java/java/util/Set.java @@ -20,8 +20,8 @@ package java.util; /** * A {@code Set} is a data structure which does not allow duplicate elements. - * - * @since Android 1.0 + * + * @since 1.2 */ public interface Set<E> extends Collection<E> { @@ -38,7 +38,6 @@ public interface Set<E> extends Collection<E> { * when the class of the object is inappropriate for this set. * @throws IllegalArgumentException * when the object cannot be added to this set. - * @since Android 1.0 */ public boolean add(E object); @@ -55,7 +54,6 @@ public interface Set<E> extends Collection<E> { * when the class of an object is inappropriate for this set. * @throws IllegalArgumentException * when an object cannot be added to this set. - * @since Android 1.0 */ public boolean addAll(Collection<? extends E> collection); @@ -66,7 +64,6 @@ public interface Set<E> extends Collection<E> { * when removing from this set is not supported. * @see #isEmpty * @see #size - * @since Android 1.0 */ public void clear(); @@ -77,7 +74,6 @@ public interface Set<E> extends Collection<E> { * the object to search for. * @return {@code true} if object is an element of this set, {@code false} * otherwise. - * @since Android 1.0 */ public boolean contains(Object object); @@ -88,7 +84,6 @@ public interface Set<E> extends Collection<E> { * the collection of objects. * @return {@code true} if all objects in the specified collection are * elements of this set, {@code false} otherwise. - * @since Android 1.0 */ public boolean containsAll(Collection<?> collection); @@ -103,7 +98,6 @@ public interface Set<E> extends Collection<E> { * @return boolean {@code true} if the object is the same as this object, * and {@code false} if it is different from this object. * @see #hashCode - * @since Android 1.0 */ public boolean equals(Object object); @@ -114,7 +108,6 @@ public interface Set<E> extends Collection<E> { * @return the hash code of this set. * * @see #equals - * @since Android 1.0 */ public int hashCode(); @@ -124,7 +117,6 @@ public interface Set<E> extends Collection<E> { * @return {@code true} if this set has no elements, {@code false} * otherwise. * @see #size - * @since Android 1.0 */ public boolean isEmpty(); @@ -134,7 +126,6 @@ public interface Set<E> extends Collection<E> { * * @return an iterator on the elements of this set. * @see Iterator - * @since Android 1.0 */ public Iterator<E> iterator(); @@ -146,7 +137,6 @@ public interface Set<E> extends Collection<E> { * @return {@code true} if this set was modified, {@code false} otherwise. * @throws UnsupportedOperationException * when removing from this set is not supported. - * @since Android 1.0 */ public boolean remove(Object object); @@ -158,7 +148,6 @@ public interface Set<E> extends Collection<E> { * @return {@code true} if this set was modified, {@code false} otherwise. * @throws UnsupportedOperationException * when removing from this set is not supported. - * @since Android 1.0 */ public boolean removeAll(Collection<?> collection); @@ -171,7 +160,6 @@ public interface Set<E> extends Collection<E> { * @return {@code true} if this set was modified, {@code false} otherwise. * @throws UnsupportedOperationException * when removing from this set is not supported. - * @since Android 1.0 */ public boolean retainAll(Collection<?> collection); @@ -179,7 +167,6 @@ public interface Set<E> extends Collection<E> { * Returns the number of elements in this set. * * @return the number of elements in this set. - * @since Android 1.0 */ public int size(); @@ -187,7 +174,6 @@ public interface Set<E> extends Collection<E> { * Returns an array containing all elements contained in this set. * * @return an array of the elements from this set. - * @since Android 1.0 */ public Object[] toArray(); @@ -205,7 +191,6 @@ public interface Set<E> extends Collection<E> { * when the type of an element in this set cannot be stored in * the type of the specified array. * @see Collection#toArray(Object[]) - * @since Android 1.0 */ public <T> T[] toArray(T[] array); } diff --git a/luni/src/main/java/java/util/SimpleTimeZone.java b/luni/src/main/java/java/util/SimpleTimeZone.java index 18d076f..702b6ef 100644 --- a/luni/src/main/java/java/util/SimpleTimeZone.java +++ b/luni/src/main/java/java/util/SimpleTimeZone.java @@ -14,12 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2008, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ + +// BEGIN android-note +// This implementation is based on an old version of Apache Harmony. The current +// Harmony uses ICU4J, which makes it much simpler. We should consider updating +// this implementation to leverage ICU4JNI. +// END android-note package java.util; @@ -27,33 +27,41 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamField; +// BEGIN android-removed +// import java.security.AccessController; +// import java.security.PrivilegedAction; +// END android-removed import org.apache.harmony.luni.util.Msg; -// BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. -// END android-note /** * {@code SimpleTimeZone} is a concrete subclass of {@code TimeZone} * that represents a time zone for use with a Gregorian calendar. This class * does not handle historical changes. - * <P> + * <p> * Use a negative value for {@code dayOfWeekInMonth} to indicate that * {@code SimpleTimeZone} should count from the end of the month * backwards. For example, Daylight Savings Time ends at the last * (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time. - * + * * @see Calendar * @see GregorianCalendar * @see TimeZone - * @since Android 1.0 */ public class SimpleTimeZone extends TimeZone { - + private static final long serialVersionUID = -403250971215465050L; + // BEGIN android-removed + // private static com.ibm.icu.util.TimeZone getICUTimeZone(final String name){ + // return AccessController.doPrivileged(new PrivilegedAction<com.ibm.icu.util.TimeZone>(){ + // public com.ibm.icu.util.TimeZone run() { + // return com.ibm.icu.util.TimeZone.getTimeZone(name); + // } + // }); + // } + // END android-removed + private int rawOffset; private int startYear, startMonth, startDay, startDayOfWeek, startTime; @@ -67,8 +75,6 @@ public class SimpleTimeZone extends TimeZone { /** * The constant for representing a start or end time in GMT time mode. - * - * @since Android 1.0 */ public static final int UTC_TIME = 2; @@ -76,8 +82,6 @@ public class SimpleTimeZone extends TimeZone { * The constant for representing a start or end time in standard local time mode, * based on timezone's raw offset from GMT; does not include Daylight * savings. - * - * @since Android 1.0 */ public static final int STANDARD_TIME = 1; @@ -85,8 +89,6 @@ public class SimpleTimeZone extends TimeZone { * The constant for representing a start or end time in local wall clock time * mode, based on timezone's adjusted offset from GMT; includes * Daylight savings. - * - * @since Android 1.0 */ public static final int WALL_TIME = 0; @@ -96,22 +98,37 @@ public class SimpleTimeZone extends TimeZone { private int dstSavings = 3600000; + // BEGIN android-removed + // private final transient com.ibm.icu.util.TimeZone icuTZ; + // + // private final transient boolean isSimple; + // END android-removed + /** * Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT * and time zone ID. Timezone IDs can be obtained from * {@code TimeZone.getAvailableIDs}. Normally you should use {@code TimeZone.getDefault} to * construct a {@code TimeZone}. - * + * * @param offset * the given base time zone offset to GMT. * @param name * the time zone ID which is obtained from * {@code TimeZone.getAvailableIDs}. - * @since Android 1.0 */ - public SimpleTimeZone(int offset, String name) { + public SimpleTimeZone(int offset, final String name) { setID(name); rawOffset = offset; + // BEGIN android-removed + // icuTZ = getICUTimeZone(name); + // if (icuTZ instanceof com.ibm.icu.util.SimpleTimeZone) { + // isSimple = true; + // icuTZ.setRawOffset(offset); + // } else { + // isSimple = false; + // } + // useDaylight = icuTZ.useDaylightTime(); + // END android-removed } /** @@ -146,8 +163,8 @@ public class SimpleTimeZone extends TimeZone { * The above examples refer to the {@code startMonth}, {@code startDay}, and {@code startDayOfWeek}; * the same applies for the {@code endMonth}, {@code endDay}, and {@code endDayOfWeek}. * <p> - * The daylight savings time difference is set to the default value: one hour. - * + * The daylight savings time difference is set to the default value: one hour. + * * @param offset * the given base time zone offset to GMT. * @param name @@ -182,7 +199,6 @@ public class SimpleTimeZone extends TimeZone { * @throws IllegalArgumentException * if the month, day, dayOfWeek, or time parameters are out of * range for the start or end rule. - * @since Android 1.0 */ public SimpleTimeZone(int offset, String name, int startMonth, int startDay, int startDayOfWeek, int startTime, int endMonth, @@ -193,9 +209,9 @@ public class SimpleTimeZone extends TimeZone { /** * Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT, - * time zone ID, times to start and end the daylight savings time, and - * the daylight savings time difference in milliseconds - * + * time zone ID, times to start and end the daylight savings time, and + * the daylight savings time difference in milliseconds. + * * @param offset * the given base time zone offset to GMT. * @param name @@ -212,7 +228,7 @@ public class SimpleTimeZone extends TimeZone { * description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example. * @param startTime * The daylight savings starting time in local wall time, which - * is standard time in this case. Please see the description of + * is standard time in this case. Please see the description of * {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example. * @param endMonth * the daylight savings ending month. Month is 0-based. eg, 0 for @@ -221,7 +237,7 @@ public class SimpleTimeZone extends TimeZone { * the daylight savings ending day-of-week-in-month. Please see * the description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example. * @param endDayOfWeek - * the daylight savings ending day-of-week. Please see the description of + * the daylight savings ending day-of-week. Please see the description of * {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example. * @param endTime * the daylight savings ending time in local wall time, which is @@ -229,31 +245,50 @@ public class SimpleTimeZone extends TimeZone { * for an example. * @param daylightSavings * the daylight savings time difference in milliseconds. - * @exception IllegalArgumentException - * the month, day, dayOfWeek, or time parameters are out of + * @throws IllegalArgumentException + * if the month, day, dayOfWeek, or time parameters are out of * range for the start or end rule. - * @since Android 1.0 */ public SimpleTimeZone(int offset, String name, int startMonth, int startDay, int startDayOfWeek, int startTime, int endMonth, int endDay, int endDayOfWeek, int endTime, int daylightSavings) { + // BEGIN android-changed + // icuTZ = getICUTimeZone(name); + // if (icuTZ instanceof com.ibm.icu.util.SimpleTimeZone) { + // isSimple = true; + // com.ibm.icu.util.SimpleTimeZone tz = (com.ibm.icu.util.SimpleTimeZone)icuTZ; + // tz.setRawOffset(offset); + // tz.setStartRule(startMonth, startDay, startDayOfWeek, startTime); + // tz.setEndRule(endMonth, endDay, endDayOfWeek, endTime); + // tz.setDSTSavings(daylightSavings); + // } else { + // isSimple = false; + // } + // setID(name); + // rawOffset = offset; this(offset, name); + // END android-changed if (daylightSavings <= 0) { - throw new IllegalArgumentException(Msg.getString("K00e9", daylightSavings)); //$NON-NLS-1$ + throw new IllegalArgumentException(Msg.getString( + "K00e9", daylightSavings)); //$NON-NLS-1$ } dstSavings = daylightSavings; setStartRule(startMonth, startDay, startDayOfWeek, startTime); setEndRule(endMonth, endDay, endDayOfWeek, endTime); + + // BEGIN android-removed + // useDaylight = daylightSavings > 0 || icuTZ.useDaylightTime(); + // END android-removed } /** * Construct a {@code SimpleTimeZone} with the given base time zone offset from GMT, - * time zone ID, times to start and end the daylight savings time including a + * time zone ID, times to start and end the daylight savings time including a * mode specifier, the daylight savings time difference in milliseconds. * The mode specifies either {@link #WALL_TIME}, {@link #STANDARD_TIME}, or * {@link #UTC_TIME}. - * + * * @param offset * the given base time zone offset to GMT. * @param name @@ -269,21 +304,21 @@ public class SimpleTimeZone extends TimeZone { * the daylight savings starting day-of-week. Please see the * description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example. * @param startTime - * the time of day in milliseconds on which daylight savings + * the time of day in milliseconds on which daylight savings * time starts, based on the {@code startTimeMode}. * @param startTimeMode * the mode (UTC, standard, or wall time) of the start time * value. - * @param endDay - * the day of the week on which daylight savings time ends. + * @param endDay + * the day of the week on which daylight savings time ends. * @param endMonth * the daylight savings ending month. The month indexing is 0-based. eg, 0 for * January. * @param endDayOfWeek - * the daylight savings ending day-of-week. Please see the description of + * the daylight savings ending day-of-week. Please see the description of * {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example. * @param endTime - * the time of day in milliseconds on which daylight savings + * the time of day in milliseconds on which daylight savings * time ends, based on the {@code endTimeMode}. * @param endTimeMode * the mode (UTC, standard, or wall time) of the end time value. @@ -292,7 +327,6 @@ public class SimpleTimeZone extends TimeZone { * @throws IllegalArgumentException * if the month, day, dayOfWeek, or time parameters are out of * range for the start or end rule. - * @since Android 1.0 */ public SimpleTimeZone(int offset, String name, int startMonth, int startDay, int startDayOfWeek, int startTime, int startTimeMode, @@ -308,10 +342,9 @@ public class SimpleTimeZone extends TimeZone { /** * Returns a new {@code SimpleTimeZone} with the same ID, {@code rawOffset} and daylight * savings time rules as this SimpleTimeZone. - * + * * @return a shallow copy of this {@code SimpleTimeZone}. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -326,13 +359,12 @@ public class SimpleTimeZone extends TimeZone { * Compares the specified object to this {@code SimpleTimeZone} and returns whether they * are equal. The object must be an instance of {@code SimpleTimeZone} and have the * same internal data. - * + * * @param object * the object to compare with this object. * @return {@code true} if the specified object is equal to this * {@code SimpleTimeZone}, {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -372,6 +404,8 @@ public class SimpleTimeZone extends TimeZone { checkDay(month, day); } + // BEGIN android-changed + // return icuTZ.getOffset(era, year, month, day, dayOfWeek, time); if (!useDaylightTime() || era != GregorianCalendar.AD || year < startYear) { return rawOffset; @@ -389,38 +423,39 @@ public class SimpleTimeZone extends TimeZone { int ruleDay = 0, daysInMonth, firstDayOfMonth = mod7(dayOfWeek - day); if (month == startMonth) { switch (startMode) { - case DOM_MODE: - ruleDay = startDay; - break; - case DOW_IN_MONTH_MODE: - if (startDay >= 0) { - ruleDay = mod7(startDayOfWeek - firstDayOfMonth) + 1 - + (startDay - 1) * 7; - } else { - daysInMonth = GregorianCalendar.DaysInMonth[startMonth]; - if (startMonth == Calendar.FEBRUARY && isLeapYear(year)) { - daysInMonth += 1; + case DOM_MODE: + ruleDay = startDay; + break; + case DOW_IN_MONTH_MODE: + if (startDay >= 0) { + ruleDay = mod7(startDayOfWeek - firstDayOfMonth) + 1 + + (startDay - 1) * 7; + } else { + daysInMonth = GregorianCalendar.DaysInMonth[startMonth]; + if (startMonth == Calendar.FEBRUARY && isLeapYear( + year)) { + daysInMonth += 1; + } + ruleDay = daysInMonth + + 1 + + mod7(startDayOfWeek + - (firstDayOfMonth + daysInMonth)) + + startDay * 7; } - ruleDay = daysInMonth - + 1 + break; + case DOW_GE_DOM_MODE: + ruleDay = startDay + mod7(startDayOfWeek - - (firstDayOfMonth + daysInMonth)) - + startDay * 7; - } - break; - case DOW_GE_DOM_MODE: - ruleDay = startDay - + mod7(startDayOfWeek - - (firstDayOfMonth + startDay - 1)); - break; - case DOW_LE_DOM_MODE: - ruleDay = startDay - + mod7(startDayOfWeek - - (firstDayOfMonth + startDay - 1)); - if (ruleDay != startDay) { - ruleDay -= 7; - } - break; + - (firstDayOfMonth + startDay - 1)); + break; + case DOW_LE_DOM_MODE: + ruleDay = startDay + + mod7(startDayOfWeek + - (firstDayOfMonth + startDay - 1)); + if (ruleDay != startDay) { + ruleDay -= 7; + } + break; } if (ruleDay > day || ruleDay == day && time < startTime) { return rawOffset; @@ -431,36 +466,38 @@ public class SimpleTimeZone extends TimeZone { int nextMonth = (month + 1) % 12; if (month == endMonth || (ruleTime < 0 && nextMonth == endMonth)) { switch (endMode) { - case DOM_MODE: - ruleDay = endDay; - break; - case DOW_IN_MONTH_MODE: - if (endDay >= 0) { - ruleDay = mod7(endDayOfWeek - firstDayOfMonth) + 1 - + (endDay - 1) * 7; - } else { - daysInMonth = GregorianCalendar.DaysInMonth[endMonth]; - if (endMonth == Calendar.FEBRUARY && isLeapYear(year)) { - daysInMonth++; + case DOM_MODE: + ruleDay = endDay; + break; + case DOW_IN_MONTH_MODE: + if (endDay >= 0) { + ruleDay = mod7(endDayOfWeek - firstDayOfMonth) + 1 + + (endDay - 1) * 7; + } else { + daysInMonth = GregorianCalendar.DaysInMonth[endMonth]; + if (endMonth == Calendar.FEBRUARY && isLeapYear(year)) { + daysInMonth++; + } + ruleDay = daysInMonth + + 1 + + mod7(endDayOfWeek + - (firstDayOfMonth + daysInMonth)) + endDay + * 7; } - ruleDay = daysInMonth - + 1 - + mod7(endDayOfWeek - - (firstDayOfMonth + daysInMonth)) + endDay - * 7; - } - break; - case DOW_GE_DOM_MODE: - ruleDay = endDay - + mod7(endDayOfWeek - (firstDayOfMonth + endDay - 1)); - break; - case DOW_LE_DOM_MODE: - ruleDay = endDay - + mod7(endDayOfWeek - (firstDayOfMonth + endDay - 1)); - if (ruleDay != endDay) { - ruleDay -= 7; - } - break; + break; + case DOW_GE_DOM_MODE: + ruleDay = endDay + + mod7( + endDayOfWeek - (firstDayOfMonth + endDay - 1)); + break; + case DOW_LE_DOM_MODE: + ruleDay = endDay + + mod7( + endDayOfWeek - (firstDayOfMonth + endDay - 1)); + if (ruleDay != endDay) { + ruleDay -= 7; + } + break; } int ruleMonth = endMonth; @@ -488,10 +525,13 @@ public class SimpleTimeZone extends TimeZone { } } return rawOffset + dstSavings; + // END android-changed } @Override public int getOffset(long time) { + // BEGIN android-changed + // return icuTZ.getOffset(time); if (!useDaylightTime()) { return rawOffset; } @@ -499,6 +539,7 @@ public class SimpleTimeZone extends TimeZone { daylightSavings = new GregorianCalendar(this); } return daylightSavings.getOffset(time + rawOffset); + // END android-changed } @Override @@ -509,10 +550,9 @@ public class SimpleTimeZone extends TimeZone { /** * Returns an integer hash code for the receiver. Objects which are equal * return the same value for this method. - * + * * @return the receiver's hash. * @see #equals - * @since Android 1.0 */ @Override public synchronized int hashCode() { @@ -548,6 +588,8 @@ public class SimpleTimeZone extends TimeZone { @Override public boolean inDaylightTime(Date time) { + // BEGIN android-changed + // return icuTZ.inDaylightTime(time); // check for null pointer long millis = time.getTime(); if (!useDaylightTime()) { @@ -557,6 +599,7 @@ public class SimpleTimeZone extends TimeZone { daylightSavings = new GregorianCalendar(this); } return daylightSavings.getOffset(millis + rawOffset) != rawOffset; + // END android-changed } private boolean isLeapYear(int year) { @@ -566,17 +609,18 @@ public class SimpleTimeZone extends TimeZone { return year % 4 == 0; } + // BEGIN android-added private int mod7(int num1) { int rem = num1 % 7; return (num1 < 0 && rem < 0) ? 7 + rem : rem; } + // END android-added /** * Sets the daylight savings offset in milliseconds for this {@code SimpleTimeZone}. - * + * * @param milliseconds * the daylight savings offset in milliseconds. - * @since Android 1.0 */ public void setDSTSavings(int milliseconds) { if (milliseconds > 0) { @@ -591,7 +635,8 @@ public class SimpleTimeZone extends TimeZone { throw new IllegalArgumentException(Msg.getString("K00e5", month)); //$NON-NLS-1$ } if (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY) { - throw new IllegalArgumentException(Msg.getString("K00e7", dayOfWeek)); //$NON-NLS-1$ + throw new IllegalArgumentException(Msg + .getString("K00e7", dayOfWeek)); //$NON-NLS-1$ } if (time < 0 || time >= 24 * 3600000) { throw new IllegalArgumentException(Msg.getString("K00e8", time)); //$NON-NLS-1$ @@ -626,7 +671,8 @@ public class SimpleTimeZone extends TimeZone { checkDay(endMonth, endDay); } else { if (endDay < -5 || endDay > 5) { - throw new IllegalArgumentException(Msg.getString("K00f8", endDay)); //$NON-NLS-1$ + throw new IllegalArgumentException(Msg.getString( + "K00f8", endDay)); //$NON-NLS-1$ } } } @@ -637,7 +683,7 @@ public class SimpleTimeZone extends TimeZone { /** * Sets the rule which specifies the end of daylight savings time. - * + * * @param month * the {@code Calendar} month in which daylight savings time ends. * @param dayOfMonth @@ -646,7 +692,6 @@ public class SimpleTimeZone extends TimeZone { * @param time * the time of day in milliseconds standard time on which * daylight savings time ends. - * @since Android 1.0 */ public void setEndRule(int month, int dayOfMonth, int time) { endMonth = month; @@ -654,11 +699,17 @@ public class SimpleTimeZone extends TimeZone { endDayOfWeek = 0; // Initialize this value for hasSameRules() endTime = time; setEndMode(); + // BEGIN android-removed + // if (isSimple) { + // ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month, + // dayOfMonth, time); + // } + // END android-removed } /** * Sets the rule which specifies the end of daylight savings time. - * + * * @param month * the {@code Calendar} month in which daylight savings time ends. * @param day @@ -670,7 +721,6 @@ public class SimpleTimeZone extends TimeZone { * @param time * the time of day in milliseconds standard time on which * daylight savings time ends. - * @since Android 1.0 */ public void setEndRule(int month, int day, int dayOfWeek, int time) { endMonth = month; @@ -678,11 +728,17 @@ public class SimpleTimeZone extends TimeZone { endDayOfWeek = dayOfWeek; endTime = time; setEndMode(); + // BEGIN android-removed + // if (isSimple) { + // ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month, day, + // dayOfWeek, time); + // } + // END android-removed } /** * Sets the rule which specifies the end of daylight savings time. - * + * * @param month * the {@code Calendar} month in which daylight savings time ends. * @param day @@ -695,7 +751,6 @@ public class SimpleTimeZone extends TimeZone { * ends. * @param after * selects the day after or before the day of month. - * @since Android 1.0 */ public void setEndRule(int month, int day, int dayOfWeek, int time, boolean after) { @@ -704,18 +759,26 @@ public class SimpleTimeZone extends TimeZone { endDayOfWeek = -dayOfWeek; endTime = time; setEndMode(); + // BEGIN android-removed + // if (isSimple) { + // ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month, day, + // dayOfWeek, time, after); + // } + // END android-removed } /** * Sets the offset for standard time from GMT for this {@code SimpleTimeZone}. - * + * * @param offset * the offset from GMT of standard time in milliseconds. - * @since Android 1.0 */ @Override public void setRawOffset(int offset) { rawOffset = offset; + // BEGIN android-removed + // icuTZ.setRawOffset(offset); + // END android-removed } private void setStartMode() { @@ -740,7 +803,8 @@ public class SimpleTimeZone extends TimeZone { checkDay(startMonth, startDay); } else { if (startDay < -5 || startDay > 5) { - throw new IllegalArgumentException(Msg.getString("K00f8", startDay)); //$NON-NLS-1$ + throw new IllegalArgumentException(Msg.getString( + "K00f8", startDay)); //$NON-NLS-1$ } } } @@ -751,7 +815,7 @@ public class SimpleTimeZone extends TimeZone { /** * Sets the rule which specifies the start of daylight savings time. - * + * * @param month * the {@code Calendar} month in which daylight savings time starts. * @param dayOfMonth @@ -760,7 +824,6 @@ public class SimpleTimeZone extends TimeZone { * @param time * the time of day in milliseconds on which daylight savings time * starts. - * @since Android 1.0 */ public void setStartRule(int month, int dayOfMonth, int time) { startMonth = month; @@ -768,11 +831,17 @@ public class SimpleTimeZone extends TimeZone { startDayOfWeek = 0; // Initialize this value for hasSameRules() startTime = time; setStartMode(); + // BEGIN android-removed + // if (isSimple) { + // ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month, + // dayOfMonth, time); + // } + // END android-removed } /** * Sets the rule which specifies the start of daylight savings time. - * + * * @param month * the {@code Calendar} month in which daylight savings time starts. * @param day @@ -784,7 +853,6 @@ public class SimpleTimeZone extends TimeZone { * @param time * the time of day in milliseconds on which daylight savings time * starts. - * @since Android 1.0 */ public void setStartRule(int month, int day, int dayOfWeek, int time) { startMonth = month; @@ -792,11 +860,17 @@ public class SimpleTimeZone extends TimeZone { startDayOfWeek = dayOfWeek; startTime = time; setStartMode(); + // BEGIN android-removed + // if (isSimple) { + // ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month, day, + // dayOfWeek, time); + // } + // END android-removed } /** * Sets the rule which specifies the start of daylight savings time. - * + * * @param month * the {@code Calendar} month in which daylight savings time starts. * @param day @@ -809,7 +883,6 @@ public class SimpleTimeZone extends TimeZone { * starts. * @param after * selects the day after or before the day of month. - * @since Android 1.0 */ public void setStartRule(int month, int day, int dayOfWeek, int time, boolean after) { @@ -818,15 +891,20 @@ public class SimpleTimeZone extends TimeZone { startDayOfWeek = -dayOfWeek; startTime = time; setStartMode(); + // BEGIN android-removed + // if (isSimple) { + // ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month, day, + // dayOfWeek, time, after); + // } + // END android-removed } /** * Sets the starting year for daylight savings time in this {@code SimpleTimeZone}. * Years before this start year will always be in standard time. - * + * * @param year * the starting year. - * @since Android 1.0 */ public void setStartYear(int year) { startYear = year; @@ -835,9 +913,8 @@ public class SimpleTimeZone extends TimeZone { /** * Returns the string representation of this {@code SimpleTimeZone}. - * + * * @return the string representation of this {@code SimpleTimeZone}. - * @since Android 1.0 */ @Override public String toString() { @@ -864,7 +941,7 @@ public class SimpleTimeZone extends TimeZone { + endMode + ",endMonth=" + endMonth + ",endDay=" + endDay //$NON-NLS-1$ //$NON-NLS-2$ + ",endDayOfWeek=" //$NON-NLS-1$ + (useDaylight && (endMode != DOM_MODE) ? endDayOfWeek + 1 : 0) - + ",endTime=" + endTime + "]"; //$NON-NLS-1$//$NON-NLS-2$ + + ",endTime=" + endTime + "]"; //$NON-NLS-1$//$NON-NLS-2$ } @Override diff --git a/luni/src/main/java/java/util/SortedMap.java b/luni/src/main/java/java/util/SortedMap.java index 10b2647..2fb25fd 100644 --- a/luni/src/main/java/java/util/SortedMap.java +++ b/luni/src/main/java/java/util/SortedMap.java @@ -21,8 +21,6 @@ package java.util; /** * A map that has its keys ordered. The sorting is according to either the * natural ordering of its keys or the ordering given by a specified comparator. - * - * @since Android 1.0 */ public interface SortedMap<K,V> extends Map<K,V> { @@ -30,7 +28,6 @@ public interface SortedMap<K,V> extends Map<K,V> { * Returns the comparator used to compare keys in this sorted map. * * @return the comparator or {@code null} if the natural order is used. - * @since Android 1.0 */ public Comparator<? super K> comparator(); @@ -38,9 +35,8 @@ public interface SortedMap<K,V> extends Map<K,V> { * Returns the first key in this sorted map. * * @return the first key in this sorted map. - * @exception NoSuchElementException + * @throws NoSuchElementException * if this sorted map is empty. - * @since Android 1.0 */ public K firstKey(); @@ -51,8 +47,7 @@ public interface SortedMap<K,V> extends Map<K,V> { * <p> * Note: The returned map will not allow an insertion of a key outside the * specified range. - * </p> - * + * * @param endKey * the high boundary of the range specified. * @return a sorted map where the keys are less than {@code endKey}. @@ -65,7 +60,6 @@ public interface SortedMap<K,V> extends Map<K,V> { * @throws IllegalArgumentException * if this map is itself a sorted map over a range of another * map and the specified key is outside of its range. - * @since Android 1.0 */ public SortedMap<K,V> headMap(K endKey); @@ -73,9 +67,8 @@ public interface SortedMap<K,V> extends Map<K,V> { * Returns the last key in this sorted map. * * @return the last key in this sorted map. - * @exception NoSuchElementException + * @throws NoSuchElementException * if this sorted map is empty. - * @since Android 1.0 */ public K lastKey(); @@ -87,8 +80,7 @@ public interface SortedMap<K,V> extends Map<K,V> { * <p> * Note: The returned map will not allow an insertion of a key outside the * specified range. - * </p> - * + * * @param startKey * the low boundary of the range (inclusive). * @param endKey @@ -104,7 +96,6 @@ public interface SortedMap<K,V> extends Map<K,V> { * if the start key is greater than the end key, or if this map * is itself a sorted map over a range of another sorted map and * the specified range is outside of its range. - * @since Android 1.0 */ public SortedMap<K,V> subMap(K startKey, K endKey); @@ -115,7 +106,6 @@ public interface SortedMap<K,V> extends Map<K,V> { * <p> * Note: The returned map will not allow an insertion of a key outside the * specified range. - * </p> * * @param startKey * the low boundary of the range specified. @@ -130,7 +120,6 @@ public interface SortedMap<K,V> extends Map<K,V> { * @throws IllegalArgumentException * if this map itself a sorted map over a range of another map * and the specified key is outside of its range. - * @since Android 1.0 */ public SortedMap<K,V> tailMap(K startKey); } diff --git a/luni/src/main/java/java/util/SortedSet.java b/luni/src/main/java/java/util/SortedSet.java index 24fa017..d387540 100644 --- a/luni/src/main/java/java/util/SortedSet.java +++ b/luni/src/main/java/java/util/SortedSet.java @@ -27,7 +27,6 @@ package java.util; * * @see Comparator * @see Comparable - * @since Android 1.0 */ public interface SortedSet<E> extends Set<E> { @@ -35,7 +34,6 @@ public interface SortedSet<E> extends Set<E> { * Returns the comparator used to compare elements in this {@code SortedSet}. * * @return a comparator or null if the natural ordering is used. - * @since Android 1.0 */ public Comparator<? super E> comparator(); @@ -46,7 +44,6 @@ public interface SortedSet<E> extends Set<E> { * @return the first element. * @throws NoSuchElementException * when this {@code SortedSet} is empty. - * @since Android 1.0 */ public E first(); @@ -65,7 +62,6 @@ public interface SortedSet<E> extends Set<E> { * @throws NullPointerException * when the end element is null and this {@code SortedSet} does * not support null elements. - * @since Android 1.0 */ public SortedSet<E> headSet(E end); @@ -76,7 +72,6 @@ public interface SortedSet<E> extends Set<E> { * @return the last element. * @throws NoSuchElementException * when this {@code SortedSet} is empty. - * @since Android 1.0 */ public E last(); @@ -101,7 +96,6 @@ public interface SortedSet<E> extends Set<E> { * {@code SortedSet} does not support null elements. * @throws IllegalArgumentException * when the start element is greater than the end element. - * @since Android 1.0 */ public SortedSet<E> subSet(E start, E end); @@ -120,7 +114,6 @@ public interface SortedSet<E> extends Set<E> { * @throws NullPointerException * when the start element is null and this {@code SortedSet} * does not support null elements. - * @since Android 1.0 */ public SortedSet<E> tailSet(E start); } diff --git a/luni/src/main/java/java/util/Stack.java b/luni/src/main/java/java/util/Stack.java index 8ecb765..1572a08 100644 --- a/luni/src/main/java/java/util/Stack.java +++ b/luni/src/main/java/java/util/Stack.java @@ -17,22 +17,17 @@ package java.util; - /** * {@code Stack} is a Last-In/First-Out(LIFO) data structure which represents a * stack of objects. It enables users to pop to and push from the stack, * including null objects. There is no limit to the size of the stack. - * - * @since Android 1.0 */ public class Stack<E> extends Vector<E> { - + private static final long serialVersionUID = 1224463164541339165L; /** * Constructs a stack with the default size of {@code Vector}. - * - * @since Android 1.0 */ public Stack() { super(); @@ -40,9 +35,8 @@ public class Stack<E> extends Vector<E> { /** * Returns whether the stack is empty or not. - * + * * @return {@code true} if the stack is empty, {@code false} otherwise. - * @since Android 1.0 */ public boolean empty() { return elementCount == 0; @@ -50,16 +44,16 @@ public class Stack<E> extends Vector<E> { /** * Returns the element at the top of the stack without removing it. - * + * * @return the element at the top of the stack. * @throws EmptyStackException * if the stack is empty. * @see #pop - * @since Android 1.0 */ + @SuppressWarnings("unchecked") public synchronized E peek() { try { - return (E)elementData[elementCount - 1]; + return (E) elementData[elementCount - 1]; } catch (IndexOutOfBoundsException e) { throw new EmptyStackException(); } @@ -67,36 +61,35 @@ public class Stack<E> extends Vector<E> { /** * Returns the element at the top of the stack and removes it. - * + * * @return the element at the top of the stack. * @throws EmptyStackException * if the stack is empty. * @see #peek * @see #push - * @since Android 1.0 */ + @SuppressWarnings("unchecked") public synchronized E pop() { - try { - int index = elementCount - 1; - E obj = (E)elementData[index]; - removeElementAt(index); - return obj; - } catch (IndexOutOfBoundsException e) { + if (elementCount == 0) { throw new EmptyStackException(); } + final int index = --elementCount; + final E obj = (E) elementData[index]; + elementData[index] = null; + modCount++; + return obj; } /** * Pushes the specified object onto the top of the stack. - * + * * @param object * The object to be added on top of the stack. * @return the object argument. * @see #peek * @see #pop - * @since Android 1.0 */ - public synchronized E push(E object) { + public E push(E object) { addElement(object); return object; } @@ -104,17 +97,28 @@ public class Stack<E> extends Vector<E> { /** * Returns the index of the first occurrence of the object, starting from * the top of the stack. - * + * * @return the index of the first occurrence of the object, assuming that * the topmost object on the stack has a distance of one. * @param o * the object to be searched. - * @since Android 1.0 */ public synchronized int search(Object o) { - int index = lastIndexOf(o); - if (index >= 0) - return (elementCount - index); + final Object[] dumpArray = elementData; + final int size = elementCount; + if (o != null) { + for (int i = size - 1; i >= 0; i--) { + if (o.equals(dumpArray[i])) { + return size - i; + } + } + } else { + for (int i = size - 1; i >= 0; i--) { + if (dumpArray[i] == null) { + return size - i; + } + } + } return -1; } } diff --git a/luni/src/main/java/java/util/StringTokenizer.java b/luni/src/main/java/java/util/StringTokenizer.java index 3bbeefa..2800283 100644 --- a/luni/src/main/java/java/util/StringTokenizer.java +++ b/luni/src/main/java/java/util/StringTokenizer.java @@ -14,32 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2006, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ package java.util; - -// BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. -// END android-note /** - * <p> * The {@code StringTokenizer} class allows an application to break a string * into tokens by performing code point comparison. The {@code StringTokenizer} * methods do not distinguish among identifiers, numbers, and quoted strings, * nor do they recognize and skip comments. - * </p> * <p> * The set of delimiters (the codepoints that separate tokens) may be specified * either at creation time or on a per-token basis. - * </p> * <p> * An instance of {@code StringTokenizer} behaves in one of three ways, * depending on whether it was created with the {@code returnDelimiters} flag @@ -55,45 +40,40 @@ package java.util; * <p> * A token is thus either one delimiter code point, or a maximal sequence of * consecutive code points that are not delimiters. - * </p> * <p> * A {@code StringTokenizer} object internally maintains a current position * within the string to be tokenized. Some operations advance this current * position past the code point processed. - * </p> * <p> * A token is returned by taking a substring of the string that was used to * create the {@code StringTokenizer} object. - * </p> * <p> * Here's an example of the use of the default delimiter {@code StringTokenizer} * : <blockquote> - * + * * <pre> * StringTokenizer st = new StringTokenizer("this is a test"); * while (st.hasMoreTokens()) { * println(st.nextToken()); * } * </pre> - * + * * </blockquote> - * </p> * <p> * This prints the following output: <blockquote> - * + * * <pre> * this * is * a * test * </pre> - * + * * </blockquote> - * </p> * <p> * Here's an example of how to use a {@code StringTokenizer} with a user * specified delimiter: <blockquote> - * + * * <pre> * StringTokenizer st = new StringTokenizer( * "this is a test with supplementary characters \ud800\ud800\udc00\udc00", @@ -102,12 +82,11 @@ package java.util; * println(st.nextToken()); * } * </pre> - * + * * </blockquote> - * </p> * <p> * This prints the following output: <blockquote> - * + * * <pre> * this * is @@ -119,14 +98,11 @@ package java.util; * \ud800 * \udc00 * </pre> - * + * * </blockquote> - * </p> - * - * @since Android 1.0 */ public class StringTokenizer implements Enumeration<Object> { - + private String string; private String delimiters; @@ -139,10 +115,9 @@ public class StringTokenizer implements Enumeration<Object> { * Constructs a new {@code StringTokenizer} for the parameter string using * whitespace as the delimiter. The {@code returnDelimiters} flag is set to * {@code false}. - * + * * @param string * the string to be tokenized. - * @since Android 1.0 */ public StringTokenizer(String string) { this(string, " \t\n\r\f", false); //$NON-NLS-1$ @@ -154,12 +129,11 @@ public class StringTokenizer implements Enumeration<Object> { * {@code false}. If {@code delimiters} is {@code null}, this constructor * doesn't throw an {@code Exception}, but later calls to some methods might * throw a {@code NullPointerException}. - * + * * @param string * the string to be tokenized. * @param delimiters * the delimiters to use. - * @since Android 1.0 */ public StringTokenizer(String string, String delimiters) { this(string, delimiters, false); @@ -171,14 +145,13 @@ public class StringTokenizer implements Enumeration<Object> { * parameter {@code returnDelimiters} is {@code true}. If {@code delimiters} * is null this constructor doesn't throw an {@code Exception}, but later * calls to some methods might throw a {@code NullPointerException}. - * + * * @param string * the string to be tokenized. * @param delimiters * the delimiters to use. * @param returnDelimiters * {@code true} to return each delimiter as a token. - * @since Android 1.0 */ public StringTokenizer(String string, String delimiters, boolean returnDelimiters) { @@ -193,10 +166,9 @@ public class StringTokenizer implements Enumeration<Object> { /** * Returns the number of unprocessed tokens remaining in the string. - * + * * @return number of tokens that can be retreived before an {@code * Exception} will result from a call to {@code nextToken()}. - * @since Android 1.0 */ public int countTokens() { int count = 0; @@ -221,9 +193,8 @@ public class StringTokenizer implements Enumeration<Object> { /** * Returns {@code true} if unprocessed tokens remain. This method is * implemented in order to satisfy the {@code Enumeration} interface. - * + * * @return {@code true} if unprocessed tokens remain. - * @since Android 1.0 */ public boolean hasMoreElements() { return hasMoreTokens(); @@ -231,11 +202,13 @@ public class StringTokenizer implements Enumeration<Object> { /** * Returns {@code true} if unprocessed tokens remain. - * + * * @return {@code true} if unprocessed tokens remain. - * @since Android 1.0 */ public boolean hasMoreTokens() { + if (delimiters == null) { + throw new NullPointerException(); + } int length = string.length(); if (position < length) { if (returnDelimiters) @@ -253,11 +226,10 @@ public class StringTokenizer implements Enumeration<Object> { /** * Returns the next token in the string as an {@code Object}. This method is * implemented in order to satisfy the {@code Enumeration} interface. - * + * * @return next token in the string as an {@code Object} - * @exception NoSuchElementException + * @throws NoSuchElementException * if no tokens remain. - * @since Android 1.0 */ public Object nextElement() { return nextToken(); @@ -265,13 +237,15 @@ public class StringTokenizer implements Enumeration<Object> { /** * Returns the next token in the string as a {@code String}. - * + * * @return next token in the string as a {@code String}. - * @exception NoSuchElementException + * @throws NoSuchElementException * if no tokens remain. - * @since Android 1.0 */ public String nextToken() { + if (delimiters == null) { + throw new NullPointerException(); + } int i = position; int length = string.length(); @@ -301,20 +275,14 @@ public class StringTokenizer implements Enumeration<Object> { /** * Returns the next token in the string as a {@code String}. The delimiters * used are changed to the specified delimiters. - * + * * @param delims * the new delimiters to use. * @return next token in the string as a {@code String}. - * @exception NoSuchElementException + * @throws NoSuchElementException * if no tokens remain. - * @since Android 1.0 */ public String nextToken(String delims) { - // BEGIN android-added - if (delims == null) { - throw new NullPointerException(); - } - // END android-added this.delimiters = delims; return nextToken(); } diff --git a/luni/src/main/java/java/util/TimeZone.java b/luni/src/main/java/java/util/TimeZone.java index c9709ce..b0bcc6b 100644 --- a/luni/src/main/java/java/util/TimeZone.java +++ b/luni/src/main/java/java/util/TimeZone.java @@ -14,35 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** -******************************************************************************* -* Copyright (C) 1996-2008, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ - -// BEGIN android-note -// The class javadoc and some of the method descriptions are copied from ICU4J -// source files. Changes have been made to the copied descriptions. -// The icu license header was added to this file. -// END android-note package java.util; - import java.io.Serializable; -// BEGIN android-removed -// import java.security.AccessController; -// import java.text.DateFormatSymbols; -// -// import org.apache.harmony.luni.util.PriviAction; -// END android-removed // BEGIN android-added import org.apache.harmony.luni.internal.util.ZoneInfo; import org.apache.harmony.luni.internal.util.ZoneInfoDB; import com.ibm.icu4jni.util.Resources; // END android-added + /** * {@code TimeZone} represents a time zone offset, taking into account * daylight savings. @@ -57,21 +39,21 @@ import com.ibm.icu4jni.util.Resources; * along with a time zone ID. For instance, the time zone ID for the U.S. * Pacific Time zone is "America/Los_Angeles". So, you can get a U.S. Pacific * Time {@code TimeZone} object with the following: <blockquote> - * + * * <pre> * TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); * </pre> - * + * * </blockquote> You can use the {@code getAvailableIDs} method to iterate * through all the supported time zone IDs. You can then choose a supported ID * to get a {@code TimeZone}. If the time zone you want is not * represented by one of the supported IDs, then you can create a custom time * zone ID with the following syntax: <blockquote> - * + * * <pre> * GMT[+|-]hh[[:]mm] * </pre> - * + * * </blockquote> For example, you might specify GMT+14:00 as a custom time zone * ID. The {@code TimeZone} that is returned when you specify a custom * time zone ID does not include daylight savings time. @@ -83,33 +65,26 @@ import com.ibm.icu4jni.util.Resources; * "China Standard Time"), and the Java platform can then only recognize one of * them. * <p> - * Please note the type returned by factory methods, i.e. - * {@code getDefault()} and {@code getTimeZone(String)}, is - * implementation dependent, so it may introduce serialization - * incompatibility issues between different implementations. Android returns - * instances of {@link SimpleTimeZone} so that the bytes serialized by Android - * can be deserialized successfully on other implementations, but the reverse - * compatibility cannot be guaranteed. - * + * Please note the type returned by factory methods, i.e. {@code getDefault()} + * and {@code getTimeZone(String)}, is implementation dependent, so it may + * introduce serialization incompatibility issues between different + * implementations. Android returns instances of {@link SimpleTimeZone} so that + * the bytes serialized by Android can be deserialized successfully on other + * implementations, but the reverse compatibility cannot be guaranteed. + * * @see GregorianCalendar * @see SimpleTimeZone - * @since Android 1.0 */ - public abstract class TimeZone implements Serializable, Cloneable { private static final long serialVersionUID = 3581463369166924961L; /** * The SHORT display name style. - * - * @since Android 1.0 */ public static final int SHORT = 0; /** * The LONG display name style. - * - * @since Android 1.0 */ public static final int LONG = 1; @@ -124,41 +99,49 @@ public abstract class TimeZone implements Serializable, Cloneable { private String ID; // BEGIN android-removed + // private com.ibm.icu.util.TimeZone icuTimeZone = null; + // // private static void initializeAvailable() { // TimeZone[] zones = TimeZones.getTimeZones(); - // AvailableZones = new HashMap<String, TimeZone>((zones.length + 1) * 4 / 3); + // AvailableZones = new HashMap<String, TimeZone>( + // (zones.length + 1) * 4 / 3); // AvailableZones.put(GMT.getID(), GMT); // for (int i = 0; i < zones.length; i++) { // AvailableZones.put(zones[i].getID(), zones[i]); // } + //} + // + // private static boolean isAvailableIDInICU(String name) { + // String[] availableIDs = com.ibm.icu.util.TimeZone.getAvailableIDs(); + // for (int i = 0; i < availableIDs.length; i++) { + // if (availableIDs[i].equals(name)) { + // return true; + // } + // } + // return false; + // } + // + // private static void appendAvailableZones(String name) { + // com.ibm.icu.util.TimeZone icuTZ = com.ibm.icu.util.TimeZone + // .getTimeZone(name); + // int raw = icuTZ.getRawOffset(); + // TimeZone zone = new SimpleTimeZone(raw, name); + // AvailableZones.put(name, zone); // } // END android-removed /** * Constructs a new instance of this class. - * - * @since Android 1.0 */ public TimeZone() { } - private void appendNumber(StringBuffer buffer, int count, int value) { - String string = Integer.toString(value); - if (count > string.length()) { - for (int i = 0; i < count - string.length(); i++) { - buffer.append('0'); - } - } - buffer.append(string); - } - /** * Returns a new {@code TimeZone} with the same ID, {@code rawOffset} and daylight savings * time rules as this {@code TimeZone}. - * + * * @return a shallow copy of this {@code TimeZone}. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override public Object clone() { @@ -173,49 +156,34 @@ public abstract class TimeZone implements Serializable, Cloneable { /** * Gets the available time zone IDs. Any one of these IDs can be passed to * {@code get()} to create the corresponding {@code TimeZone} instance. - * + * * @return an array of time zone ID strings. - * @since Android 1.0 */ public static synchronized String[] getAvailableIDs() { - // BEGIN android-removed - // if (AvailableZones == null) { - // initializeAvailable(); - // } - // int length = AvailableZones.size(); - // String[] answer = new String[length]; - // Iterator<String> keys = AvailableZones.keySet().iterator(); - // for (int i = 0; i < length; i++) { - // answer[i] = keys.next(); - // } - // return answer; - // END android-removed - - // BEGIN android-added + // BEGIN android-changed + // return com.ibm.icu.util.TimeZone.getAvailableIDs(); return ZoneInfoDB.getAvailableIDs(); - // END android-added + // END android-changed } /** * Gets the available time zone IDs which match the specified offset from * GMT. Any one of these IDs can be passed to {@code get()} to create the corresponding * {@code TimeZone} instance. - * + * * @param offset * the offset from GMT in milliseconds. * @return an array of time zone ID strings. - * @since Android 1.0 */ public static synchronized String[] getAvailableIDs(int offset) { - // BEGIN android-removed - // if (AvailableZones == null) { - // initializeAvailable(); - // } - // int count = 0, length = AvailableZones.size(); + // BEGIN android-changed + // String[] availableIDs = com.ibm.icu.util.TimeZone.getAvailableIDs(); + // int count = 0; + // int length = availableIDs.length; // String[] all = new String[length]; - // Iterator<TimeZone> zones = AvailableZones.values().iterator(); // for (int i = 0; i < length; i++) { - // TimeZone tz = zones.next(); + // com.ibm.icu.util.TimeZone tz = com.ibm.icu.util.TimeZone + // .getTimeZone(availableIDs[i]); // if (tz.getRawOffset() == offset) { // all[count++] = tz.getID(); // } @@ -223,23 +191,21 @@ public abstract class TimeZone implements Serializable, Cloneable { // String[] answer = new String[count]; // System.arraycopy(all, 0, answer, 0, count); // return answer; - // END android-removed - - // BEGIN android-added return ZoneInfoDB.getAvailableIDs(offset); - // END android-added - + // END android-changed } /** * Gets the default time zone. - * + * * @return the default time zone. - * @since Android 1.0 */ public static synchronized TimeZone getDefault() { if (Default == null) { + // BEGIN android-changed + // setDefault(null); Default = ZoneInfoDB.getDefault(); + // END android-changed } return (TimeZone) Default.clone(); } @@ -248,9 +214,8 @@ public abstract class TimeZone implements Serializable, Cloneable { * Gets the LONG name for this {@code TimeZone} for the default {@code Locale} in standard * time. If the name is not available, the result is in the format * {@code GMT[+-]hh:mm}. - * + * * @return the {@code TimeZone} name. - * @since Android 1.0 */ public final String getDisplayName() { return getDisplayName(false, LONG, Locale.getDefault()); @@ -260,11 +225,10 @@ public abstract class TimeZone implements Serializable, Cloneable { * Gets the LONG name for this {@code TimeZone} for the specified {@code Locale} in standard * time. If the name is not available, the result is in the format * {@code GMT[+-]hh:mm}. - * + * * @param locale * the {@code Locale}. * @return the {@code TimeZone} name. - * @since Android 1.0 */ public final String getDisplayName(Locale locale) { return getDisplayName(false, LONG, locale); @@ -274,14 +238,13 @@ public abstract class TimeZone implements Serializable, Cloneable { * Gets the specified style of name ({@code LONG} or {@code SHORT}) for this {@code TimeZone} for * the default {@code Locale} in either standard or daylight time as specified. If * the name is not available, the result is in the format {@code GMT[+-]hh:mm}. - * + * * @param daylightTime * {@code true} for daylight time, {@code false} for standard * time. * @param style - * Either {@code LONG} or {@code SHORT}. + * either {@code LONG} or {@code SHORT}. * @return the {@code TimeZone} name. - * @since Android 1.0 */ public final String getDisplayName(boolean daylightTime, int style) { return getDisplayName(daylightTime, style, Locale.getDefault()); @@ -291,39 +254,31 @@ public abstract class TimeZone implements Serializable, Cloneable { * Gets the specified style of name ({@code LONG} or {@code SHORT}) for this {@code TimeZone} for * the specified {@code Locale} in either standard or daylight time as specified. If * the name is not available, the result is in the format {@code GMT[+-]hh:mm}. - * + * * @param daylightTime * {@code true} for daylight time, {@code false} for standard * time. * @param style - * Either LONG or SHORT. + * either LONG or SHORT. * @param locale - * Either {@code LONG} or {@code SHORT}. + * either {@code LONG} or {@code SHORT}. * @return the {@code TimeZone} name. - * @since Android 1.0 */ public String getDisplayName(boolean daylightTime, int style, Locale locale) { + // BEGIN android-changed + // if(icuTimeZone == null || !ID.equals(icuTimeZone.getID())){ + // icuTimeZone = com.ibm.icu.util.TimeZone.getTimeZone(ID); + // } + // return icuTimeZone.getDisplayName( + // daylightTime, style, locale); if (style == SHORT || style == LONG) { boolean useDaylight = daylightTime && useDaylightTime(); - // BEGIN android-removed - // DateFormatSymbols data = new DateFormatSymbols(locale); - // String id = getID(); - // String[][] zones = data.getZoneStrings(); - // for (int i = 0; i < zones.length; i++) { - // if (id.equals(zones[i][0])) { - // return style == SHORT ? zones[i][useDaylight ? 4 : 2] - // : zones[i][useDaylight ? 3 : 1]; - // } - // } - // BEGIN android-removed - - // BEGIN android-added + String result = Resources.getDisplayTimeZone(getID(), daylightTime, style, locale.toString()); if (result != null) { return result; } - // END android-added - + int offset = getRawOffset(); if (useDaylight && this instanceof SimpleTimeZone) { offset += ((SimpleTimeZone) this).getDSTSavings(); @@ -343,13 +298,25 @@ public abstract class TimeZone implements Serializable, Cloneable { return buffer.toString(); } throw new IllegalArgumentException(); + // END android-changed } + // BEGIN android-added + private void appendNumber(StringBuffer buffer, int count, int value) { + String string = Integer.toString(value); + if (count > string.length()) { + for (int i = 0; i < count - string.length(); i++) { + buffer.append('0'); + } + } + buffer.append(string); + } + // END android-added + /** * Gets the ID of this {@code TimeZone}. - * + * * @return the time zone ID string. - * @since Android 1.0 */ public String getID() { return ID; @@ -364,10 +331,9 @@ public abstract class TimeZone implements Serializable, Cloneable { * Subclasses may override to return daylight savings values other than 1 * hour. * <p> - * + * * @return the daylight savings offset in milliseconds if this {@code TimeZone} * observes daylight savings, zero otherwise. - * @since Android 1.0 */ public int getDSTSavings() { if (useDaylightTime()) { @@ -380,11 +346,10 @@ public abstract class TimeZone implements Serializable, Cloneable { * Gets the offset from GMT of this {@code TimeZone} for the specified date. The * offset includes daylight savings time if the specified date is within the * daylight savings time period. - * + * * @param time * the date in milliseconds since January 1, 1970 00:00:00 GMT * @return the offset from GMT in milliseconds. - * @since Android 1.0 */ public int getOffset(long time) { if (inDaylightTime(new Date(time))) { @@ -397,7 +362,7 @@ public abstract class TimeZone implements Serializable, Cloneable { * Gets the offset from GMT of this {@code TimeZone} for the specified date and * time. The offset includes daylight savings time if the specified date and * time are within the daylight savings time period. - * + * * @param era * the {@code GregorianCalendar} era, either {@code GregorianCalendar.BC} or * {@code GregorianCalendar.AD}. @@ -412,39 +377,38 @@ public abstract class TimeZone implements Serializable, Cloneable { * @param time * the time of day in milliseconds. * @return the offset from GMT in milliseconds. - * @since Android 1.0 */ abstract public int getOffset(int era, int year, int month, int day, int dayOfWeek, int time); /** * Gets the offset for standard time from GMT for this {@code TimeZone}. - * + * * @return the offset from GMT in milliseconds. - * @since Android 1.0 */ abstract public int getRawOffset(); /** * Gets the {@code TimeZone} with the specified ID. - * + * * @param name * a time zone string ID. * @return the {@code TimeZone} with the specified ID or null if no {@code TimeZone} with * the specified ID exists. - * @since Android 1.0 */ public static synchronized TimeZone getTimeZone(String name) { - // BEGIN android-removed + // BEGIN android-changed // if (AvailableZones == null) { // initializeAvailable(); // } + // // TimeZone zone = AvailableZones.get(name); - // END android-removed - - // BEGIN android-added + // if(zone == null && isAvailableIDInICU(name)){ + // appendAvailableZones(name); + // zone = AvailableZones.get(name); + // } TimeZone zone = ZoneInfo.getTimeZone(name); - // END android-added + // END android-changed if (zone == null) { if (name.startsWith("GMT") && name.length() > 3) { char sign = name.charAt(3); @@ -513,12 +477,11 @@ public abstract class TimeZone implements Serializable, Cloneable { /** * Returns whether the specified {@code TimeZone} has the same raw offset as this * {@code TimeZone}. - * + * * @param zone * a {@code TimeZone}. * @return {@code true} when the {@code TimeZone} have the same raw offset, {@code false} * otherwise. - * @since Android 1.0 */ public boolean hasSameRules(TimeZone zone) { if (zone == null) { @@ -530,12 +493,11 @@ public abstract class TimeZone implements Serializable, Cloneable { /** * Returns whether the specified {@code Date} is in the daylight savings time period for * this {@code TimeZone}. - * + * * @param time * a {@code Date}. * @return {@code true} when the {@code Date} is in the daylight savings time period, {@code false} * otherwise. - * @since Android 1.0 */ abstract public boolean inDaylightTime(Date time); @@ -555,34 +517,30 @@ public abstract class TimeZone implements Serializable, Cloneable { * time {@link #getDefault} is called, the default time zone will be * determined. This behavior is slightly different than the canonical * description of this method, but it follows the spirit of it. - * + * * @param timezone * a {@code TimeZone} object. - * @since Android 1.0 */ public static synchronized void setDefault(TimeZone timezone) { // BEGIN android-removed // if (timezone != null) { + // setICUDefaultTimeZone(timezone); // Default = timezone; // return; // } - // END android-removed - - // BEGIN android-added - Default = timezone; - - // TODO Not sure if this is spec-compliant. Shouldn't be persistent. - ZoneInfoDB.setDefault(timezone); - // END android-added - - // BEGIN android-removed + // // String zone = AccessController.doPrivileged(new PriviAction<String>( - // "user.timezone")); + // "user.timezone")); + // + // // sometimes DRLVM incorrectly adds "\n" to the end of timezone ID + // if (zone != null && zone.contains("\n")) { + // zone = zone.substring(0, zone.indexOf("\n")); + // } // // // if property user.timezone is not set, we call the native method // // getCustomTimeZone - // if (zone == null) { - // int[] tzinfo = new int[10]; + // if (zone == null || zone.length() == 0) { + // int[] tzinfo = new int[10]; // boolean[] isCustomTimeZone = new boolean[1]; // // String zoneId = getCustomTimeZone(tzinfo, isCustomTimeZone); @@ -609,15 +567,45 @@ public abstract class TimeZone implements Serializable, Cloneable { // // if property user.timezone is set in command line (with -D option) // Default = getTimeZone(zone); // } + // setICUDefaultTimeZone(Default); // END android-removed + + // BEGIN android-added + Default = timezone; + + // TODO Not sure if this is spec-compliant. Shouldn't be persistent. + ZoneInfoDB.setDefault(timezone); + // END android-added } + // BEGIN android-removed + // private static void setICUDefaultTimeZone(TimeZone timezone) { + // final com.ibm.icu.util.TimeZone icuTZ = com.ibm.icu.util.TimeZone + // .getTimeZone(timezone.getID()); + // + // AccessController + // .doPrivileged(new PrivilegedAction<java.lang.reflect.Field>() { + // public java.lang.reflect.Field run() { + // java.lang.reflect.Field field = null; + // try { + // field = com.ibm.icu.util.TimeZone.class + // .getDeclaredField("defaultZone"); + // field.setAccessible(true); + // field.set("defaultZone", icuTZ); + // } catch (Exception e) { + // return null; + // } + // return field; + // } + // }); + // } + // END android-removed + /** * Sets the ID of this {@code TimeZone}. - * + * * @param name * a string which is the time zone ID. - * @since Android 1.0 */ public void setID(String name) { if (name == null) { @@ -628,44 +616,40 @@ public abstract class TimeZone implements Serializable, Cloneable { /** * Sets the offset for standard time from GMT for this {@code TimeZone}. - * + * * @param offset * the offset from GMT in milliseconds. - * @since Android 1.0 */ abstract public void setRawOffset(int offset); /** * Returns whether this {@code TimeZone} has a daylight savings time period. - * + * * @return {@code true} if this {@code TimeZone} has a daylight savings time period, {@code false} * otherwise. - * @since Android 1.0 */ abstract public boolean useDaylightTime(); - // BEGIN android-removed - // /** - // * Gets the name and the details of the user-selected TimeZone on the - // * device. - // * - // * @param tzinfo - // * int array of 10 elements to be filled with the TimeZone - // * information. Once filled, the contents of the array are - // * formatted as follows: tzinfo[0] -> the timezone offset; - // * tzinfo[1] -> the dst adjustment; tzinfo[2] -> the dst start - // * hour; tzinfo[3] -> the dst start day of week; tzinfo[4] -> the - // * dst start week of month; tzinfo[5] -> the dst start month; - // * tzinfo[6] -> the dst end hour; tzinfo[7] -> the dst end day of - // * week; tzinfo[8] -> the dst end week of month; tzinfo[9] -> the - // * dst end month; - // * @param isCustomTimeZone - // * boolean array of size 1 that indicates if a timezone - // * match is found - // * @return the name of the TimeZone or null if error occurs in native - // * method. - // */ - // private static native String getCustomTimeZone(int[] tzinfo, - // boolean[] isCustomTimeZone); - // END android-removed + /** + * Gets the name and the details of the user-selected TimeZone on the + * device. + * + * @param tzinfo + * int array of 10 elements to be filled with the TimeZone + * information. Once filled, the contents of the array are + * formatted as follows: tzinfo[0] -> the timezone offset; + * tzinfo[1] -> the dst adjustment; tzinfo[2] -> the dst start + * hour; tzinfo[3] -> the dst start day of week; tzinfo[4] -> the + * dst start week of month; tzinfo[5] -> the dst start month; + * tzinfo[6] -> the dst end hour; tzinfo[7] -> the dst end day of + * week; tzinfo[8] -> the dst end week of month; tzinfo[9] -> the + * dst end month; + * @param isCustomTimeZone + * boolean array of size 1 that indicates if a timezone match is + * found + * @return the name of the TimeZone or null if error occurs in native + * method. + */ + private static native String getCustomTimeZone(int[] tzinfo, + boolean[] isCustomTimeZone); } diff --git a/luni/src/main/java/java/util/Timer.java b/luni/src/main/java/java/util/Timer.java index ccff929..48970be 100644 --- a/luni/src/main/java/java/util/Timer.java +++ b/luni/src/main/java/java/util/Timer.java @@ -29,145 +29,143 @@ import org.apache.harmony.luni.util.Msg; * excessive amount of time to run it may impact the time at which subsequent * tasks may run. * <p> - * + * * The {@code TimerTask} does not offer any guarantees about the real-time nature of * scheduling tasks as its underlying implementation relies on the * {@code Object.wait(long)} method. - * </p> * <p> * Multiple threads can share a single {@code Timer} without the need for their own - * synchronization.</p> + * synchronization. * <p> - * A {@code Timer} can be set to schedule tasks either at a fixed rate or - * with a fixed period. Fixed-period execution is the default.</p> + * A {@code Timer} can be set to schedule tasks either at a fixed rate or + * with a fixed period. Fixed-period execution is the default. * <p> - * The difference between fixed-rate and fixed-period execution - * is the following: With fixed-rate execution, the start time of each + * The difference between fixed-rate and fixed-period execution + * is the following: With fixed-rate execution, the start time of each * successive run of the task is scheduled in absolute terms without regard for when the previous - * task run actually took place. This can result in a series of bunched-up runs - * (one launched immediately after another) if busy resources or other + * task run actually took place. This can result in a series of bunched-up runs + * (one launched immediately after another) if busy resources or other * system delays prevent the {@code Timer} from firing for an extended time. - * With fixed-period execution, each successive run of the - * task is scheduled relative to the start time of the previous run of the - * task, so two runs of the task are never fired closer together in time than - * the specified {@code period}.</p> - * </p> - * + * With fixed-period execution, each successive run of the + * task is scheduled relative to the start time of the previous run of the + * task, so two runs of the task are never fired closer together in time than + * the specified {@code period}. + * * @see TimerTask * @see java.lang.Object#wait(long) - * @since Android 1.0 */ public class Timer { private static final class TimerImpl extends Thread { - private static final class TimerNode { - TimerNode parent, left, right; + private static final class TimerHeap { + private int DEFAULT_HEAP_SIZE = 256; + + private TimerTask[] timers = new TimerTask[DEFAULT_HEAP_SIZE]; - TimerTask task; + private int size = 0; - public TimerNode(TimerTask value) { - this.task = value; + private int deletedCancelledNumber = 0; + + public TimerTask minimum() { + return timers[0]; } - public void deleteIfCancelled(TimerTree tasks) { - /* - * All changes in the tree structure during deleting this node - * affect only the structure of the subtree having this node as - * its root - */ - if (left != null) { - left.deleteIfCancelled(tasks); - } - if (right != null) { - right.deleteIfCancelled(tasks); - } - if (task.cancelled) { - tasks.delete(this); - tasks.deletedCancelledNumber++; + public boolean isEmpty() { + return size == 0; + } + + public void insert(TimerTask task) { + if (timers.length == size) { + TimerTask[] appendedTimers = new TimerTask[size * 2]; + System.arraycopy(timers, 0, appendedTimers, 0, size); + timers = appendedTimers; } + timers[size++] = task; + upHeap(); } - } - private static final class TimerTree { + public void delete(int pos) { + // posible to delete any position of the heap + if (pos >= 0 && pos < size) { + timers[pos] = timers[--size]; + timers[size] = null; + downHeap(pos); + } + } - int deletedCancelledNumber; + private void upHeap() { + int current = size - 1; + int parent = (current - 1) / 2; - TimerNode root; + while (timers[current].when < timers[parent].when) { + // swap the two + TimerTask tmp = timers[current]; + timers[current] = timers[parent]; + timers[parent] = tmp; - boolean isEmpty() { - return root == null; + // update pos and current + current = parent; + parent = (current - 1) / 2; + } } - void insert(TimerNode z) { - TimerNode y = null, x = root; - while (x != null) { - y = x; - if (z.task.getWhen() < x.task.getWhen()) { - x = x.left; - } else { - x = x.right; + private void downHeap(int pos) { + int current = pos; + int child = 2 * current + 1; + + while (child < size && size > 0) { + // compare the children if they exist + if (child + 1 < size + && timers[child + 1].when < timers[child].when) { + child++; } - } - z.parent = y; - if (y == null) { - root = z; - } else if (z.task.getWhen() < y.task.getWhen()) { - y.left = z; - } else { - y.right = z; + + // compare selected child with parent + if (timers[current].when < timers[child].when) { + break; + } + + // swap the two + TimerTask tmp = timers[current]; + timers[current] = timers[child]; + timers[child] = tmp; + + // update pos and current + current = child; + child = 2 * current + 1; } } - void delete(TimerNode z) { - TimerNode y = null, x = null; - if (z.left == null || z.right == null) { - y = z; - } else { - y = successor(z); - } - if (y.left != null) { - x = y.left; - } else { - x = y.right; - } - if (x != null) { - x.parent = y.parent; - } - if (y.parent == null) { - root = x; - } else if (y == y.parent.left) { - y.parent.left = x; - } else { - y.parent.right = x; - } - if (y != z) { - z.task = y.task; - } + public void reset() { + timers = new TimerTask[DEFAULT_HEAP_SIZE]; + size = 0; } - private TimerNode successor(TimerNode x) { - if (x.right != null) { - return minimum(x.right); - } - TimerNode y = x.parent; - while (y != null && x == y.right) { - x = y; - y = y.parent; - } - return y; + public void adjustMinimum() { + downHeap(0); } - private TimerNode minimum(TimerNode x) { - while (x.left != null) { - x = x.left; + public void deleteIfCancelled() { + for (int i = 0; i < size; i++) { + if (timers[i].cancelled) { + deletedCancelledNumber++; + delete(i); + // re-try this point + i--; + } } - return x; } - TimerNode minimum() { - return minimum(root); + private int getTask(TimerTask task) { + for (int i = 0; i < timers.length; i++) { + if (timers[i] == task) { + return i; + } + } + return -1; } + } /** @@ -185,11 +183,11 @@ public class Timer { * Vector consists of scheduled events, sorted according to * {@code when} field of TaskScheduled object. */ - private TimerTree tasks = new TimerTree(); + private TimerHeap tasks = new TimerHeap(); /** * Starts a new timer. - * + * * @param isDaemon */ TimerImpl(boolean isDaemon) { @@ -230,13 +228,12 @@ public class Timer { long currentTime = System.currentTimeMillis(); - TimerNode taskNode = tasks.minimum(); - task = taskNode.task; + task = tasks.minimum(); long timeToSleep; synchronized (task.lock) { if (task.cancelled) { - tasks.delete(taskNode); + tasks.delete(0); continue; } @@ -257,8 +254,12 @@ public class Timer { // no sleep is necessary before launching the task synchronized (task.lock) { + int pos = 0; + if (tasks.minimum().when != task.when) { + pos = tasks.getTask(task); + } if (task.cancelled) { - tasks.delete(taskNode); + tasks.delete(tasks.getTask(task)); continue; } @@ -266,7 +267,7 @@ public class Timer { task.setScheduledTime(task.when); // remove task from queue - tasks.delete(taskNode); + tasks.delete(pos); // set when the next task should be launched if (task.period >= 0) { @@ -299,7 +300,7 @@ public class Timer { private void insertTask(TimerTask newTask) { // callers are synchronized - tasks.insert(new TimerNode(newTask)); + tasks.insert(newTask); this.notify(); } @@ -308,7 +309,7 @@ public class Timer { */ public synchronized void cancel() { cancelled = true; - tasks = new TimerTree(); + tasks.reset(); this.notify(); } @@ -318,7 +319,7 @@ public class Timer { } // callers are synchronized tasks.deletedCancelledNumber = 0; - tasks.root.deleteIfCancelled(tasks); + tasks.deleteIfCancelled(); return tasks.deletedCancelledNumber; } @@ -329,71 +330,72 @@ public class Timer { // Used to finalize thread @SuppressWarnings("unused") - private Object finalizer = new Object() { // $NON-LOCK-1$ - @Override - protected void finalize() { - synchronized (impl) { - impl.finished = true; - impl.notify(); - } - } - }; + 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. - * @since Android 1.0 */ 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}. - * - * @since Android 1.0 */ public Timer() { // BEGIN android-changed impl = new TimerImpl("java.util.Timer", false); // END android-changed + finalizer = newFinalizer(); } /** * 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. - * @since Android 1.0 */ public Timer(String name, boolean isDaemon) { impl = new TimerImpl(name, isDaemon); + finalizer = newFinalizer(); } /** * Creates a new named {@code Timer} which does not run as a daemon thread. - * + * * @param name * the name of the Timer. - * @since Android 1.0 */ public Timer(String name) { impl = new TimerImpl(name, false); + finalizer = newFinalizer(); + } + + private Object newFinalizer() { + return new Object() { // $NON-LOCK-1$ + @Override + protected void finalize() { + synchronized (impl) { + impl.finished = true; + impl.notify(); + } + } + }; } /** * Cancels the {@code Timer} and removes any scheduled tasks. If there is a * currently running task it is not affected. No more tasks may be scheduled * on this {@code Timer}. Subsequent calls do nothing. - * - * @since Android 1.0 */ public void cancel() { impl.cancel(); @@ -401,12 +403,11 @@ public class Timer { /** * Removes all canceled tasks from the task queue. If there are no - * other references on the tasks, then after this call they are free + * other references on the tasks, then after this call they are free * to be garbage collected. - * + * * @return the number of canceled tasks that were removed from the task * queue. - * @since Android 1.0 */ public int purge() { synchronized (impl) { @@ -417,17 +418,16 @@ public class Timer { /** * Schedule a task for single execution. If {@code when} is less than the * current time, it will be scheduled to be executed as soon as possible. - * + * * @param task * the task to schedule. * @param when * time of execution. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code when.getTime() < 0}. - * @exception IllegalStateException + * @throws IllegalStateException * if the {@code Timer} has been canceled, or if the task has been * scheduled or canceled. - * @since Android 1.0 */ public void schedule(TimerTask task, Date when) { if (when.getTime() < 0) { @@ -439,17 +439,16 @@ public class Timer { /** * Schedule a task for single execution after a specified delay. - * + * * @param task * the task to schedule. * @param delay * amount of time before execution. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code delay < 0}. - * @exception IllegalStateException + * @throws IllegalStateException * if the {@code Timer} has been canceled, or if the task has been * scheduled or canceled. - * @since Android 1.0 */ public void schedule(TimerTask task, long delay) { if (delay < 0) { @@ -460,19 +459,18 @@ public class Timer { /** * Schedule a task for repeated fixed-delay execution after a specific delay. - * + * * @param task * the task to schedule. * @param delay * amount of time before first execution. * @param period * amount of time between subsequent executions. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code delay < 0} or {@code period < 0}. - * @exception IllegalStateException + * @throws IllegalStateException * if the {@code Timer} has been canceled, or if the task has been * scheduled or canceled. - * @since Android 1.0 */ public void schedule(TimerTask task, long delay, long period) { if (delay < 0 || period <= 0) { @@ -484,19 +482,18 @@ public class Timer { /** * Schedule a task for repeated fixed-delay execution after a specific time * has been reached. - * + * * @param task * the task to schedule. * @param when * time of first execution. * @param period * amount of time between subsequent executions. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code when.getTime() < 0} or {@code period < 0}. - * @exception IllegalStateException + * @throws IllegalStateException * if the {@code Timer} has been canceled, or if the task has been * scheduled or canceled. - * @since Android 1.0 */ public void schedule(TimerTask task, Date when, long period) { if (period <= 0 || when.getTime() < 0) { @@ -509,19 +506,18 @@ public class Timer { /** * Schedule a task for repeated fixed-rate execution after a specific delay * has passed. - * + * * @param task * the task to schedule. * @param delay * amount of time before first execution. * @param period * amount of time between subsequent executions. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code delay < 0} or {@code period < 0}. - * @exception IllegalStateException + * @throws IllegalStateException * if the {@code Timer} has been canceled, or if the task has been * scheduled or canceled. - * @since Android 1.0 */ public void scheduleAtFixedRate(TimerTask task, long delay, long period) { if (delay < 0 || period <= 0) { @@ -533,19 +529,18 @@ public class Timer { /** * Schedule a task for repeated fixed-rate execution after a specific time * has been reached. - * + * * @param task * the task to schedule. * @param when * time of first execution. * @param period * amount of time between subsequent executions. - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if {@code when.getTime() < 0} or {@code period < 0}. - * @exception IllegalStateException + * @throws IllegalStateException * if the {@code Timer} has been canceled, or if the task has been * scheduled or canceled. - * @since Android 1.0 */ public void scheduleAtFixedRate(TimerTask task, Date when, long period) { if (period <= 0 || when.getTime() < 0) { @@ -555,13 +550,8 @@ public class Timer { scheduleImpl(task, delay < 0 ? 0 : delay, period, true); } - /** + /* * Schedule a task. - * - * @param task - * @param delay - * @param period - * @param fixed */ private void scheduleImpl(TimerTask task, long delay, long period, boolean fixed) { diff --git a/luni/src/main/java/java/util/TimerTask.java b/luni/src/main/java/java/util/TimerTask.java index 384746f..319ed58 100644 --- a/luni/src/main/java/java/util/TimerTask.java +++ b/luni/src/main/java/java/util/TimerTask.java @@ -23,7 +23,6 @@ package java.util; * * @see Timer * @see java.lang.Object#wait(long) - * @since Android 1.0 */ public abstract class TimerTask implements Runnable { /* Lock object for synchronization. It's also used by Timer class. */ @@ -77,8 +76,6 @@ public abstract class TimerTask implements Runnable { /** * Creates a new {@code TimerTask}. - * - * @since Android 1.0 */ protected TimerTask() { super(); @@ -91,7 +88,6 @@ public abstract class TimerTask implements Runnable { * * @return {@code true} if the call prevented a scheduled execution * from taking place, {@code false} otherwise. - * @since Android 1.0 */ public boolean cancel() { synchronized (lock) { @@ -107,7 +103,6 @@ public abstract class TimerTask implements Runnable { * have not yet run return an undefined value. * * @return the most recent execution time. - * @since Android 1.0 */ public long scheduledExecutionTime() { synchronized (lock) { @@ -118,8 +113,6 @@ public abstract class TimerTask implements Runnable { /** * The task to run should be specified in the implementation of the {@code run()} * method. - * - * @since Android 1.0 */ public abstract void run(); diff --git a/luni/src/main/java/java/util/TooManyListenersException.java b/luni/src/main/java/java/util/TooManyListenersException.java index 32b2133..8c044c0 100644 --- a/luni/src/main/java/java/util/TooManyListenersException.java +++ b/luni/src/main/java/java/util/TooManyListenersException.java @@ -22,8 +22,6 @@ package java.util; * A {@code TooManyListenersException} is thrown when an attempt is made to add * more than one listener to an event source which only supports a single * listener. It is also thrown when the same listener is added more than once. - * - * @since Android 1.0 */ public class TooManyListenersException extends Exception { diff --git a/luni/src/main/java/java/util/TreeMap.java b/luni/src/main/java/java/util/TreeMap.java index e3dc5a7..b97821f 100644 --- a/luni/src/main/java/java/util/TreeMap.java +++ b/luni/src/main/java/java/util/TreeMap.java @@ -27,43 +27,124 @@ import java.io.Serializable; * and removing) are supported. The values can be any objects. The keys can be * any objects which are comparable to each other either using their natural * order or a specified Comparator. - * - * @since Android 1.0 + * + * @since 1.2 */ -public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, Cloneable, - Serializable { +public class TreeMap <K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, + Cloneable, Serializable { private static final long serialVersionUID = 919286545866124006L; transient int size; - transient Entry<K, V> root; - private Comparator<? super K> comparator; transient int modCount; transient Set<Map.Entry<K, V>> entrySet; - /** - * Entry is an internal class which is used to hold the entries of a - * TreeMap. - */ - static class Entry<K, V> extends MapEntry<K, V> { - Entry<K, V> parent, left, right; - + transient Node<K, V> root; + +class MapEntry implements Map.Entry<K, V>, Cloneable { + + final int offset; + final Node<K, V> node; + final K key; + + MapEntry(Node<K, V> node, int offset) { + this.node = node; + this.offset = offset; + key = node.keys[offset]; + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof Map.Entry) { + Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object; + V value = getValue(); + return (key == null ? entry.getKey() == null : key.equals(entry + .getKey())) + && (value == null ? entry.getValue() == null : value + .equals(entry.getValue())); + } + return false; + } + + public K getKey() { + return key; + } + + public V getValue() { + if (node.keys[offset] == key) { + return node.values[offset]; + } + if (containsKey(key)) { + return get(key); + } + throw new IllegalStateException(); + } + + @Override + public int hashCode() { + V value = getValue(); + return (key == null ? 0 : key.hashCode()) + ^ (value == null ? 0 : value.hashCode()); + } + + public V setValue(V object) { + if (node.keys[offset] == key) { + V res = node.values[offset]; + node.values[offset] = object; + return res; + } + if (containsKey(key)) { + return put(key, object); + } + throw new IllegalStateException(); + } + + @Override + public String toString() { + return key + "=" + getValue(); + } + } + + static class Node <K,V> implements Cloneable { + static final int NODE_SIZE = 64; + Node<K, V> prev, next; + Node<K, V> parent, left, right; + V[] values; + K[] keys; + int left_idx = 0; + int right_idx = -1; + int size = 0; boolean color; - Entry(K key) { - super(key); - } - - Entry(K key, V value) { - super(key, value); + public Node() { + keys = (K[]) new Object[NODE_SIZE]; + values = (V[]) new Object[NODE_SIZE]; } @SuppressWarnings("unchecked") - Entry<K, V> clone(Entry<K, V> parent) { - Entry<K, V> clone = (Entry<K, V>) super.clone(); + Node<K, V> clone(Node<K, V> parent) throws CloneNotSupportedException { + Node<K, V> clone = (Node<K, V>) super.clone(); + clone.keys = (K[]) new Object[NODE_SIZE]; + clone.values = (V[]) new Object[NODE_SIZE]; + System.arraycopy(keys, 0, clone.keys, 0, keys.length); + System.arraycopy(values, 0, clone.values, 0, values.length); + clone.left_idx = left_idx; + clone.right_idx = right_idx; clone.parent = parent; if (left != null) { clone.left = left.clone(clone); @@ -71,35 +152,68 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, if (right != null) { clone.right = right.clone(clone); } + clone.prev = null; + clone.next = null; return clone; } } - + @SuppressWarnings("unchecked") - private static <T> Comparable<T> toComparable(T obj) { - return (Comparable<T>)obj; + private static <T> Comparable<T> toComparable(T obj) { + return (Comparable) obj; } - private static class AbstractMapIterator <K,V> { + static class AbstractMapIterator <K,V> { TreeMap<K, V> backingMap; int expectedModCount; - TreeMap.Entry<K, V> node; - TreeMap.Entry<K, V> lastNode; + Node<K, V> node; + Node<K, V> lastNode; + int offset; + int lastOffset; - AbstractMapIterator(TreeMap<K, V> map, Entry<K, V> startNode) { + AbstractMapIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) { backingMap = map; expectedModCount = map.modCount; node = startNode; + offset = startOffset; + } + + AbstractMapIterator(TreeMap<K, V> map, Node<K, V> startNode) { + this(map, startNode, startNode != null ? + startNode.right_idx - startNode.left_idx : 0); + } + + AbstractMapIterator(TreeMap<K, V> map) { + this(map, minimum(map.root)); } public boolean hasNext() { return node != null; } + final void makeNext() { + if (expectedModCount != backingMap.modCount) { + throw new ConcurrentModificationException(); + } else if (node == null) { + throw new NoSuchElementException(); + } + lastNode = node; + lastOffset = offset; + if (offset != 0) { + offset--; + } else { + node = node.next; + if (node != null) { + offset = node.right_idx - node.left_idx; + } + } + } + final public void remove() { if (expectedModCount == backingMap.modCount) { if (lastNode != null) { - backingMap.rbDelete(lastNode); + int idx = lastNode.right_idx - lastOffset; + backingMap.removeFromIterator(lastNode, idx); lastNode = null; expectedModCount++; } else { @@ -109,572 +223,752 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, throw new ConcurrentModificationException(); } } + } - final void makeNext() { - if (expectedModCount != backingMap.modCount) { - throw new ConcurrentModificationException(); - } else if (node == null) { - throw new NoSuchElementException(); - } - lastNode = node; - node = TreeMap.successor(node); - } - } - - private static class UnboundedEntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> { - - UnboundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode) { - super(map, startNode); - } - - UnboundedEntryIterator(TreeMap<K, V> map) { - super(map, map.root == null ? null : TreeMap.minimum(map.root)); - } + static class UnboundedEntryIterator <K, V> extends AbstractMapIterator<K, V> + implements Iterator<Map.Entry<K, V>> { - public Map.Entry<K, V> next() { - makeNext(); - return lastNode; - } + UnboundedEntryIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) { + super(map, startNode, startOffset); } - static class UnboundedKeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> { - public UnboundedKeyIterator(TreeMap<K, V> treeMap, Entry<K, V> entry) { - super(treeMap, entry); - } - - public UnboundedKeyIterator(TreeMap<K, V> map) { - super(map, map.root == null ? null : TreeMap.minimum(map.root)); - } - - public K next() { - makeNext(); - return lastNode.key; - } + UnboundedEntryIterator(TreeMap<K, V> map) { + super(map); } - static class UnboundedValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> { - - public UnboundedValueIterator(TreeMap<K, V> treeMap, Entry<K, V> startNode) { - super(treeMap, startNode); - } - - public UnboundedValueIterator(TreeMap<K, V> map) { - super(map, map.root == null ? null : TreeMap.minimum(map.root)); - } - - public V next() { - makeNext(); - return lastNode.value; - } + public Map.Entry<K, V> next() { + makeNext(); + int idx = lastNode.right_idx - lastOffset; + return backingMap.new MapEntry(lastNode, idx); } + } - private static class ComparatorBoundedIterator<K, V> extends AbstractMapIterator<K, V> { - private final K endKey; - - private final Comparator<? super K> cmp; + static class UnboundedKeyIterator <K, V> extends AbstractMapIterator<K, V> + implements Iterator<K> { - ComparatorBoundedIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) { - super(map, startNode); - endKey = end; - cmp = map.comparator(); + UnboundedKeyIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) { + super(map, startNode, startOffset); } - final void cleanNext() { - if (node != null && cmp.compare(endKey, node.key) <= 0) { - node = null; - } + UnboundedKeyIterator(TreeMap<K, V> map) { + super(map); } - @Override - public boolean hasNext() { - return (node != null && endKey != null) && (cmp.compare(node.key, endKey) < 0); + public K next() { + makeNext(); + return lastNode.keys[lastNode.right_idx - lastOffset]; } } - private static class ComparatorBoundedEntryIterator<K, V> extends - ComparatorBoundedIterator<K, V> implements Iterator<Map.Entry<K, V>> { - - ComparatorBoundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) { - super(map, startNode, end); - } + static class UnboundedValueIterator <K, V> extends AbstractMapIterator<K, V> + implements Iterator<V> { - public Map.Entry<K, V> next() { - makeNext(); - cleanNext(); - return lastNode; + UnboundedValueIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) { + super(map, startNode, startOffset); } - } - - private static class ComparatorBoundedKeyIterator<K, V> extends - ComparatorBoundedIterator<K, V> implements Iterator<K> { - ComparatorBoundedKeyIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) { - super(map, startNode, end); + UnboundedValueIterator(TreeMap<K, V> map) { + super(map); } - public K next() { + public V next() { makeNext(); - cleanNext(); - return lastNode.key; + return lastNode.values[lastNode.right_idx - lastOffset]; } } - private static class ComparatorBoundedValueIterator<K, V> extends - ComparatorBoundedIterator<K, V> implements Iterator<V> { + static class BoundedMapIterator <K, V> extends AbstractMapIterator<K, V> { - ComparatorBoundedValueIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) { - super(map, startNode, end); - } + Node<K, V> finalNode; + int finalOffset; - public V next() { - makeNext(); - cleanNext(); - return lastNode.value; + BoundedMapIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map, + Node<K, V> finalNode, int finalOffset) { + super(map, finalNode==null? null : startNode, startOffset); + this.finalNode = finalNode; + this.finalOffset = finalOffset; } - } - private static class ComparableBoundedIterator<K, V> extends AbstractMapIterator<K, V> { - private final Comparable<K> endKey; + BoundedMapIterator(Node<K, V> startNode, TreeMap<K, V> map, + Node<K, V> finalNode, int finalOffset) { + this(startNode, startNode != null ? + startNode.right_idx - startNode.left_idx : 0, + map, finalNode, finalOffset); + } - public ComparableBoundedIterator(TreeMap<K, V> treeMap, Entry<K, V> entry, - Comparable<K> endKey) { - super(treeMap, entry); - this.endKey = endKey; + BoundedMapIterator(Node<K, V> startNode, int startOffset, + TreeMap<K, V> map, Node<K, V> finalNode) { + this(startNode, startOffset, map, finalNode, + finalNode.right_idx - finalNode.left_idx); } - final void cleanNext() { - if ((node != null) && (endKey.compareTo(node.key) <= 0)) { + void makeBoundedNext() { + makeNext(); + if (lastNode == finalNode && lastOffset == finalOffset) { node = null; } } - - @Override - public boolean hasNext() { - return (node != null) && (endKey.compareTo(node.key) > 0); - } } - private static class ComparableBoundedEntryIterator<K, V> extends - ComparableBoundedIterator<K, V> implements Iterator<Map.Entry<K, V>> { + static class BoundedEntryIterator <K, V> extends BoundedMapIterator<K, V> + implements Iterator<Map.Entry<K, V>> { - ComparableBoundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode, - Comparable<K> end) { - super(map, startNode, end); + public BoundedEntryIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map, + Node<K, V> finalNode, int finalOffset) { + super(startNode, startOffset, map, finalNode, finalOffset); } public Map.Entry<K, V> next() { - makeNext(); - cleanNext(); - return lastNode; + makeBoundedNext(); + int idx = lastNode.right_idx - lastOffset; + return backingMap.new MapEntry(lastNode, idx); } - } - private static class ComparableBoundedKeyIterator<K, V> extends - ComparableBoundedIterator<K, V> implements Iterator<K> { + static class BoundedKeyIterator <K, V> extends BoundedMapIterator<K, V> + implements Iterator<K> { - ComparableBoundedKeyIterator(TreeMap<K, V> map, Entry<K, V> startNode, Comparable<K> end) { - super(map, startNode, end); + public BoundedKeyIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map, + Node<K, V> finalNode, int finalOffset) { + super(startNode, startOffset, map, finalNode, finalOffset); } public K next() { - makeNext(); - cleanNext(); - return lastNode.key; + makeBoundedNext(); + return lastNode.keys[lastNode.right_idx - lastOffset]; } } - private static class ComparableBoundedValueIterator<K, V> extends - ComparableBoundedIterator<K, V> implements Iterator<V> { + static class BoundedValueIterator <K, V> extends BoundedMapIterator<K, V> + implements Iterator<V> { - ComparableBoundedValueIterator(TreeMap<K, V> map, Entry<K, V> startNode, - Comparable<K> end) { - super(map, startNode, end); + public BoundedValueIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map, + Node<K, V> finalNode, int finalOffset) { + super(startNode, startOffset, map, finalNode, finalOffset); } public V next() { - makeNext(); - cleanNext(); - return lastNode.value; + makeBoundedNext(); + return lastNode.values[lastNode.right_idx - lastOffset]; } } - static final class SubMap<K,V> extends AbstractMap<K,V> implements SortedMap<K,V>, Serializable { - private static final long serialVersionUID = -6520786458950516097L; + static final class SubMap <K,V> extends AbstractMap<K, V> + implements SortedMap<K, V>, Serializable { + private static final long serialVersionUID = -6520786458950516097L; - private TreeMap<K,V> backingMap; + private TreeMap<K, V> backingMap; - boolean hasStart, hasEnd; + boolean hasStart, hasEnd; + K startKey, endKey; + transient Set<Map.Entry<K, V>> entrySet = null; + transient int firstKeyModCount = -1; + transient int lastKeyModCount = -1; + transient Node<K, V> firstKeyNode; + transient int firstKeyIndex; + transient Node<K, V> lastKeyNode; + transient int lastKeyIndex; - K startKey, endKey; + SubMap(K start, TreeMap<K, V> map) { + backingMap = map; + hasStart = true; + startKey = start; + } - transient Set<Map.Entry<K,V>> entrySet = null; + SubMap(K start, TreeMap<K, V> map, K end) { + backingMap = map; + hasStart = hasEnd = true; + startKey = start; + endKey = end; + } - SubMap(K start, TreeMap<K,V> map) { - backingMap = map; - hasStart = true; - startKey = start; - } + SubMap(TreeMap<K, V> map, K end) { + backingMap = map; + hasEnd = true; + endKey = end; + } - SubMap(K start, TreeMap<K,V> map, K end) { - backingMap = map; - hasStart = hasEnd = true; - startKey = start; - endKey = end; + private void checkRange(K key) { + Comparator<? super K> cmp = backingMap.comparator; + if (cmp == null) { + Comparable<K> object = toComparable(key); + if (hasStart && object.compareTo(startKey) < 0) { + throw new IllegalArgumentException(); + } + if (hasEnd && object.compareTo(endKey) > 0) { + throw new IllegalArgumentException(); + } + } else { + if (hasStart + && backingMap.comparator().compare(key, startKey) < 0) { + throw new IllegalArgumentException(); + } + if (hasEnd && backingMap.comparator().compare(key, endKey) > 0) { + throw new IllegalArgumentException(); + } } - - SubMap(TreeMap<K,V> map, K end) { - backingMap = map; - hasEnd = true; - endKey = end; + } + + private boolean isInRange(K key) { + Comparator<? super K> cmp = backingMap.comparator; + if (cmp == null) { + Comparable<K> object = toComparable(key); + if (hasStart && object.compareTo(startKey) < 0) { + return false; + } + if (hasEnd && object.compareTo(endKey) >= 0) { + return false; + } + } else { + if (hasStart && cmp.compare(key, startKey) < 0) { + return false; + } + if (hasEnd && cmp.compare(key, endKey) >= 0) { + return false; + } } + return true; + } - private void checkRange(K key) { + private boolean checkUpperBound(K key) { + if (hasEnd) { Comparator<? super K> cmp = backingMap.comparator; if (cmp == null) { - Comparable<K> object = toComparable(key); - if (hasStart && object.compareTo(startKey) < 0) { - throw new IllegalArgumentException(); - } - if (hasEnd && object.compareTo(endKey) > 0) { - throw new IllegalArgumentException(); - } - } else { - if (hasStart - && backingMap.comparator().compare(key, startKey) < 0) { - throw new IllegalArgumentException(); - } - if (hasEnd && backingMap.comparator().compare(key, endKey) > 0) { - throw new IllegalArgumentException(); - } + return (toComparable(key).compareTo(endKey) < 0); } + return (cmp.compare(key, endKey) < 0); } + return true; + } - private boolean isInRange(K key) { + private boolean checkLowerBound(K key) { + if (hasStart) { Comparator<? super K> cmp = backingMap.comparator; if (cmp == null) { - Comparable<K> object = toComparable(key); - if (hasStart && object.compareTo(startKey) < 0) { - return false; - } - if (hasEnd && object.compareTo(endKey) >= 0) { - return false; - } - } else { - if (hasStart && cmp.compare(key, startKey) < 0) { - return false; - } - if (hasEnd && cmp.compare(key, endKey) >= 0) { - return false; - } + return (toComparable(key).compareTo(startKey) >= 0); } - return true; + return (cmp.compare(key, startKey) >= 0); } + return true; + } - private boolean checkUpperBound(K key) { - if (hasEnd) { - Comparator<? super K> cmp = backingMap.comparator; - if (cmp == null) { - return (toComparable(key).compareTo(endKey) < 0); - } - return (cmp.compare(key, endKey) < 0); - } - return true; + public Comparator<? super K> comparator() { + return backingMap.comparator(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsKey(Object key) { + if (isInRange((K) key)) { + return backingMap.containsKey(key); } + return false; + } + + @Override + public void clear() { + keySet().clear(); + } - private boolean checkLowerBound(K key) { - if (hasStart) { - Comparator<? super K> cmp = backingMap.comparator; - if (cmp == null) { - return (toComparable(key).compareTo(startKey) >= 0); + @Override + public boolean containsValue(Object value) { + Iterator<V> it = values().iterator(); + if (value != null) { + while (it.hasNext()) { + if (value.equals(it.next())) { + return true; + } + } + } else { + while (it.hasNext()) { + if (it.next() == null) { + return true; } - return (cmp.compare(key, startKey) >= 0); } - return true; } + return false; + } - public Comparator<? super K> comparator() { - return backingMap.comparator(); + @Override + public Set<Map.Entry<K, V>> entrySet() { + if (entrySet == null) { + entrySet = new SubMapEntrySet<K, V>(this); } + return entrySet; + } - @SuppressWarnings("unchecked") - @Override - public boolean containsKey(Object key) { - if (isInRange((K)key)) { - return backingMap.containsKey(key); - } - return false; + private void setFirstKey() { + if (firstKeyModCount == backingMap.modCount) { + return; } - - @Override - public Set<Map.Entry<K,V>> entrySet() { - if(entrySet==null) { - entrySet = new SubMapEntrySet<K,V>(this); + Comparable<K> object = backingMap.comparator == null ? + toComparable((K) startKey) : null; + K key = (K) startKey; + Node<K, V> node = backingMap.root; + Node<K, V> foundNode = null; + int foundIndex = -1; + TOP_LOOP: + while (node != null) { + K[] keys = node.keys; + int left_idx = node.left_idx; + int result = backingMap.cmp(object, key, keys[left_idx]); + if (result < 0) { + foundNode = node; + foundIndex = left_idx; + node = node.left; + } else if (result == 0) { + foundNode = node; + foundIndex = left_idx; + break; + } else { + int right_idx = node.right_idx; + if (left_idx != right_idx) { + result = backingMap.cmp(object, key, keys[right_idx]); + } + if (result > 0) { + node = node.right; + } else if (result == 0) { + foundNode = node; + foundIndex = right_idx; + break; + } else { /*search in node*/ + foundNode = node; + foundIndex = right_idx; + int low = left_idx + 1, mid = 0, high = right_idx - 1; + while (low <= high) { + mid = (low + high) >> 1; + result = backingMap.cmp(object, key, keys[mid]); + if (result > 0) { + low = mid + 1; + } else if (result == 0) { + foundNode = node; + foundIndex = mid; + break TOP_LOOP; + } else { + foundNode = node; + foundIndex = mid; + high = mid - 1; + } + } + break TOP_LOOP; + } } - return entrySet; } - - public K firstKey() { - TreeMap.Entry<K,V> node = firstEntry(); - if (node != null ) { - return node.key; - } - throw new NoSuchElementException(); + if (foundNode != null && !checkUpperBound(foundNode.keys[foundIndex])) { + foundNode = null; } + firstKeyNode = foundNode; + firstKeyIndex = foundIndex; + firstKeyModCount = backingMap.modCount; + } - TreeMap.Entry<K,V> firstEntry() { + public K firstKey() { + if (backingMap.size > 0) { if (!hasStart) { - TreeMap.Entry<K,V> root = backingMap.root; - return (root == null) ? null : minimum(backingMap.root); - } - TreeMap.Entry<K,V> node = backingMap.findAfter(startKey); - if (node != null && checkUpperBound(node.key)) { - return node; + Node<K, V> node = minimum(backingMap.root); + if (node != null && checkUpperBound(node.keys[node.left_idx])) { + return node.keys[node.left_idx]; + } + } else { + setFirstKey(); + if (firstKeyNode != null) { + return firstKeyNode.keys[firstKeyIndex]; + } } - return null; } + throw new NoSuchElementException(); + } - @SuppressWarnings("unchecked") - @Override - public V get(Object key) { - if (isInRange((K)key)) { - return backingMap.get(key); - } - return null; - } - public SortedMap<K,V> headMap(K endKey) { - checkRange(endKey); - if (hasStart) { - return new SubMap<K,V>(startKey, backingMap, endKey); - } - return new SubMap<K,V>(backingMap, endKey); + @SuppressWarnings("unchecked") + @Override + public V get(Object key) { + if (isInRange((K) key)) { + return backingMap.get(key); } + return null; + } - @Override - public boolean isEmpty() { - if (hasStart) { - TreeMap.Entry<K,V> node = backingMap.findAfter(startKey); - return node == null || !checkUpperBound(node.key); - } - return backingMap.findBefore(endKey) == null; + public SortedMap<K, V> headMap(K endKey) { + checkRange(endKey); + if (hasStart) { + return new SubMap<K, V>(startKey, backingMap, endKey); } + return new SubMap<K, V>(backingMap, endKey); + } - @Override - public Set<K> keySet() { - if (keySet == null) { - keySet = new SubMapKeySet<K,V>(this); - } - return keySet; + @Override + public boolean isEmpty() { + if (hasStart) { + setFirstKey(); + return firstKeyNode == null; + } else { + setLastKey(); + return lastKeyNode == null; } + } - public K lastKey() { - if (!hasEnd) { - return backingMap.lastKey(); - } - TreeMap.Entry<K,V> node = backingMap.findBefore(endKey); - if (node != null && checkLowerBound(node.key)) { - return node.key; - } - throw new NoSuchElementException(); + @Override + public Set<K> keySet() { + if (keySet == null) { + keySet = new SubMapKeySet<K, V>(this); } + return keySet; + } - @Override - public V put(K key, V value) { - if (isInRange(key)) { - return backingMap.put(key, value); - } - throw new IllegalArgumentException(); + private void setLastKey() { + if (lastKeyModCount == backingMap.modCount) { + return; } - - @SuppressWarnings("unchecked") - @Override - public V remove(Object key) { - if (isInRange((K)key)) { - return backingMap.remove(key); + Comparable<K> object = backingMap.comparator == null ? + toComparable((K) endKey) : null; + K key = (K) endKey; + Node<K, V> node = backingMap.root; + Node<K, V> foundNode = null; + int foundIndex = -1; + TOP_LOOP: + while (node != null) { + K[] keys = node.keys; + int left_idx = node.left_idx; + int result = backingMap.cmp(object, key, keys[left_idx]); + if (result <= 0) { + node = node.left; + } else { + int right_idx = node.right_idx; + if (left_idx != right_idx) { + result = backingMap.cmp(object, key, keys[right_idx]); + } + if (result > 0) { + foundNode = node; + foundIndex = right_idx; + node = node.right; + } else if (result == 0) { + if (node.left_idx == node.right_idx) { + foundNode = node.prev; + if (foundNode != null) { + foundIndex = foundNode.right_idx - 1; + } + } else { + foundNode = node; + foundIndex = right_idx - 1; + } + break; + } else { /*search in node*/ + foundNode = node; + foundIndex = left_idx; + int low = left_idx + 1, mid = 0, high = right_idx - 1; + while (low <= high) { + mid = (low + high) >> 1; + result = backingMap.cmp(object, key, keys[mid]); + if (result > 0) { + foundNode = node; + foundIndex = mid; + low = mid + 1; + } else if (result == 0) { + foundNode = node; + foundIndex = mid - 1; + break TOP_LOOP; + } else { + high = mid - 1; + } + } + break TOP_LOOP; + } } - return null; } + if (foundNode != null && !checkLowerBound(foundNode.keys[foundIndex])) { + foundNode = null; + } + lastKeyNode = foundNode; + lastKeyIndex = foundIndex; + lastKeyModCount = backingMap.modCount; + } - public SortedMap<K,V> subMap(K startKey, K endKey) { - checkRange(startKey); - checkRange(endKey); - Comparator<? super K> c = backingMap.comparator(); - if (c == null) { - if (toComparable(startKey).compareTo(endKey) <= 0) { - return new SubMap<K,V>(startKey, backingMap, endKey); + public K lastKey() { + if (backingMap.size > 0) { + if (!hasEnd) { + Node<K, V> node = maximum(backingMap.root); + if (node != null && checkLowerBound(node.keys[node.right_idx])) { + return node.keys[node.right_idx]; } } else { - if (c.compare(startKey, endKey) <= 0) { - return new SubMap<K,V>(startKey, backingMap, endKey); + setLastKey(); + if (lastKeyNode != null) { + return lastKeyNode.keys[lastKeyIndex]; } } - throw new IllegalArgumentException(); } + throw new NoSuchElementException(); + } - public SortedMap<K,V> tailMap(K startKey) { - checkRange(startKey); - if (hasEnd) { - return new SubMap<K,V>(startKey, backingMap, endKey); - } - return new SubMap<K,V>(startKey, backingMap); - } - @Override - public Collection<V> values() { - if(valuesCollection==null) { - valuesCollection = new SubMapValuesCollection<K,V>(this); - } - return valuesCollection; + @Override + public V put(K key, V value) { + if (isInRange(key)) { + return backingMap.put(key, value); } + throw new IllegalArgumentException(); } - static class SubMapEntrySet<K,V> extends AbstractSet<Map.Entry<K,V>> implements Set<Map.Entry<K,V>> { - SubMap<K,V> subMap; - - SubMapEntrySet(SubMap<K,V> map) { - subMap = map; + @SuppressWarnings("unchecked") + @Override + public V remove(Object key) { + if (isInRange((K) key)) { + return backingMap.remove(key); } + return null; + } - @Override - public boolean isEmpty() { - return subMap.isEmpty(); + public SortedMap<K, V> subMap(K startKey, K endKey) { + checkRange(startKey); + checkRange(endKey); + Comparator<? super K> c = backingMap.comparator(); + if (c == null) { + if (toComparable(startKey).compareTo(endKey) <= 0) { + return new SubMap<K, V>(startKey, backingMap, endKey); + } + } else { + if (c.compare(startKey, endKey) <= 0) { + return new SubMap<K, V>(startKey, backingMap, endKey); + } } + throw new IllegalArgumentException(); + } - @Override - public Iterator<Map.Entry<K,V>> iterator() { - TreeMap.Entry<K,V> startNode = subMap.firstEntry(); - if (subMap.hasEnd) { - Comparator<? super K> cmp = subMap.comparator(); - if (cmp == null) { - return new ComparableBoundedEntryIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey)); - } - return new ComparatorBoundedEntryIterator<K,V>(subMap.backingMap, startNode, subMap.endKey); - } - return new UnboundedEntryIterator<K,V>(subMap.backingMap, startNode); + public SortedMap<K, V> tailMap(K startKey) { + checkRange(startKey); + if (hasEnd) { + return new SubMap<K, V>(startKey, backingMap, endKey); } + return new SubMap<K, V>(startKey, backingMap); + } - @Override - public int size() { - int size = 0; - Iterator<Map.Entry<K,V>> it = iterator(); - while (it.hasNext()) { - size++; - it.next(); - } - return size; + @Override + public Collection<V> values() { + if (valuesCollection == null) { + valuesCollection = new SubMapValuesCollection<K, V>(this); } + return valuesCollection; + } - @SuppressWarnings("unchecked") - @Override - public boolean contains(Object object) { - if (object instanceof Map.Entry) { - Map.Entry<K,V> entry = (Map.Entry<K,V>) object; - K key = entry.getKey(); - if (subMap.isInRange(key)) { - V v1 = subMap.get(key), v2 = entry.getValue(); - return v1 == null ? v2 == null : v1.equals(v2); - } - } - return false; + public int size() { + Node<K, V> from, to; + int fromIndex, toIndex; + if (hasStart) { + setFirstKey(); + from = firstKeyNode; + fromIndex = firstKeyIndex; + } else { + from = minimum(backingMap.root); + fromIndex = from == null ? 0 : from.left_idx; + } + if (from == null) { + return 0; + } + if (hasEnd) { + setLastKey(); + to = lastKeyNode; + toIndex = lastKeyIndex; + } else { + to = maximum(backingMap.root); + toIndex = to == null ? 0 : to.right_idx; + } + if (to == null) { + return 0; + } + if (from == to) { + return toIndex - fromIndex + 1; } + int sum = 0; + while (from != to) { + sum += (from.right_idx - fromIndex + 1); + from = from.next; + fromIndex = from.left_idx; + } + return sum + toIndex - fromIndex + 1; + } + private void readObject(ObjectInputStream stream) throws IOException, + ClassNotFoundException { + stream.defaultReadObject(); + firstKeyModCount = -1; + lastKeyModCount = -1; } + } - static class SubMapKeySet<K,V> extends AbstractSet<K> implements Set<K> { - SubMap<K,V> subMap; + static class SubMapEntrySet <K,V> extends AbstractSet<Map.Entry<K, V>> + implements Set<Map.Entry<K, V>> { + SubMap<K, V> subMap; - SubMapKeySet(SubMap<K,V> map) { - subMap = map; - } + SubMapEntrySet(SubMap<K, V> map) { + subMap = map; + } - @Override - public boolean contains(Object object) { - return subMap.containsKey(object); - } + @Override + public boolean isEmpty() { + return subMap.isEmpty(); + } - @Override - public boolean isEmpty() { - return subMap.isEmpty(); + public Iterator<Map.Entry<K, V>> iterator() { + Node<K, V> from; + int fromIndex; + if (subMap.hasStart) { + subMap.setFirstKey(); + from = subMap.firstKeyNode; + fromIndex = subMap.firstKeyIndex; + } else { + from = minimum(subMap.backingMap.root); + fromIndex = from != null ? from.left_idx : 0; + } + if (!subMap.hasEnd) { + return new UnboundedEntryIterator<K, V>(subMap.backingMap, from, from == null ? 0 : from.right_idx - fromIndex); } + subMap.setLastKey(); + Node<K, V> to = subMap.lastKeyNode; + int toIndex = subMap.lastKeyIndex; + return new BoundedEntryIterator<K, V>(from, from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, to == null ? 0 : to.right_idx - toIndex); + } - @Override - public int size() { - int size = 0; - Iterator<K> it = iterator(); - while (it.hasNext()) { - size++; - it.next(); + @Override + public int size() { + return subMap.size(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean contains(Object object) { + if (object instanceof Map.Entry) { + Map.Entry<K, V> entry = (Map.Entry<K, V>) object; + K key = entry.getKey(); + if (subMap.isInRange(key)) { + V v1 = subMap.get(key), v2 = entry.getValue(); + return v1 == null ? ( v2 == null && subMap.containsKey(key) ) : v1.equals(v2); } - return size; } + return false; + } - @Override - public Iterator<K> iterator() { - TreeMap.Entry<K,V> startNode = subMap.firstEntry(); - if (subMap.hasEnd) { - Comparator<? super K> cmp = subMap.comparator(); - if (cmp == null) { - return new ComparableBoundedKeyIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey)); - } - return new ComparatorBoundedKeyIterator<K,V>(subMap.backingMap, startNode, subMap.endKey); - } - return new UnboundedKeyIterator<K,V>(subMap.backingMap, startNode); + @Override + public boolean remove(Object object) { + if (contains(object)) { + Map.Entry<K, V> entry = (Map.Entry<K, V>) object; + K key = entry.getKey(); + subMap.remove(key); + return true; } + return false; } + } - static class SubMapValuesCollection<K,V> extends AbstractCollection<V> { - SubMap<K,V> subMap; + static class SubMapKeySet <K,V> extends AbstractSet<K> implements Set<K> { + SubMap<K, V> subMap; - public SubMapValuesCollection(SubMap<K,V> subMap) { - this.subMap = subMap; - } + SubMapKeySet(SubMap<K, V> map) { + subMap = map; + } - @Override - public boolean isEmpty() { - return subMap.isEmpty(); + @Override + public boolean contains(Object object) { + return subMap.containsKey(object); + } + + @Override + public boolean isEmpty() { + return subMap.isEmpty(); + } + + @Override + public int size() { + return subMap.size(); + } + + @Override + public boolean remove(Object object) { + if (subMap.containsKey(object)) { + subMap.remove(object); + return true; } + return false; + } - @Override - public Iterator<V> iterator() { - TreeMap.Entry<K,V> startNode = subMap.firstEntry(); - if (subMap.hasEnd) { - Comparator<? super K> cmp = subMap.comparator(); - if (cmp == null) { - return new ComparableBoundedValueIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey)); - } - return new ComparatorBoundedValueIterator<K,V>(subMap.backingMap, startNode, subMap.endKey); - } - return new UnboundedValueIterator<K,V>(subMap.backingMap, startNode); + public Iterator<K> iterator() { + Node<K, V> from; + int fromIndex; + if (subMap.hasStart) { + subMap.setFirstKey(); + from = subMap.firstKeyNode; + fromIndex = subMap.firstKeyIndex; + } else { + from = minimum(subMap.backingMap.root); + fromIndex = from != null ? from.left_idx : 0; } + if (!subMap.hasEnd) { + return new UnboundedKeyIterator<K, V>(subMap.backingMap, from, + from == null ? 0 : from.right_idx - fromIndex); + } + subMap.setLastKey(); + Node<K, V> to = subMap.lastKeyNode; + int toIndex = subMap.lastKeyIndex; + return new BoundedKeyIterator<K, V>(from, + from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, + to == null ? 0 : to.right_idx - toIndex); + } + } - @Override - public int size() { - int cnt = 0; - for (Iterator<V> it = iterator(); it.hasNext();) { - it.next(); - cnt++; - } - return cnt; + static class SubMapValuesCollection <K,V> extends AbstractCollection<V> { + SubMap<K, V> subMap; + + public SubMapValuesCollection(SubMap<K, V> subMap) { + this.subMap = subMap; + } + + @Override + public boolean isEmpty() { + return subMap.isEmpty(); + } + + @Override + public Iterator<V> iterator() { + Node<K, V> from; + int fromIndex; + if (subMap.hasStart) { + subMap.setFirstKey(); + from = subMap.firstKeyNode; + fromIndex = subMap.firstKeyIndex; + } else { + from = minimum(subMap.backingMap.root); + fromIndex = from != null ? from.left_idx : 0; + } + if (!subMap.hasEnd) { + return new UnboundedValueIterator<K, V>(subMap.backingMap, from, + from == null ? 0 : from.right_idx - fromIndex); } + subMap.setLastKey(); + Node<K, V> to = subMap.lastKeyNode; + int toIndex = subMap.lastKeyIndex; + return new BoundedValueIterator<K, V>(from, + from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, + to == null ? 0 : to.right_idx - toIndex); } + @Override + public int size() { + return subMap.size(); + } + } + /** * Constructs a new empty {@code TreeMap} instance. - * - * @since Android 1.0 */ public TreeMap() { - super(); } /** * Constructs a new empty {@code TreeMap} instance with the specified * comparator. - * + * * @param comparator * the comparator to compare keys with. - * @since Android 1.0 */ public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; @@ -683,95 +977,57 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, /** * Constructs a new {@code TreeMap} instance containing the mappings from * the specified map and using natural ordering. - * + * * @param map * the mappings to add. * @throws ClassCastException * if a key in the specified map does not implement the * Comparable interface, or if the keys in the map cannot be * compared. - * @since Android 1.0 */ - public TreeMap(Map<? extends K,? extends V> map) { - this(); + public TreeMap(Map<? extends K, ? extends V> map) { putAll(map); } /** * Constructs a new {@code TreeMap} instance containing the mappings from * the specified SortedMap and using the same comparator. - * + * * @param map * the mappings to add. - * @since Android 1.0 */ - public TreeMap(SortedMap<K,? extends V> map) { + public TreeMap(SortedMap<K, ? extends V> map) { this(map.comparator()); + Node<K, V> lastNode = null; Iterator<? extends Map.Entry<K, ? extends V>> it = map.entrySet().iterator(); - if (it.hasNext()) { + while (it.hasNext()) { Map.Entry<K, ? extends V> entry = it.next(); - Entry<K, V> last = new Entry<K, V>(entry.getKey(), entry.getValue()); - root = last; - size = 1; - while (it.hasNext()) { - entry = it.next(); - Entry<K, V> x = new Entry<K, V>(entry.getKey(), entry.getValue()); - x.parent = last; - last.right = x; - size++; - balance(x); - last = x; - } + lastNode = addToLast(lastNode, entry.getKey(), entry.getValue()); } } - void balance(Entry<K, V> x) { - Entry<K, V> y; - x.color = true; - while (x != root && x.parent.color) { - if (x.parent == x.parent.parent.left) { - y = x.parent.parent.right; - if (y != null && y.color) { - x.parent.color = false; - y.color = false; - x.parent.parent.color = true; - x = x.parent.parent; - } else { - if (x == x.parent.right) { - x = x.parent; - leftRotate(x); - } - x.parent.color = false; - x.parent.parent.color = true; - rightRotate(x.parent.parent); - } - } else { - y = x.parent.parent.left; - if (y != null && y.color) { - x.parent.color = false; - y.color = false; - x.parent.parent.color = true; - x = x.parent.parent; - } else { - if (x == x.parent.left) { - x = x.parent; - rightRotate(x); - } - x.parent.color = false; - x.parent.parent.color = true; - leftRotate(x.parent.parent); - } - } + Node<K, V> addToLast(Node<K, V> last, K key, V value) { + if (last == null) { + root = last = createNode(key, value); + size = 1; + } else if (last.size == Node.NODE_SIZE) { + Node<K, V> newNode = createNode(key, value); + attachToRight(last, newNode); + balance(newNode); + size++; + last = newNode; + } else { + appendFromRight(last, key, value); + size++; } - root.color = false; + return last; } /** * Removes all mappings from this TreeMap, leaving it empty. - * + * * @see Map#isEmpty() * @see #size() - * @since Android 1.0 */ @Override public void clear() { @@ -783,10 +1039,9 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, /** * Returns a new {@code TreeMap} with the same mappings, size and comparator * as this instance. - * + * * @return a shallow copy of this instance. * @see java.lang.Cloneable - * @since Android 1.0 */ @SuppressWarnings("unchecked") @Override @@ -796,6 +1051,17 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, clone.entrySet = null; if (root != null) { clone.root = root.clone(null); + // restore prev/next chain + Node<K, V> node = minimum(clone.root); + while (true) { + Node<K, V> nxt = successor(node); + if (nxt == null) { + break; + } + nxt.prev = node; + node.next = nxt; + node = nxt; + } } return clone; } catch (CloneNotSupportedException e) { @@ -803,11 +1069,22 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, } } + static private <K, V> Node<K, V> successor(Node<K, V> x) { + if (x.right != null) { + return minimum(x.right); + } + Node<K, V> y = x.parent; + while (y != null && x == y.right) { + x = y; + y = y.parent; + } + return y; + } + /** * Returns the comparator used to compare elements in this map. - * + * * @return the comparator or {@code null} if the natural ordering is used. - * @since Android 1.0 */ public Comparator<? super K> comparator() { return comparator; @@ -815,47 +1092,95 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, /** * Returns whether this map contains the specified key. - * + * * @param key * the key to search for. * @return {@code true} if this map contains the specified key, * {@code false} otherwise. - * @since Android 1.0 + * @throws ClassCastException + * if the specified key cannot be compared with the keys in this + * map. + * @throws NullPointerException + * if the specified key is {@code null} and the comparator + * cannot handle {@code null} keys. */ @Override public boolean containsKey(Object key) { - return find(key) != null; + Comparable<K> object = comparator == null ? toComparable((K) key) : null; + K keyK = (K) key; + Node<K, V> node = root; + while (node != null) { + K[] keys = node.keys; + int left_idx = node.left_idx; + int result = cmp(object, keyK, keys[left_idx]); + if (result < 0) { + node = node.left; + } else if (result == 0) { + return true; + } else { + int right_idx = node.right_idx; + if (left_idx != right_idx) { + result = cmp(object, keyK, keys[right_idx]); + } + if (result > 0) { + node = node.right; + } else if (result == 0) { + return true; + } else { /*search in node*/ + int low = left_idx + 1, mid = 0, high = right_idx - 1; + while (low <= high) { + mid = (low + high) >> 1; + result = cmp(object, keyK, keys[mid]); + if (result > 0) { + low = mid + 1; + } else if (result == 0) { + return true; + } else { + high = mid - 1; + } + } + return false; + } + } + } + return false; } /** * Returns whether this map contains the specified value. - * + * * @param value * the value to search for. * @return {@code true} if this map contains the specified value, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsValue(Object value) { - if (root != null) { - return containsValue(root, value); + if (root == null) { + return false; } - return false; - } - - private boolean containsValue(Entry<K, V> node, Object value) { - if (value == null ? node.value == null : value.equals(node.value)) { - return true; - } - if (node.left != null) { - if (containsValue(node.left, value)) { - return true; + Node<K, V> node = minimum(root); + if (value != null) { + while (node != null) { + int to = node.right_idx; + V[] values = node.values; + for (int i = node.left_idx; i <= to; i++) { + if (value.equals(values[i])) { + return true; + } + } + node = node.next; } - } - if (node.right != null) { - if (containsValue(node.right, value)) { - return true; + } else { + while (node != null) { + int to = node.right_idx; + V[] values = node.values; + for (int i = node.left_idx; i <= to; i++) { + if (values[i] == null) { + return true; + } + } + node = node.next; } } return false; @@ -866,15 +1191,14 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * an instance of {@link Map.Entry}. As the set is backed by this map, * changes in one will be reflected in the other. It does not support adding * operations. - * + * * @return a set of the mappings. - * @since Android 1.0 */ @Override public Set<Map.Entry<K, V>> entrySet() { if (entrySet == null) { entrySet = new AbstractSet<Map.Entry<K, V>>() { - @Override + @Override public int size() { return size; } @@ -889,8 +1213,20 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, public boolean contains(Object object) { if (object instanceof Map.Entry) { Map.Entry<K, V> entry = (Map.Entry<K, V>) object; - Object v1 = get(entry.getKey()), v2 = entry.getValue(); - return v1 == null ? v2 == null : v1.equals(v2); + K key = entry.getKey(); + Object v1 = TreeMap.this.get(key), v2 = entry.getValue(); + return v1 == null ? ( v2 == null && TreeMap.this.containsKey(key) ) : v1.equals(v2); + } + return false; + } + + @Override + public boolean remove(Object object) { + if (contains(object)) { + Map.Entry<K, V> entry = (Map.Entry<K, V>) object; + K key = entry.getKey(); + TreeMap.this.remove(key); + return true; } return false; } @@ -904,163 +1240,25 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, return entrySet; } - @SuppressWarnings("unchecked") - private Entry<K, V> find(Object keyObj) { - int result; - K key = (K)keyObj; - Comparable<K> object = null; - if (comparator == null) { - object = toComparable(key); - } - Entry<K, V> x = root; - while (x != null) { - result = object != null ? object.compareTo(x.key) : comparator - .compare(key, x.key); - if (result == 0) { - return x; - } - x = result < 0 ? x.left : x.right; - } - return null; - } - - @SuppressWarnings("unchecked") - Entry<K, V> findAfter(Object keyObj) { - K key = (K)keyObj; - int result; - Comparable<K> object = null; - if (comparator == null) { - object = toComparable(key); - } - Entry<K, V> x = root, last = null; - while (x != null) { - result = object != null ? object.compareTo(x.key) : comparator - .compare(key, x.key); - if (result == 0) { - return x; - } - if (result < 0) { - last = x; - x = x.left; - } else { - x = x.right; - } - } - return last; - } - - Entry<K, V> findBefore(K key) { - int result; - Comparable<K> object = null; - if (comparator == null) { - object = toComparable(key); - } - Entry<K, V> x = root, last = null; - while (x != null) { - result = object != null ? object.compareTo(x.key) : comparator - .compare(key, x.key); - if (result <= 0) { - x = x.left; - } else { - last = x; - x = x.right; - } - } - return last; - } - /** * Returns the first key in this map. - * + * * @return the first key in this map. - * @exception NoSuchElementException - * if this sorted map is empty. - * @since Android 1.0 + * @throws NoSuchElementException + * if this map is empty. */ public K firstKey() { if (root != null) { - return minimum(root).key; + Node<K, V> node = minimum(root); + return node.keys[node.left_idx]; } throw new NoSuchElementException(); } - private void fixup(Entry<K, V> x) { - Entry<K, V> w; - while (x != root && !x.color) { - if (x == x.parent.left) { - w = x.parent.right; - if (w == null) { - x = x.parent; - continue; - } - if (w.color) { - w.color = false; - x.parent.color = true; - leftRotate(x.parent); - w = x.parent.right; - if (w == null) { - x = x.parent; - continue; - } - } - if ((w.left == null || !w.left.color) - && (w.right == null || !w.right.color)) { - w.color = true; - x = x.parent; - } else { - if (w.right == null || !w.right.color) { - w.left.color = false; - w.color = true; - rightRotate(w); - w = x.parent.right; - } - w.color = x.parent.color; - x.parent.color = false; - w.right.color = false; - leftRotate(x.parent); - x = root; - } - } else { - w = x.parent.left; - if (w == null) { - x = x.parent; - continue; - } - if (w.color) { - w.color = false; - x.parent.color = true; - rightRotate(x.parent); - w = x.parent.left; - if (w == null) { - x = x.parent; - continue; - } - } - if ((w.left == null || !w.left.color) - && (w.right == null || !w.right.color)) { - w.color = true; - x = x.parent; - } else { - if (w.left == null || !w.left.color) { - w.right.color = false; - w.color = true; - leftRotate(w); - w = x.parent.left; - } - w.color = x.parent.color; - x.parent.color = false; - w.left.color = false; - rightRotate(x.parent); - x = root; - } - } - } - x.color = false; - } /** * Returns the value of the mapping with the specified key. - * + * * @param key * the key. * @return the value of the mapping with the specified key. @@ -1069,17 +1267,54 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * @throws NullPointerException * if the key is {@code null} and the comparator cannot handle * {@code null}. - * @since Android 1.0 */ @Override public V get(Object key) { - Entry<K, V> node = find(key); - if (node != null) { - return node.value; + Comparable<K> object = comparator == null ? toComparable((K) key) : null; + K keyK = (K) key; + Node<K, V> node = root; + while (node != null) { + K[] keys = node.keys; + int left_idx = node.left_idx; + int result = cmp(object, keyK, keys[left_idx]); + if (result < 0) { + node = node.left; + } else if (result == 0) { + return node.values[left_idx]; + } else { + int right_idx = node.right_idx; + if (left_idx != right_idx) { + result = cmp(object, keyK, keys[right_idx]); + } + if (result > 0) { + node = node.right; + } else if (result == 0) { + return node.values[right_idx]; + } else { /*search in node*/ + int low = left_idx + 1, mid = 0, high = right_idx - 1; + while (low <= high) { + mid = (low + high) >> 1; + result = cmp(object, keyK, keys[mid]); + if (result > 0) { + low = mid + 1; + } else if (result == 0) { + return node.values[mid]; + } else { + high = mid - 1; + } + } + return null; + } + } } return null; } + private int cmp(Comparable<K> object, K key1, K key2) { + return object != null ? + object.compareTo(key2) : comparator.compare(key1, key2); + } + /** * Returns a sorted map over a range of this sorted map with all keys that * are less than the specified {@code endKey}. Changes to the returned @@ -1087,8 +1322,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * <p> * Note: The returned map will not allow an insertion of a key outside the * specified range. - * </p> - * + * * @param endKey * the high boundary of the range specified. * @return a sorted map where the keys are less than {@code endKey}. @@ -1101,7 +1335,6 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * @throws IllegalArgumentException * if this map is itself a sorted map over a range of another * map and the specified key is outside of its range. - * @since Android 1.0 */ public SortedMap<K, V> headMap(K endKey) { // Check for errors @@ -1117,9 +1350,8 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * Returns a set of the keys contained in this map. The set is backed by * this map so changes to one are reflected by the other. The set does not * support adding. - * + * * @return a set of the keys. - * @since Android 1.0 */ @Override public Set<K> keySet() { @@ -1127,12 +1359,12 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, keySet = new AbstractSet<K>() { @Override public boolean contains(Object object) { - return containsKey(object); + return TreeMap.this.containsKey(object); } @Override public int size() { - return size; + return TreeMap.this.size; } @Override @@ -1141,8 +1373,17 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, } @Override + public boolean remove(Object object) { + if (contains(object)) { + TreeMap.this.remove(object); + return true; + } + return false; + } + + @Override public Iterator<K> iterator() { - return new UnboundedKeyIterator<K,V> (TreeMap.this); + return new UnboundedKeyIterator<K, V>(TreeMap.this); } }; } @@ -1151,68 +1392,42 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, /** * Returns the last key in this map. - * + * * @return the last key in this map. * @throws NoSuchElementException * if this map is empty. - * @since Android 1.0 */ public K lastKey() { if (root != null) { - return maximum(root).key; + Node<K, V> node = maximum(root); + return node.keys[node.right_idx]; } throw new NoSuchElementException(); } - private void leftRotate(Entry<K, V> x) { - Entry<K, V> y = x.right; - x.right = y.left; - if (y.left != null) { - y.left.parent = x; - } - y.parent = x.parent; - if (x.parent == null) { - root = y; - } else { - if (x == x.parent.left) { - x.parent.left = y; - } else { - x.parent.right = y; - } - } - y.left = x; - x.parent = y; - } - - static <K, V> Entry<K, V> maximum(Entry<K, V> x) { - while (x.right != null) { - x = x.right; + static <K,V> Node<K, V> minimum(Node<K, V> x) { + if (x == null) { + return null; } - return x; - } - - static <K, V> Entry<K, V> minimum(Entry<K, V> x) { while (x.left != null) { x = x.left; } return x; } - static <K, V> Entry<K, V> predecessor(Entry<K, V> x) { - if (x.left != null) { - return maximum(x.left); + static <K,V> Node<K, V> maximum(Node<K, V> x) { + if (x == null) { + return null; } - Entry<K, V> y = x.parent; - while (y != null && x == y.left) { - x = y; - y = y.parent; + while (x.right != null) { + x = x.right; } - return y; + return x; } /** * Maps the specified key to the specified value. - * + * * @param key * the key. * @param value @@ -1225,21 +1440,376 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * @throws NullPointerException * if the specified key is {@code null} and the comparator * cannot handle {@code null} keys. - * @since Android 1.0 */ @Override public V put(K key, V value) { - MapEntry<K, V> entry = rbInsert(key); - V result = entry.value; - entry.value = value; - return result; + if (root == null) { + root = createNode(key, value); + size = 1; + modCount++; + return null; + } + Comparable<K> object = comparator == null ? toComparable((K) key) : null; + K keyK = (K) key; + Node<K, V> node = root; + Node<K, V> prevNode = null; + int result = 0; + while (node != null) { + prevNode = node; + K[] keys = node.keys; + int left_idx = node.left_idx; + result = cmp(object, keyK, keys[left_idx]); + if (result < 0) { + node = node.left; + } else if (result == 0) { + V res = node.values[left_idx]; + node.values[left_idx] = value; + return res; + } else { + int right_idx = node.right_idx; + if (left_idx != right_idx) { + result = cmp(object, keyK, keys[right_idx]); + } + if (result > 0) { + node = node.right; + } else if (result == 0) { + V res = node.values[right_idx]; + node.values[right_idx] = value; + return res; + } else { /*search in node*/ + int low = left_idx + 1, mid = 0, high = right_idx - 1; + while (low <= high) { + mid = (low + high) >> 1; + result = cmp(object, keyK, keys[mid]); + if (result > 0) { + low = mid + 1; + } else if (result == 0) { + V res = node.values[mid]; + node.values[mid] = value; + return res; + } else { + high = mid - 1; + } + } + result = low; + break; + } + } + } /* while */ +/* + if(node == null) { + if(prevNode==null) { + - case of empty Tree + } else { + result < 0 - prevNode.left==null - attach here + result > 0 - prevNode.right==null - attach here + } + } else { + insert into node. + result - index where it should be inserted. + } + */ + size++; + modCount++; + if (node == null) { + if (prevNode == null) { + // case of empty Tree + root = createNode(key, value); + } else if (prevNode.size < Node.NODE_SIZE) { + // there is a place for insert + if (result < 0) { + appendFromLeft(prevNode, key, value); + } else { + appendFromRight(prevNode, key, value); + } + } else { + // create and link + Node<K, V> newNode = createNode(key, value); + if (result < 0) { + attachToLeft(prevNode, newNode); + } else { + attachToRight(prevNode, newNode); + } + balance(newNode); + } + } else { + // insert into node. + // result - index where it should be inserted. + if (node.size < Node.NODE_SIZE) { // insert and ok + int left_idx = node.left_idx; + int right_idx = node.right_idx; + if (left_idx == 0 || ((right_idx != Node.NODE_SIZE - 1) && (right_idx - result <= result - left_idx))) { + int right_idxPlus1 = right_idx + 1; + System.arraycopy(node.keys, result, node.keys, result + 1, right_idxPlus1 - result); + System.arraycopy(node.values, result, node.values, result + 1, right_idxPlus1 - result); + node.right_idx = right_idxPlus1; + node.keys[result] = key; + node.values[result] = value; + } else { + int left_idxMinus1 = left_idx - 1; + System.arraycopy(node.keys, left_idx, node.keys, left_idxMinus1, result - left_idx); + System.arraycopy(node.values, left_idx, node.values, left_idxMinus1, result - left_idx); + node.left_idx = left_idxMinus1; + node.keys[result - 1] = key; + node.values[result - 1] = value; + } + node.size++; + } else { + // there are no place here + // insert and push old pair + Node<K, V> previous = node.prev; + Node<K, V> nextNode = node.next; + boolean removeFromStart; + boolean attachFromLeft = false; + Node<K, V> attachHere = null; + if (previous == null) { + if (nextNode != null && nextNode.size < Node.NODE_SIZE) { + // move last pair to next + removeFromStart = false; + } else { + // next node doesn't exist or full + // left==null + // drop first pair to new node from left + removeFromStart = true; + attachFromLeft = true; + attachHere = node; + } + } else if (nextNode == null) { + if (previous.size < Node.NODE_SIZE) { + // move first pair to prev + removeFromStart = true; + } else { + // right == null; + // drop last pair to new node from right + removeFromStart = false; + attachFromLeft = false; + attachHere = node; + } + } else { + if (previous.size < Node.NODE_SIZE) { + if (nextNode.size < Node.NODE_SIZE) { + // choose prev or next for moving + removeFromStart = previous.size < nextNode.size; + } else { + // move first pair to prev + removeFromStart = true; + } + } else { + if (nextNode.size < Node.NODE_SIZE) { + // move last pair to next + removeFromStart = false; + } else { + // prev & next are full + // if node.right!=null then node.next.left==null + // if node.left!=null then node.prev.right==null + if (node.right == null) { + attachHere = node; + attachFromLeft = false; + removeFromStart = false; + } else { + attachHere = nextNode; + attachFromLeft = true; + removeFromStart = false; + } + } + } + } + K movedKey; + V movedValue; + if (removeFromStart) { + // node.left_idx == 0 + movedKey = node.keys[0]; + movedValue = node.values[0]; + int resMunus1 = result - 1; + System.arraycopy(node.keys, 1, node.keys, 0, resMunus1); + System.arraycopy(node.values, 1, node.values, 0, resMunus1); + node.keys [resMunus1] = key; + node.values[resMunus1] = value; + } else { + // node.right_idx == Node.NODE_SIZE - 1 + movedKey = node.keys[Node.NODE_SIZE - 1]; + movedValue = node.values[Node.NODE_SIZE - 1]; + System.arraycopy(node.keys, result, node.keys, result + 1, Node.NODE_SIZE - 1 - result); + System.arraycopy(node.values, result, node.values, result + 1, Node.NODE_SIZE - 1 - result); + node.keys[result] = key; + node.values[result] = value; + } + if (attachHere == null) { + if (removeFromStart) { + appendFromRight(previous, movedKey, movedValue); + } else { + appendFromLeft(nextNode, movedKey, movedValue); + } + } else { + Node<K, V> newNode = createNode(movedKey, movedValue); + if (attachFromLeft) { + attachToLeft(attachHere, newNode); + } else { + attachToRight(attachHere, newNode); + } + balance(newNode); + } + } + } + return null; + } + + private void appendFromLeft(Node<K, V> node, K keyObj, V value) { + if (node.left_idx == 0) { + int new_right = node.right_idx + 1; + System.arraycopy(node.keys, 0, node.keys, 1, new_right); + System.arraycopy(node.values, 0, node.values, 1, new_right); + node.right_idx = new_right; + } else { + node.left_idx--; + } + node.size++; + node.keys[node.left_idx] = keyObj; + node.values[node.left_idx] = value; + } + + private void attachToLeft(Node<K, V> node, Node<K, V> newNode) { + newNode.parent = node; + // node.left==null - attach here + node.left = newNode; + Node<K, V> predecessor = node.prev; + newNode.prev = predecessor; + newNode.next = node; + if (predecessor != null) { + predecessor.next = newNode; + } + node.prev = newNode; + } + + /* add pair into node; existence free room in the node should be checked + * before call + */ + private void appendFromRight(Node<K, V> node, K keyObj, V value) { + if (node.right_idx == Node.NODE_SIZE - 1) { + int left_idx = node.left_idx; + int left_idxMinus1 = left_idx - 1; + System.arraycopy(node.keys, left_idx, node.keys, left_idxMinus1, Node.NODE_SIZE - left_idx); + System.arraycopy(node.values, left_idx, node.values, left_idxMinus1, Node.NODE_SIZE - left_idx); + node.left_idx = left_idxMinus1; + } else { + node.right_idx++; + } + node.size++; + node.keys[node.right_idx] = keyObj; + node.values[node.right_idx] = value; + } + + private void attachToRight(Node<K, V> node, Node<K, V> newNode) { + newNode.parent = node; + // - node.right==null - attach here + node.right = newNode; + newNode.prev = node; + Node<K, V> successor = node.next; + newNode.next = successor; + if (successor != null) { + successor.prev = newNode; + } + node.next = newNode; + } + + private Node<K, V> createNode(K keyObj, V value) { + Node<K, V> node = new Node<K, V>(); + node.keys[0] = keyObj; + node.values[0] = value; + node.left_idx = 0; + node.right_idx = 0; + node.size = 1; + return node; + } + + void balance(Node<K, V> x) { + Node<K, V> y; + x.color = true; + while (x != root && x.parent.color) { + if (x.parent == x.parent.parent.left) { + y = x.parent.parent.right; + if (y != null && y.color) { + x.parent.color = false; + y.color = false; + x.parent.parent.color = true; + x = x.parent.parent; + } else { + if (x == x.parent.right) { + x = x.parent; + leftRotate(x); + } + x.parent.color = false; + x.parent.parent.color = true; + rightRotate(x.parent.parent); + } + } else { + y = x.parent.parent.left; + if (y != null && y.color) { + x.parent.color = false; + y.color = false; + x.parent.parent.color = true; + x = x.parent.parent; + } else { + if (x == x.parent.left) { + x = x.parent; + rightRotate(x); + } + x.parent.color = false; + x.parent.parent.color = true; + leftRotate(x.parent.parent); + } + } + } + root.color = false; } + private void rightRotate(Node<K, V> x) { + Node<K, V> y = x.left; + x.left = y.right; + if (y.right != null) { + y.right.parent = x; + } + y.parent = x.parent; + if (x.parent == null) { + root = y; + } else { + if (x == x.parent.right) { + x.parent.right = y; + } else { + x.parent.left = y; + } + } + y.right = x; + x.parent = y; + } + + + private void leftRotate(Node<K, V> x) { + Node<K, V> y = x.right; + x.right = y.left; + if (y.left != null) { + y.left.parent = x; + } + y.parent = x.parent; + if (x.parent == null) { + root = y; + } else { + if (x == x.parent.left) { + x.parent.left = y; + } else { + x.parent.right = y; + } + } + y.left = x; + x.parent = y; + } + + /** * Copies all the mappings in the given map to this map. These mappings will * replace all mappings that this map had for any of the keys currently in * the given map. - * + * * @param map * the map to copy mappings from. * @throws ClassCastException @@ -1248,131 +1818,443 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * @throws NullPointerException * if a key in the specified map is {@code null} and the * comparator cannot handle {@code null} keys. - * @since Android 1.0 */ @Override public void putAll(Map<? extends K, ? extends V> map) { super.putAll(map); } - void rbDelete(Entry<K, V> z) { - Entry<K, V> y = z.left == null || z.right == null ? z : successor(z); - Entry<K, V> x = y.left != null ? y.left : y.right; - if (x != null) { - x.parent = y.parent; + /** + * Removes the mapping with the specified key from this map. + * + * @param key + * the key of the mapping to remove. + * @return the value of the removed mapping or {@code null} if no mapping + * for the specified key was found. + * @throws ClassCastException + * if the specified key cannot be compared with the keys in this + * map. + * @throws NullPointerException + * if the specified key is {@code null} and the comparator + * cannot handle {@code null} keys. + */ + @Override + public V remove(Object key) { + if (size == 0) { + return null; + } + Comparable<K> object = comparator == null ? toComparable((K) key) : null; + K keyK = (K) key; + Node<K, V> node = root; + while (node != null) { + K[] keys = node.keys; + int left_idx = node.left_idx; + int result = cmp(object, keyK, keys[left_idx]); + if (result < 0) { + node = node.left; + } else if (result == 0) { + V value = node.values[left_idx]; + removeLeftmost(node); + return value; + } else { + int right_idx = node.right_idx; + if (left_idx != right_idx) { + result = cmp(object, keyK, keys[right_idx]); + } + if (result > 0) { + node = node.right; + } else if (result == 0) { + V value = node.values[right_idx]; + removeRightmost(node); + return value; + } else { /*search in node*/ + int low = left_idx + 1, mid = 0, high = right_idx - 1; + while (low <= high) { + mid = (low + high) >> 1; + result = cmp(object, keyK, keys[mid]); + if (result > 0) { + low = mid + 1; + } else if (result == 0) { + V value = node.values[mid]; + removeMiddleElement(node, mid); + return value; + } else { + high = mid - 1; + } + } + return null; + } + } } - if (y.parent == null) { - root = x; - } else if (y == y.parent.left) { - y.parent.left = x; + return null; + } + + void removeLeftmost(Node<K, V> node) { + int index = node.left_idx; + if (node.size == 1) { + deleteNode(node); + } else if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) { + // move all to prev node and kill it + Node<K, V> prev = node.prev; + int size = node.right_idx - index; + System.arraycopy(node.keys, index + 1, prev.keys, prev.right_idx + 1, size); + System.arraycopy(node.values, index + 1, prev.values, prev.right_idx + 1, size); + prev.right_idx += size; + prev.size += size; + deleteNode(node); + } else if (node.next != null && (node.next.left_idx) > node.size) { + // move all to next node and kill it + Node<K, V> next = node.next; + int size = node.right_idx - index; + int next_new_left = next.left_idx - size; + next.left_idx = next_new_left; + System.arraycopy(node.keys, index + 1, next.keys, next_new_left, size); + System.arraycopy(node.values, index + 1, next.values, next_new_left, size); + next.size += size; + deleteNode(node); } else { - y.parent.right = x; + node.keys[index] = null; + node.values[index] = null; + node.left_idx++; + node.size--; + Node<K, V> prev = node.prev; + if (prev != null && prev.size == 1) { + node.size++; + node.left_idx--; + node.keys [node.left_idx] = prev.keys [prev.left_idx]; + node.values[node.left_idx] = prev.values[prev.left_idx]; + deleteNode(prev); + } } modCount++; - if (y != z) { - z.key = y.key; - z.value = y.value; + size--; + } + + void removeRightmost(Node<K, V> node) { + int index = node.right_idx; + if (node.size == 1) { + deleteNode(node); + } else if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) { + // move all to prev node and kill it + Node<K, V> prev = node.prev; + int left_idx = node.left_idx; + int size = index - left_idx; + System.arraycopy(node.keys, left_idx, prev.keys, prev.right_idx + 1, size); + System.arraycopy(node.values, left_idx, prev.values, prev.right_idx + 1, size); + prev.right_idx += size; + prev.size += size; + deleteNode(node); + } else if (node.next != null && (node.next.left_idx) > node.size) { + // move all to next node and kill it + Node<K, V> next = node.next; + int left_idx = node.left_idx; + int size = index - left_idx; + int next_new_left = next.left_idx - size; + next.left_idx = next_new_left; + System.arraycopy(node.keys, left_idx, next.keys, next_new_left, size); + System.arraycopy(node.values, left_idx, next.values, next_new_left, size); + next.size += size; + deleteNode(node); + } else { + node.keys[index] = null; + node.values[index] = null; + node.right_idx--; + node.size--; + Node<K, V> next = node.next; + if (next != null && next.size == 1) { + node.size++; + node.right_idx++; + node.keys[node.right_idx] = next.keys[next.left_idx]; + node.values[node.right_idx] = next.values[next.left_idx]; + deleteNode(next); + } } - if (!y.color && root != null) { - if (x == null) { - fixup(y.parent); + modCount++; + size--; + } + + void removeMiddleElement(Node<K, V> node, int index) { + // this function is called iff index if some middle element; + // so node.left_idx < index < node.right_idx + // condition above assume that node.size > 1 + if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) { + // move all to prev node and kill it + Node<K, V> prev = node.prev; + int left_idx = node.left_idx; + int size = index - left_idx; + System.arraycopy(node.keys, left_idx, prev.keys, prev.right_idx + 1, size); + System.arraycopy(node.values, left_idx, prev.values, prev.right_idx + 1, size); + prev.right_idx += size; + size = node.right_idx - index; + System.arraycopy(node.keys, index + 1, prev.keys, prev.right_idx + 1, size); + System.arraycopy(node.values, index + 1, prev.values, prev.right_idx + 1, size); + prev.right_idx += size; + prev.size += (node.size - 1); + deleteNode(node); + } else if (node.next != null && (node.next.left_idx) > node.size) { + // move all to next node and kill it + Node<K, V> next = node.next; + int left_idx = node.left_idx; + int next_new_left = next.left_idx - node.size + 1; + next.left_idx = next_new_left; + int size = index - left_idx; + System.arraycopy(node.keys, left_idx, next.keys, next_new_left, size); + System.arraycopy(node.values, left_idx, next.values, next_new_left, size); + next_new_left += size; + size = node.right_idx - index; + System.arraycopy(node.keys, index + 1, next.keys, next_new_left, size); + System.arraycopy(node.values, index + 1, next.values, next_new_left, size); + next.size += (node.size - 1); + deleteNode(node); + } else { + int moveFromRight = node.right_idx - index; + int left_idx = node.left_idx; + int moveFromLeft = index - left_idx ; + if (moveFromRight <= moveFromLeft) { + System.arraycopy(node.keys, index + 1, node.keys, index, moveFromRight); + System.arraycopy(node.values, index + 1, node.values, index, moveFromRight); + Node<K, V> next = node.next; + if (next != null && next.size == 1) { + node.keys [node.right_idx] = next.keys [next.left_idx]; + node.values[node.right_idx] = next.values[next.left_idx]; + deleteNode(next); + } else { + node.keys [node.right_idx] = null; + node.values[node.right_idx] = null; + node.right_idx--; + node.size--; + } } else { - fixup(x); + System.arraycopy(node.keys, left_idx , node.keys, left_idx + 1, moveFromLeft); + System.arraycopy(node.values, left_idx , node.values, left_idx + 1, moveFromLeft); + Node<K, V> prev = node.prev; + if (prev != null && prev.size == 1) { + node.keys [left_idx ] = prev.keys [prev.left_idx]; + node.values[left_idx ] = prev.values[prev.left_idx]; + deleteNode(prev); + } else { + node.keys [left_idx ] = null; + node.values[left_idx ] = null; + node.left_idx++; + node.size--; + } } } + modCount++; size--; } - private Entry<K, V> rbInsert(K object) { - int result = 0; - Entry<K, V> y = null; - if (size != 0) { - Comparable<K> key = null; - if (comparator == null) { - key = toComparable(object); - } - Entry<K, V> x = root; - while (x != null) { - y = x; - result = key != null ? key.compareTo(x.key) : comparator - .compare(object, x.key); - if (result == 0) { - return x; + void removeFromIterator(Node<K, V> node, int index) { + if (node.size == 1) { + // it is safe to delete the whole node here. + // iterator already moved to the next node; + deleteNode(node); + } else { + int left_idx = node.left_idx; + if (index == left_idx) { + Node<K, V> prev = node.prev; + if (prev != null && prev.size == 1) { + node.keys [left_idx] = prev.keys [prev.left_idx]; + node.values[left_idx] = prev.values[prev.left_idx]; + deleteNode(prev); + } else { + node.keys [left_idx] = null; + node.values[left_idx] = null; + node.left_idx++; + node.size--; } - x = result < 0 ? x.left : x.right; + } else if (index == node.right_idx) { + node.keys [index] = null; + node.values[index] = null; + node.right_idx--; + node.size--; + } else { + int moveFromRight = node.right_idx - index; + int moveFromLeft = index - left_idx; + if (moveFromRight <= moveFromLeft) { + System.arraycopy(node.keys, index + 1, node.keys, index, moveFromRight ); + System.arraycopy(node.values, index + 1, node.values, index, moveFromRight ); + node.keys [node.right_idx] = null; + node.values[node.right_idx] = null; + node.right_idx--; + node.size--; + } else { + System.arraycopy(node.keys, left_idx, node.keys, left_idx+ 1, moveFromLeft); + System.arraycopy(node.values, left_idx, node.values, left_idx+ 1, moveFromLeft); + node.keys [left_idx] = null; + node.values[left_idx] = null; + node.left_idx++; + node.size--; + } } } - - size++; modCount++; - Entry<K, V> z = new Entry<K, V>(object); - if (y == null) { - return root = z; + size--; + } + + private void deleteNode(Node<K, V> node) { + if (node.right == null) { + if (node.left != null) { + attachToParent(node, node.left); + } else { + attachNullToParent(node); + } + fixNextChain(node); + } else if(node.left == null) { // node.right != null + attachToParent(node, node.right); + fixNextChain(node); + } else { + // Here node.left!=nul && node.right!=null + // node.next should replace node in tree + // node.next!=null by tree logic. + // node.next.left==null by tree logic. + // node.next.right may be null or non-null + Node<K, V> toMoveUp = node.next; + fixNextChain(node); + if(toMoveUp.right==null){ + attachNullToParent(toMoveUp); + } else { + attachToParent(toMoveUp, toMoveUp.right); + } + // Here toMoveUp is ready to replace node + toMoveUp.left = node.left; + if (node.left != null) { + node.left.parent = toMoveUp; + } + toMoveUp.right = node.right; + if (node.right != null) { + node.right.parent = toMoveUp; + } + attachToParentNoFixup(node,toMoveUp); + toMoveUp.color = node.color; } - z.parent = y; - if (result < 0) { - y.left = z; + } + + private void attachToParentNoFixup(Node<K, V> toDelete, Node<K, V> toConnect) { + // assert toConnect!=null + Node<K,V> parent = toDelete.parent; + toConnect.parent = parent; + if (parent == null) { + root = toConnect; + } else if (toDelete == parent.left) { + parent.left = toConnect; } else { - y.right = z; + parent.right = toConnect; } - balance(z); - return z; } - /** - * Removes the mapping with the specified key from this map. - * - * @param key - * the key of the mapping to remove. - * @return the value of the removed mapping or {@code null} if no mapping - * for the specified key was found. - * @throws ClassCastException - * if the specified key cannot be compared with the keys in this - * map. - * @throws NullPointerException - * if the specified key is {@code null} and the comparator - * cannot handle {@code null} keys. - * @since Android 1.0 - */ - @Override - public V remove(Object key) { - if (size == 0) { - return null; + private void attachToParent(Node<K, V> toDelete, Node<K, V> toConnect) { + // assert toConnect!=null + attachToParentNoFixup(toDelete,toConnect); + if (!toDelete.color) { + fixup(toConnect); } - Entry<K, V> node = find(key); - if (node == null) { - return null; + } + + private void attachNullToParent(Node<K, V> toDelete) { + Node<K, V> parent = toDelete.parent; + if (parent == null) { + root = null; + } else { + if (toDelete == parent.left) { + parent.left = null; + } else { + parent.right = null; + } + if (!toDelete.color) { + fixup(parent); + } } - V result = node.value; - rbDelete(node); - return result; } - private void rightRotate(Entry<K, V> x) { - Entry<K, V> y = x.left; - x.left = y.right; - if (y.right != null) { - y.right.parent = x; + private void fixNextChain(Node<K, V> node) { + if (node.prev != null) { + node.prev.next = node.next; } - y.parent = x.parent; - if (x.parent == null) { - root = y; - } else { - if (x == x.parent.right) { - x.parent.right = y; + if (node.next != null) { + node.next.prev = node.prev; + } + } + + private void fixup(Node<K, V> x) { + Node<K, V> w; + while (x != root && !x.color) { + if (x == x.parent.left) { + w = x.parent.right; + if (w == null) { + x = x.parent; + continue; + } + if (w.color) { + w.color = false; + x.parent.color = true; + leftRotate(x.parent); + w = x.parent.right; + if (w == null) { + x = x.parent; + continue; + } + } + if ((w.left == null || !w.left.color) + && (w.right == null || !w.right.color)) { + w.color = true; + x = x.parent; + } else { + if (w.right == null || !w.right.color) { + w.left.color = false; + w.color = true; + rightRotate(w); + w = x.parent.right; + } + w.color = x.parent.color; + x.parent.color = false; + w.right.color = false; + leftRotate(x.parent); + x = root; + } } else { - x.parent.left = y; + w = x.parent.left; + if (w == null) { + x = x.parent; + continue; + } + if (w.color) { + w.color = false; + x.parent.color = true; + rightRotate(x.parent); + w = x.parent.left; + if (w == null) { + x = x.parent; + continue; + } + } + if ((w.left == null || !w.left.color) + && (w.right == null || !w.right.color)) { + w.color = true; + x = x.parent; + } else { + if (w.left == null || !w.left.color) { + w.right.color = false; + w.color = true; + leftRotate(w); + w = x.parent.left; + } + w.color = x.parent.color; + x.parent.color = false; + w.left.color = false; + rightRotate(x.parent); + x = root; + } } } - y.right = x; - x.parent = y; + x.color = false; } + /** * Returns the number of mappings in this map. - * + * * @return the number of mappings in this map. - * @since Android 1.0 */ @Override public int size() { @@ -1387,8 +2269,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * <p> * Note: The returned map will not allow an insertion of a key outside the * specified range. - * </p> - * + * * @param startKey * the low boundary of the range (inclusive). * @param endKey @@ -1404,7 +2285,6 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * if the start key is greater than the end key, or if this map * is itself a sorted map over a range of another sorted map and * the specified range is outside of its range. - * @since Android 1.0 */ public SortedMap<K, V> subMap(K startKey, K endKey) { if (comparator == null) { @@ -1419,18 +2299,6 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, throw new IllegalArgumentException(); } - static <K, V> Entry<K, V> successor(Entry<K, V> x) { - if (x.right != null) { - return minimum(x.right); - } - Entry<K, V> y = x.parent; - while (y != null && x == y.right) { - x = y; - y = y.parent; - } - return y; - } - /** * Returns a sorted map over a range of this sorted map with all keys that * are greater than or equal to the specified {@code startKey}. Changes to @@ -1438,8 +2306,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * <p> * Note: The returned map will not allow an insertion of a key outside the * specified range. - * </p> - * + * * @param startKey * the low boundary of the range specified. * @return a sorted map where the keys are greater or equal to @@ -1453,7 +2320,6 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * @throws IllegalArgumentException * if this map itself a sorted map over a range of another map * and the specified key is outside of its range. - * @since Android 1.0 */ public SortedMap<K, V> tailMap(K startKey) { // Check for errors @@ -1476,16 +2342,13 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, * "wrapper object" over the iterator of map's entrySet(). The {@code size} * method wraps the map's size method and the {@code contains} method wraps * the map's containsValue method. - * </p> * <p> * The collection is created when this method is called for the first time * and returned in response to all subsequent calls. This method may return * different collections when multiple concurrent calls occur, since no * synchronization is performed. - * </p> - * + * * @return a collection of the values contained in this map. - * @since Android 1.0 */ @Override public Collection<V> values() { @@ -1508,7 +2371,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, @Override public Iterator<V> iterator() { - return new UnboundedValueIterator<K,V> (TreeMap.this); + return new UnboundedValueIterator<K, V>(TreeMap.this); } }; } @@ -1519,32 +2382,26 @@ public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, stream.defaultWriteObject(); stream.writeInt(size); if (size > 0) { - Entry<K, V> node = minimum(root); + Node<K, V> node = minimum(root); while (node != null) { - stream.writeObject(node.key); - stream.writeObject(node.value); - node = successor(node); + int to = node.right_idx; + for (int i = node.left_idx; i <= to; i++) { + stream.writeObject(node.keys[i]); + stream.writeObject(node.values[i]); + } + node = node.next; } } } @SuppressWarnings("unchecked") private void readObject(ObjectInputStream stream) throws IOException, - ClassNotFoundException { + ClassNotFoundException { stream.defaultReadObject(); - size = stream.readInt(); - Entry<K, V> last = null; - for (int i = size; --i >= 0;) { - Entry<K, V> node = new Entry<K, V>((K)stream.readObject()); - node.value = (V)stream.readObject(); - if (last == null) { - root = node; - } else { - node.parent = last; - last.right = node; - balance(node); - } - last = node; + int size = stream.readInt(); + Node<K, V> lastNode = null; + for (int i = 0; i < size; i++) { + lastNode = addToLast(lastNode, (K) stream.readObject(), (V) stream.readObject()); } } } diff --git a/luni/src/main/java/java/util/TreeSet.java b/luni/src/main/java/java/util/TreeSet.java index bfd572f..375b9c8 100644 --- a/luni/src/main/java/java/util/TreeSet.java +++ b/luni/src/main/java/java/util/TreeSet.java @@ -17,7 +17,6 @@ package java.util; - import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -28,25 +27,23 @@ import java.io.Serializable; * and removing) are supported. The elements can be any objects which are * comparable to each other either using their natural order or a specified * Comparator. - * - * @since Android 1.0 + * + * @since 1.2 */ -public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneable, - Serializable { - +public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, + Cloneable, Serializable { + private static final long serialVersionUID = -2479143000061671589L; private transient SortedMap<E, E> backingMap; - private TreeSet(SortedMap<E,E> map) { + private TreeSet(SortedMap<E, E> map) { this.backingMap = map; } /** * Constructs a new empty instance of {@code TreeSet} which uses natural * ordering. - * - * @since Android 1.0 */ public TreeSet() { backingMap = new TreeMap<E, E>(); @@ -55,14 +52,13 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Constructs a new instance of {@code TreeSet} which uses natural ordering * and containing the unique elements in the specified collection. - * + * * @param collection * the collection of elements to add. * @throws ClassCastException * when an element in the collection does not implement the * Comparable interface, or the elements in the collection * cannot be compared. - * @since Android 1.0 */ public TreeSet(Collection<? extends E> collection) { this(); @@ -72,10 +68,9 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Constructs a new empty instance of {@code TreeSet} which uses the * specified comparator. - * + * * @param comparator * the comparator to use. - * @since Android 1.0 */ public TreeSet(Comparator<? super E> comparator) { backingMap = new TreeMap<E, E>(comparator); @@ -84,10 +79,9 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Constructs a new instance of {@code TreeSet} containing the elements of * the specified SortedSet and using the same Comparator. - * + * * @param set * the SortedSet of elements to add. - * @since Android 1.0 */ public TreeSet(SortedSet<E> set) { this(set.comparator()); @@ -99,7 +93,7 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Adds the specified object to this {@code TreeSet}. - * + * * @param object * the object to add. * @return {@code true} when this {@code TreeSet} did not already contain @@ -110,7 +104,6 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * @throws NullPointerException * when the object is null and the comparator cannot handle * null. - * @since Android 1.0 */ @Override public boolean add(E object) { @@ -119,7 +112,7 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Adds the objects in the specified collection to this {@code TreeSet}. - * + * * @param collection * the collection of objects to add. * @return {@code true} if this {@code TreeSet} was modified, {@code false} @@ -130,7 +123,6 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * @throws NullPointerException * when an object in the collection is null and the comparator * cannot handle null. - * @since Android 1.0 */ @Override public boolean addAll(Collection<? extends E> collection) { @@ -139,10 +131,9 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Removes all elements from this {@code TreeSet}, leaving it empty. - * + * * @see #isEmpty * @see #size - * @since Android 1.0 */ @Override public void clear() { @@ -152,10 +143,9 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Returns a new {@code TreeSet} with the same elements, size and comparator * as this {@code TreeSet}. - * + * * @return a shallow copy of this {@code TreeSet}. * @see java.lang.Cloneable - * @since Android 1.0 */ @SuppressWarnings("unchecked") @Override @@ -163,7 +153,8 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl try { TreeSet<E> clone = (TreeSet<E>) super.clone(); if (backingMap instanceof TreeMap) { - clone.backingMap = (SortedMap<E, E>) ((TreeMap<E, E>) backingMap).clone(); + clone.backingMap = (SortedMap<E, E>) ((TreeMap<E, E>) backingMap) + .clone(); } else { clone.backingMap = new TreeMap<E, E>(backingMap); } @@ -175,9 +166,8 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Returns the comparator used to compare elements in this {@code TreeSet}. - * + * * @return a Comparator or null if the natural ordering is used - * @since Android 1.0 */ public Comparator<? super E> comparator() { return backingMap.comparator(); @@ -185,7 +175,7 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Searches this {@code TreeSet} for the specified object. - * + * * @param object * the object to search for. * @return {@code true} if {@code object} is an element of this @@ -196,7 +186,6 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * @throws NullPointerException * when the object is null and the comparator cannot handle * null. - * @since Android 1.0 */ @Override public boolean contains(Object object) { @@ -205,11 +194,10 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Returns the first element in this {@code TreeSet}. - * + * * @return the first element. * @throws NoSuchElementException * when this {@code TreeSet} is empty. - * @since Android 1.0 */ public E first() { return backingMap.firstKey(); @@ -220,7 +208,7 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * which contains elements which are all less than the end element. The * returned SortedSet is backed by this {@code TreeSet} so changes to one * are reflected by the other. - * + * * @param end * the end element. * @return a subset where the elements are less than {@code end} @@ -230,7 +218,6 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * @throws NullPointerException * when the end object is null and the comparator cannot handle * null. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public SortedSet<E> headSet(E end) { @@ -246,10 +233,9 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Returns true if this {@code TreeSet} has no element, otherwise false. - * + * * @return true if this {@code TreeSet} has no element. * @see #size - * @since Android 1.0 */ @Override public boolean isEmpty() { @@ -258,10 +244,9 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Returns an Iterator on the elements of this {@code TreeSet}. - * + * * @return an Iterator on the elements of this {@code TreeSet}. * @see Iterator - * @since Android 1.0 */ @Override public Iterator<E> iterator() { @@ -271,11 +256,10 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Returns the last element in this {@code TreeSet}. The last element is * the highest element. - * + * * @return the last element. * @throws NoSuchElementException * when this {@code TreeSet} is empty. - * @since Android 1.0 */ public E last() { return backingMap.lastKey(); @@ -283,7 +267,7 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Removes an occurrence of the specified object from this {@code TreeSet}. - * + * * @param object * the object to remove. * @return {@code true} if this {@code TreeSet} was modified, {@code false} @@ -294,7 +278,6 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * @throws NullPointerException * when the object is null and the comparator cannot handle * null. - * @since Android 1.0 */ @Override public boolean remove(Object object) { @@ -303,9 +286,8 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl /** * Returns the number of elements in this {@code TreeSet}. - * + * * @return the number of elements in this {@code TreeSet}. - * @since Android 1.0 */ @Override public int size() { @@ -317,7 +299,7 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * which contains elements greater or equal to the start element but less * than the end element. The returned SortedSet is backed by this * {@code TreeSet} so changes to one are reflected by the other. - * + * * @param start * the start element. * @param end @@ -330,7 +312,6 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * @throws NullPointerException * when the start or end object is null and the comparator * cannot handle null. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public SortedSet<E> subSet(E start, E end) { @@ -352,7 +333,7 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * which contains elements greater or equal to the start element. The * returned SortedSet is backed by this {@code TreeSet} so changes to one * are reflected by the other. - * + * * @param start * the start element. * @return a subset where the elements are greater or equal to {@code start} @@ -362,7 +343,6 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl * @throws NullPointerException * when the start object is null and the comparator cannot * handle null. - * @since Android 1.0 */ @SuppressWarnings("unchecked") public SortedSet<E> tailSet(E start) { @@ -391,23 +371,16 @@ public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneabl @SuppressWarnings("unchecked") private void readObject(ObjectInputStream stream) throws IOException, - ClassNotFoundException { + ClassNotFoundException { stream.defaultReadObject(); - TreeMap<E, E> map = new TreeMap<E, E>((Comparator<? super E>) stream.readObject()); + TreeMap<E, E> map = new TreeMap<E, E>((Comparator<? super E>) stream + .readObject()); int size = stream.readInt(); if (size > 0) { - E key = (E)stream.readObject(); - TreeMap.Entry<E,E> last = new TreeMap.Entry<E,E>(key,key); - map.root = last; - map.size = 1; - for (int i=1; i<size; i++) { - key = (E)stream.readObject(); - TreeMap.Entry<E,E> x = new TreeMap.Entry<E,E>(key,key); - x.parent = last; - last.right = x; - map.size++; - map.balance(x); - last = x; + TreeMap.Node<E,E> lastNode = null; + for(int i=0; i<size; i++) { + E elem = (E)stream.readObject(); + lastNode = map.addToLast(lastNode,elem,elem); } } backingMap = map; diff --git a/luni/src/main/java/java/util/UUID.java b/luni/src/main/java/java/util/UUID.java index a5ab702..081e900 100644 --- a/luni/src/main/java/java/util/UUID.java +++ b/luni/src/main/java/java/util/UUID.java @@ -27,19 +27,16 @@ import java.security.SecureRandom; import org.apache.harmony.luni.util.Msg; /** - * <p> * UUID is an immutable representation of a 128-bit universally unique * identifier (UUID). - * </p> * <p> * There are multiple, variant layouts of UUIDs, but this class is based upon * variant 2 of <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>, the * Leach-Salz variant. This class can be used to model alternate variants, but * most of the methods will be unsupported in those cases; see each method for * details. - * </p> - * - * @since Android 1.0 + * + * @since 1.5 */ public final class UUID implements Serializable, Comparable<UUID> { @@ -60,13 +57,11 @@ public final class UUID implements Serializable, Comparable<UUID> { /** * <p> * Constructs an instance with the specified bits. - * </p> - * + * * @param mostSigBits * The 64 most significant bits of the UUID. * @param leastSigBits * The 64 least significant bits of the UUID. - * @since Android 1.0 */ public UUID(long mostSigBits, long leastSigBits) { super(); @@ -79,7 +74,6 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * Sets up the transient fields of this instance based on the current values * of the {@code mostSigBits} and {@code leastSigBits} fields. - * </p> */ private void init() { // setup hash field @@ -123,10 +117,8 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * Generates a variant 2, version 4 (randomly generated number) UUID as per * <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. - * </p> - * + * * @return an UUID instance. - * @since Android 1.0 */ public static UUID randomUUID() { byte[] data; @@ -135,9 +127,8 @@ public final class UUID implements Serializable, Comparable<UUID> { if (rng == null) { rng = new SecureRandom(); } - rng.nextBytes(data = new byte[16]); } - + rng.nextBytes(data = new byte[16]); long msb = (data[0] & 0xFFL) << 56; msb |= (data[1] & 0xFFL) << 48; msb |= (data[2] & 0xFFL) << 40; @@ -164,12 +155,10 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * Generates a variant 2, version 3 (name-based, MD5-hashed) UUID as per <a * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. - * </p> - * + * * @param name * the name used as byte array to create an UUID. * @return an UUID instance. - * @since Android 1.0 */ public static UUID nameUUIDFromBytes(byte[] name) { if (name == null) { @@ -209,57 +198,57 @@ public final class UUID implements Serializable, Comparable<UUID> { /** * <p> * Parses a UUID string with the format defined by {@link #toString()}. - * </p> - * + * * @param uuid * the UUID string to parse. * @return an UUID instance. + * @throws NullPointerException + * if {@code uuid} is {@code null}. * @throws IllegalArgumentException * if {@code uuid} is not formatted correctly. - * @since Android 1.0 */ public static UUID fromString(String uuid) { if (uuid == null) { throw new NullPointerException(); } - + int[] position = new int[5]; int lastPosition = 1; int startPosition = 0; - + int i = 0; - for (; i < position.length && lastPosition > 0; i++) { + for (; i < position.length && lastPosition > 0; i++) { position[i] = uuid.indexOf("-", startPosition); //$NON-NLS-1$ lastPosition = position[i]; startPosition = position[i] + 1; } // should have and only can have four "-" in UUID - if(i != position.length || lastPosition != -1) - { + if (i != position.length || lastPosition != -1) { throw new IllegalArgumentException(Msg.getString("KA014") + uuid); //$NON-NLS-1$ } long m1 = Long.parseLong(uuid.substring(0, position[0]), 16); - long m2 = Long.parseLong(uuid.substring(position[0]+ 1, position[1]), 16); - long m3 = Long.parseLong(uuid.substring(position[1] + 1, position[2]), 16); + long m2 = Long.parseLong(uuid.substring(position[0] + 1, position[1]), + 16); + long m3 = Long.parseLong(uuid.substring(position[1] + 1, position[2]), + 16); - long lsb1 = Long.parseLong(uuid.substring(position[2] + 1, position[3]), 16); - long lsb2 = Long.parseLong(uuid.substring(position[3]+ 1), 16); + long lsb1 = Long.parseLong( + uuid.substring(position[2] + 1, position[3]), 16); + long lsb2 = Long.parseLong(uuid.substring(position[3] + 1), 16); long msb = (m1 << 32) | (m2 << 16) | m3; long lsb = (lsb1 << 48) | lsb2; - + return new UUID(msb, lsb); } /** * <p> * The 64 least significant bits of the UUID. - * </p> - * + * * @return the 64 least significant bits. - * @since Android 1.0 */ public long getLeastSignificantBits() { return leastSigBits; @@ -268,10 +257,8 @@ public final class UUID implements Serializable, Comparable<UUID> { /** * <p> * The 64 most significant bits of the UUID. - * </p> - * + * * @return the 64 most significant bits. - * @since Android 1.0 */ public long getMostSignificantBits() { return mostSigBits; @@ -282,7 +269,6 @@ public final class UUID implements Serializable, Comparable<UUID> { * The version of the variant 2 UUID as per <a * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. If the variant * is not 2, then the version will be 0. - * </p> * <ul> * <li>1 - Time-based UUID</li> * <li>2 - DCE Security UUID</li> @@ -290,9 +276,8 @@ public final class UUID implements Serializable, Comparable<UUID> { * <li>4 - Randomly generated UUID ({@link #randomUUID()})</li> * <li>5 - Name-based with SHA-1 hashing UUID</li> * </ul> - * + * * @return an {@code int} value. - * @since Android 1.0 */ public int version() { return version; @@ -302,16 +287,14 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * The variant of the UUID as per <a * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. - * </p> * <ul> * <li>0 - Reserved for NCS compatibility</li> * <li>2 - RFC 4122/Leach-Salz</li> * <li>6 - Reserved for Microsoft Corporation compatibility</li> * <li>7 - Reserved for future use</li> * </ul> - * + * * @return an {@code int} value. - * @since Android 1.0 */ public int variant() { return variant; @@ -321,12 +304,10 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * The timestamp value of the version 1, variant 2 UUID as per <a * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. - * </p> - * + * * @return a {@code long} value. * @throws UnsupportedOperationException * if {@link #version()} is not 1. - * @since Android 1.0 */ public long timestamp() { if (version != 1) { @@ -339,12 +320,10 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * The clock sequence value of the version 1, variant 2 UUID as per <a * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. - * </p> - * + * * @return a {@code long} value. * @throws UnsupportedOperationException * if {@link #version()} is not 1. - * @since Android 1.0 */ public int clockSequence() { if (version != 1) { @@ -357,12 +336,10 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * The node value of the version 1, variant 2 UUID as per <a * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. - * </p> - * + * * @return a {@code long} value. * @throws UnsupportedOperationException * if {@link #version()} is not 1. - * @since Android 1.0 */ public long node() { if (version != 1) { @@ -376,13 +353,11 @@ public final class UUID implements Serializable, Comparable<UUID> { * Compares this UUID to the specified UUID. The natural ordering of UUIDs * is based upon the value of the bits from most significant to least * significant. - * </p> - * + * * @param uuid * the UUID to compare to. * @return a value of -1, 0 or 1 if this UUID is less than, equal to or * greater than {@code uuid}. - * @since Android 1.0 */ public int compareTo(UUID uuid) { if (uuid == this) { @@ -409,13 +384,11 @@ public final class UUID implements Serializable, Comparable<UUID> { * Compares this UUID to another object for equality. If {@code object} * is not {@code null}, is a UUID instance, and all bits are equal, then * {@code true} is returned. - * </p> - * + * * @param object * the {@code Object} to compare to. * @return {@code true} if this UUID is equal to {@code object} * or {@code false} if not. - * @since Android 1.0 */ @Override public boolean equals(Object object) { @@ -441,10 +414,8 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * Returns a hash value for this UUID that is consistent with the * {@link #equals(Object)} method. - * </p> - * + * * @return an {@code int} value. - * @since Android 1.0 */ @Override public int hashCode() { @@ -455,8 +426,7 @@ public final class UUID implements Serializable, Comparable<UUID> { * <p> * Returns a string representation of this UUID in the following format, as * per <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. - * </p> - * + * * <pre> * UUID = time-low "-" time-mid "-" * time-high-and-version "-" @@ -474,9 +444,8 @@ public final class UUID implements Serializable, Comparable<UUID> { * "a" / "b" / "c" / "d" / "e" / "f" / * "A" / "B" / "C" / "D" / "E" / "F" * </pre> - * + * * @return a String instance. - * @since Android 1.0 */ @Override public String toString() { @@ -507,8 +476,7 @@ public final class UUID implements Serializable, Comparable<UUID> { /** * <p> * Resets the transient fields to match the behavior of the constructor. - * </p> - * + * * @param in * the {@code InputStream} to read from. * @throws IOException diff --git a/luni/src/main/java/java/util/UnknownFormatConversionException.java b/luni/src/main/java/java/util/UnknownFormatConversionException.java index 19b9b6d..8bb9441 100644 --- a/luni/src/main/java/java/util/UnknownFormatConversionException.java +++ b/luni/src/main/java/java/util/UnknownFormatConversionException.java @@ -22,7 +22,6 @@ import org.apache.harmony.luni.util.Msg; * conversion is unknown. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class UnknownFormatConversionException extends IllegalFormatException { private static final long serialVersionUID = 19060418L; diff --git a/luni/src/main/java/java/util/UnknownFormatFlagsException.java b/luni/src/main/java/java/util/UnknownFormatFlagsException.java index 837328a..2a1b075 100644 --- a/luni/src/main/java/java/util/UnknownFormatFlagsException.java +++ b/luni/src/main/java/java/util/UnknownFormatFlagsException.java @@ -23,7 +23,6 @@ import org.apache.harmony.luni.util.Msg; * an unknown flag. * * @see java.lang.RuntimeException - * @since Android 1.0 */ public class UnknownFormatFlagsException extends IllegalFormatException { diff --git a/luni/src/main/java/java/util/Vector.java b/luni/src/main/java/java/util/Vector.java index 7a5c775..8634c13 100644 --- a/luni/src/main/java/java/util/Vector.java +++ b/luni/src/main/java/java/util/Vector.java @@ -17,7 +17,6 @@ package java.util; - import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; @@ -36,26 +35,21 @@ import java.lang.reflect.Array; * The capacity of a vector may be specified when the vector is created. If the * capacity of the vector is exceeded, the capacity is increased (doubled by * default). - * + * * @see java.lang.StringBuffer - * @since Android 1.0 */ -public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, - Cloneable, Serializable { - +public class Vector<E> extends AbstractList<E> implements List<E>, + RandomAccess, Cloneable, Serializable { + private static final long serialVersionUID = -2767605614048989439L; /** * The number of elements or the size of the vector. - * - * @since Android 1.0 */ protected int elementCount; /** * The elements of the vector. - * - * @since Android 1.0 */ protected Object[] elementData; @@ -63,8 +57,6 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * How many elements should be added to the vector when it is detected that * it needs to grow to accommodate extra entries. If this value is zero or * negative the size will be doubled if an increase is needed. - * - * @since Android 1.0 */ protected int capacityIncrement; @@ -72,8 +64,6 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Constructs a new vector using the default capacity. - * - * @since Android 1.0 */ public Vector() { this(DEFAULT_SIZE, 0); @@ -81,12 +71,11 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Constructs a new vector using the specified capacity. - * + * * @param capacity * the initial capacity of the new vector. * @throws IllegalArgumentException * if {@code capacity} is negative. - * @since Android 1.0 */ public Vector(int capacity) { this(capacity, 0); @@ -95,22 +84,20 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Constructs a new vector using the specified capacity and capacity * increment. - * + * * @param capacity * the initial capacity of the new vector. * @param capacityIncrement * the amount to increase the capacity when this vector is full. * @throws IllegalArgumentException * if {@code capacity} is negative. - * @since Android 1.0 */ public Vector(int capacity, int capacityIncrement) { - elementCount = 0; - try { - elementData = newElementArray(capacity); - } catch (NegativeArraySizeException e) { + if (capacity < 0) { throw new IllegalArgumentException(); } + elementData = newElementArray(capacity); + elementCount = 0; this.capacityIncrement = capacityIncrement; } @@ -118,10 +105,9 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Constructs a new instance of {@code Vector} containing the elements in * {@code collection}. The order of the elements in the new {@code Vector} * is dependent on the iteration order of the seed collection. - * + * * @param collection * the collection of elements to add. - * @since Android 1.0 */ public Vector(Collection<? extends E> collection) { this(collection.size(), 0); @@ -130,10 +116,10 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, elementData[elementCount++] = it.next(); } } - + @SuppressWarnings("unchecked") private E[] newElementArray(int size) { - return (E[])new Object[size]; + return (E[]) new Object[size]; } /** @@ -141,16 +127,15 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * object is inserted before any element with the same or a higher index * increasing their index by 1. If the location is equal to the size of this * vector, the object is added at the end. - * + * * @param location * the index at which to insert the element. * @param object * the object to insert in this vector. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0 || location > size()}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0 || location > size()}. * @see #addElement * @see #size - * @since Android 1.0 */ @Override public void add(int location, E object) { @@ -159,15 +144,18 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Adds the specified object at the end of this vector. - * + * * @param object * the object to add to the vector. * @return {@code true} - * @since Android 1.0 */ @Override - public boolean add(E object) { - addElement(object); + public synchronized boolean add(E object) { + if (elementCount == elementData.length) { + growByOne(); + } + elementData[elementCount++] = object; + modCount++; return true; } @@ -177,18 +165,18 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * returned from the Collection iterator. The elements with an index equal * or higher than {@code location} have their index increased by the size of * the added collection. - * + * * @param location * the location to insert the objects. * @param collection * the collection of objects. * @return {@code true} if this vector is modified, {@code false} otherwise. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0} or {@code location > size()}. - * @since Android 1.0 + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0} or {@code location > size()}. */ @Override - public synchronized boolean addAll(int location, Collection<? extends E> collection) { + public synchronized boolean addAll(int location, + Collection<? extends E> collection) { if (0 <= location && location <= elementCount) { int size = collection.size(); if (size == 0) { @@ -216,11 +204,10 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Adds the objects in the specified collection to the end of this vector. - * + * * @param collection * the collection of objects. * @return {@code true} if this vector is modified, {@code false} otherwise. - * @since Android 1.0 */ @Override public synchronized boolean addAll(Collection<? extends E> collection) { @@ -229,10 +216,9 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Adds the specified object at the end of this vector. - * + * * @param object * the object to add to the vector. - * @since Android 1.0 */ public synchronized void addElement(E object) { if (elementCount == elementData.length) { @@ -244,11 +230,10 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns the number of elements this vector can hold without growing. - * + * * @return the capacity of this vector. * @see #ensureCapacity * @see #size - * @since Android 1.0 */ public synchronized int capacity() { return elementData.length; @@ -256,10 +241,9 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Removes all elements from this vector, leaving it empty. - * + * * @see #isEmpty * @see #size - * @since Android 1.0 */ @Override public void clear() { @@ -269,10 +253,9 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns a new vector with the same elements, size, capacity and capacity * increment as this vector. - * + * * @return a shallow copy of this vector. * @see java.lang.Cloneable - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -288,7 +271,7 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Searches this vector for the specified object. - * + * * @param object * the object to look for in this vector. * @return {@code true} if object is an element of this vector, @@ -296,7 +279,6 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * @see #indexOf(Object) * @see #indexOf(Object, int) * @see java.lang.Object#equals - * @since Android 1.0 */ @Override public boolean contains(Object object) { @@ -305,12 +287,11 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Searches this vector for all objects in the specified collection. - * + * * @param collection * the collection of objects. * @return {@code true} if all objects in the specified collection are * elements of this vector, {@code false} otherwise. - * @since Android 1.0 */ @Override public synchronized boolean containsAll(Collection<?> collection) { @@ -320,14 +301,13 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Attempts to copy elements contained by this {@code Vector} into the * corresponding elements of the supplied {@code Object} array. - * + * * @param elements * the {@code Object} array into which the elements of this * vector are copied. * @throws IndexOutOfBoundsException * if {@code elements} is not big enough. * @see #clone - * @since Android 1.0 */ public synchronized void copyInto(Object[] elements) { System.arraycopy(elementData, 0, elements, 0, elementCount); @@ -335,18 +315,18 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns the element at the specified location in this vector. - * + * * @param location * the index of the element to return in this vector. * @return the element at the specified location. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0 || location >= size()}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0 || location >= size()}. * @see #size - * @since Android 1.0 */ + @SuppressWarnings("unchecked") public synchronized E elementAt(int location) { if (location < elementCount) { - return (E)elementData[location]; + return (E) elementData[location]; } throw new ArrayIndexOutOfBoundsException(location); } @@ -354,26 +334,24 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns an enumeration on the elements of this vector. The results of the * enumeration may be affected if the contents of this vector is modified. - * + * * @return an enumeration of the elements of this vector. * @see #elementAt * @see Enumeration - * @since Android 1.0 */ public Enumeration<E> elements() { return new Enumeration<E>() { int pos = 0; public boolean hasMoreElements() { - synchronized (Vector.this) { - return pos < elementCount; - } + return pos < elementCount; } + @SuppressWarnings("unchecked") public E nextElement() { synchronized (Vector.this) { if (pos < elementCount) { - return (E)elementData[pos++]; + return (E) elementData[pos++]; } } throw new NoSuchElementException(); @@ -384,12 +362,11 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Ensures that this vector can hold the specified number of elements * without growing. - * + * * @param minimumCapacity * the minimum number of elements that this vector will hold * before growing. * @see #capacity - * @since Android 1.0 */ public synchronized void ensureCapacity(int minimumCapacity) { if (elementData.length < minimumCapacity) { @@ -404,13 +381,12 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Compares the specified object to this vector and returns if they are * equal. The object must be a List which contains the same objects in the * same order. - * + * * @param object * the object to compare with this object * @return {@code true} if the specified object is equal to this vector, * {@code false} otherwise. * @see #hashCode - * @since Android 1.0 */ @Override public synchronized boolean equals(Object object) { @@ -418,8 +394,8 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, return true; } if (object instanceof List) { - List<?> list = (List) object; - if (list.size() != size()) { + List<?> list = (List<?>) object; + if (list.size() != elementCount) { return false; } @@ -438,35 +414,34 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns the first element in this vector. - * + * * @return the element at the first position. - * @exception NoSuchElementException - * when this vector is empty. + * @throws NoSuchElementException + * if this vector is empty. * @see #elementAt * @see #lastElement * @see #size - * @since Android 1.0 */ + @SuppressWarnings("unchecked") public synchronized E firstElement() { if (elementCount > 0) { - return (E)elementData[0]; + return (E) elementData[0]; } throw new NoSuchElementException(); } /** * Returns the element at the specified location in this vector. - * + * * @param location * the index of the element to return in this vector. * @return the element at the specified location. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0 || location >= size()}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0 || location >= size()}. * @see #size - * @since Android 1.0 */ @Override - public synchronized E get(int location) { + public E get(int location) { return elementAt(location); } @@ -474,7 +449,7 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, E[] newData = newElementArray(newCapacity); // Assumes elementCount is <= newCapacity assert elementCount <= newCapacity; - System.arraycopy(elementData, 0, newData, 0, elementCount); + System.arraycopy(elementData, 0, newData, 0, elementCount); elementData = newData; } @@ -519,10 +494,9 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns an integer hash code for the receiver. Objects which are equal * return the same value for this method. - * + * * @return the receiver's hash. * @see #equals - * @since Android 1.0 */ @Override public synchronized int hashCode() { @@ -538,7 +512,7 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Searches in this vector for the index of the specified object. The search * for the object starts at the beginning and moves towards the end of this * vector. - * + * * @param object * the object to find in this vector. * @return the index in this vector of the specified element, -1 if the @@ -546,7 +520,6 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * @see #contains * @see #lastIndexOf(Object) * @see #lastIndexOf(Object, int) - * @since Android 1.0 */ @Override public int indexOf(Object object) { @@ -557,19 +530,18 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Searches in this vector for the index of the specified object. The search * for the object starts at the specified location and moves towards the end * of this vector. - * + * * @param object * the object to find in this vector. * @param location * the index at which to start searching. * @return the index in this vector of the specified element, -1 if the * element isn't found. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0}. * @see #contains * @see #lastIndexOf(Object) * @see #lastIndexOf(Object, int) - * @since Android 1.0 */ public synchronized int indexOf(Object object, int location) { if (object != null) { @@ -594,16 +566,15 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * location. All elements with an index equal or greater than * {@code location} have their index increased by 1. If the location is * equal to the size of this vector, the object is added at the end. - * + * * @param object * the object to insert in this vector. * @param location * the index at which to insert the element. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0 || location > size()}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0 || location > size()}. * @see #addElement * @see #size - * @since Android 1.0 */ public synchronized void insertElementAt(E object, int location) { if (0 <= location && location <= elementCount) { @@ -625,11 +596,10 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns if this vector has no elements, a size of zero. - * + * * @return {@code true} if this vector has no elements, {@code false} * otherwise. * @see #size - * @since Android 1.0 */ @Override public synchronized boolean isEmpty() { @@ -638,18 +608,18 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns the last element in this vector. - * + * * @return the element at the last position. - * @exception NoSuchElementException - * when this vector is empty. + * @throws NoSuchElementException + * if this vector is empty. * @see #elementAt * @see #firstElement * @see #size - * @since Android 1.0 */ + @SuppressWarnings("unchecked") public synchronized E lastElement() { try { - return (E)elementData[elementCount - 1]; + return (E) elementData[elementCount - 1]; } catch (IndexOutOfBoundsException e) { throw new NoSuchElementException(); } @@ -659,7 +629,7 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Searches in this vector for the index of the specified object. The search * for the object starts at the end and moves towards the start of this * vector. - * + * * @param object * the object to find in this vector. * @return the index in this vector of the specified element, -1 if the @@ -667,7 +637,6 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * @see #contains * @see #indexOf(Object) * @see #indexOf(Object, int) - * @since Android 1.0 */ @Override public synchronized int lastIndexOf(Object object) { @@ -678,19 +647,18 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Searches in this vector for the index of the specified object. The search * for the object starts at the specified location and moves towards the * start of this vector. - * + * * @param object * the object to find in this vector. * @param location * the index at which to start searching. * @return the index in this vector of the specified element, -1 if the * element isn't found. - * @exception ArrayIndexOutOfBoundsException - * when {@code location >= size()}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location >= size()}. * @see #contains * @see #indexOf(Object) * @see #indexOf(Object, int) - * @since Android 1.0 */ public synchronized int lastIndexOf(Object object, int location) { if (location < elementCount) { @@ -716,18 +684,18 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Removes the object at the specified location from this vector. All * elements with an index bigger than {@code location} have their index * decreased by 1. - * + * * @param location * the index of the object to remove. * @return the removed object. - * @exception IndexOutOfBoundsException - * when {@code location < 0 || location >= size()}. - * @since Android 1.0 + * @throws IndexOutOfBoundsException + * if {@code location < 0 || location >= size()}. */ + @SuppressWarnings("unchecked") @Override public synchronized E remove(int location) { if (location < elementCount) { - E result = (E)elementData[location]; + E result = (E) elementData[location]; elementCount--; int size = elementCount - location; if (size > 0) { @@ -746,7 +714,7 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * towards the end, of the specified object from this vector. All elements * with an index bigger than the element that gets removed have their index * decreased by 1. - * + * * @param object * the object to remove from this vector. * @return {@code true} if the specified object was found, {@code false} @@ -754,7 +722,6 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * @see #removeAllElements * @see #removeElementAt * @see #size - * @since Android 1.0 */ @Override public boolean remove(Object object) { @@ -764,13 +731,12 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Removes all occurrences in this vector of each object in the specified * Collection. - * + * * @param collection * the collection of objects to remove. * @return {@code true} if this vector is modified, {@code false} otherwise. * @see #remove(Object) * @see #contains(Object) - * @since Android 1.0 */ @Override public synchronized boolean removeAll(Collection<?> collection) { @@ -780,13 +746,14 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Removes all elements from this vector, leaving the size zero and the * capacity unchanged. - * + * * @see #isEmpty * @see #size - * @since Android 1.0 */ public synchronized void removeAllElements() { - Arrays.fill(elementData, 0, elementCount, null); + for (int i = 0; i < elementCount; i++) { + elementData[i] = null; + } modCount++; elementCount = 0; } @@ -796,7 +763,7 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * towards the end, of the specified object from this vector. All elements * with an index bigger than the element that gets removed have their index * decreased by 1. - * + * * @param object * the object to remove from this vector. * @return {@code true} if the specified object was found, {@code false} @@ -804,7 +771,6 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * @see #removeAllElements * @see #removeElementAt * @see #size - * @since Android 1.0 */ public synchronized boolean removeElement(Object object) { int index; @@ -819,15 +785,14 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Removes the element found at index position {@code location} from * this {@code Vector}. All elements with an index bigger than * {@code location} have their index decreased by 1. - * + * * @param location * the index of the element to remove. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0 || location >= size()}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0 || location >= size()}. * @see #removeElement * @see #removeAllElements * @see #size - * @since Android 1.0 */ public synchronized void removeElementAt(int location) { if (0 <= location && location < elementCount) { @@ -848,19 +813,18 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Removes the objects in the specified range from the start to the, but not * including, end index. All elements with an index bigger than or equal to * {@code end} have their index decreased by {@code end - start}. - * + * * @param start * the index at which to start removing. * @param end * the index one past the end of the range to remove. - * @exception IndexOutOfBoundsException - * when {@code start < 0, start > end} or + * @throws IndexOutOfBoundsException + * if {@code start < 0, start > end} or * {@code end > size()}. - * @since Android 1.0 */ @Override protected void removeRange(int start, int end) { - if (start >= 0 && start <= end && end <= size()) { + if (start >= 0 && start <= end && end <= elementCount) { if (start == end) { return; } @@ -883,12 +847,11 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Removes all objects from this vector that are not contained in the * specified collection. - * + * * @param collection * the collection of objects to retain. * @return {@code true} if this vector is modified, {@code false} otherwise. * @see #remove(Object) - * @since Android 1.0 */ @Override public synchronized boolean retainAll(Collection<?> collection) { @@ -898,21 +861,21 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Replaces the element at the specified location in this vector with the * specified object. - * + * * @param location * the index at which to put the specified object. * @param object * the object to add to this vector. * @return the previous element at the location. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0 || location >= size()}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0 || location >= size()}. * @see #size - * @since Android 1.0 */ + @SuppressWarnings("unchecked") @Override public synchronized E set(int location, E object) { if (location < elementCount) { - E result = (E)elementData[location]; + E result = (E) elementData[location]; elementData[location] = object; return result; } @@ -922,15 +885,14 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Replaces the element at the specified location in this vector with the * specified object. - * + * * @param object * the object to add to this vector. * @param location * the index at which to put the specified object. - * @exception ArrayIndexOutOfBoundsException - * when {@code location < 0 || location >= size()}. + * @throws ArrayIndexOutOfBoundsException + * if {@code location < 0 || location >= size()}. * @see #size - * @since Android 1.0 */ public synchronized void setElementAt(E object, int location) { if (location < elementCount) { @@ -945,11 +907,10 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * than length elements in this vector, the elements at end are lost. If * there are less than length elements in the vector, the additional * elements contain null. - * + * * @param length * the new size of this vector. * @see #size - * @since Android 1.0 */ public synchronized void setSize(int length) { if (length == elementCount) { @@ -965,11 +926,10 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns the number of elements in this vector. - * + * * @return the number of elements in this vector. * @see #elementCount * @see #lastElement - * @since Android 1.0 */ @Override public synchronized int size() { @@ -980,29 +940,27 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * Returns a List of the specified portion of this vector from the start * index to one less than the end index. The returned List is backed by this * vector so changes to one are reflected by the other. - * + * * @param start * the index at which to start the sublist. * @param end * the index one past the end of the sublist. * @return a List of a portion of this vector. - * @exception IndexOutOfBoundsException - * when {@code start < 0} or {@code end > size()}. - * @exception IllegalArgumentException - * when {@code start > end}. - * @since Android 1.0 + * @throws IndexOutOfBoundsException + * if {@code start < 0} or {@code end > size()}. + * @throws IllegalArgumentException + * if {@code start > end}. */ @Override public synchronized List<E> subList(int start, int end) { - return new Collections.SynchronizedRandomAccessList<E>( - super.subList(start, end), this); + return new Collections.SynchronizedRandomAccessList<E>(super.subList( + start, end), this); } /** * Returns a new array containing all elements contained in this vector. - * + * * @return an array of the elements from this vector. - * @since Android 1.0 */ @Override public synchronized Object[] toArray() { @@ -1017,14 +975,13 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, * is used, otherwise an array of the same type is created. If the specified * array is used and is larger than this vector, the array element following * the collection elements is set to null. - * + * * @param contents * the array to fill. * @return an array of the elements from this vector. - * @exception ArrayStoreException - * when the type of an element in this vector cannot be + * @throws ArrayStoreException + * if the type of an element in this vector cannot be * stored in the type of the specified array. - * @since Android 1.0 */ @Override @SuppressWarnings("unchecked") @@ -1042,29 +999,28 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Returns the string representation of this vector. - * + * * @return the string representation of this vector. * @see #elements - * @since Android 1.0 */ @Override public synchronized String toString() { if (elementCount == 0) { - return "[]"; + return "[]"; //$NON-NLS-1$ } int length = elementCount - 1; - StringBuffer buffer = new StringBuffer(size() * 16); + StringBuffer buffer = new StringBuffer(elementCount * 16); buffer.append('['); for (int i = 0; i < length; i++) { if (elementData[i] == this) { - buffer.append("(this Collection)"); + buffer.append("(this Collection)"); //$NON-NLS-1$ } else { buffer.append(elementData[i]); } - buffer.append(", "); + buffer.append(", "); //$NON-NLS-1$ } if (elementData[length] == this) { - buffer.append("(this Collection)"); + buffer.append("(this Collection)"); //$NON-NLS-1$ } else { buffer.append(elementData[length]); } @@ -1074,11 +1030,10 @@ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, /** * Sets the capacity of this vector to be the same as the size. - * + * * @see #capacity * @see #ensureCapacity * @see #size - * @since Android 1.0 */ public synchronized void trimToSize() { if (elementData.length != elementCount) { diff --git a/luni/src/main/java/java/util/WeakHashMap.java b/luni/src/main/java/java/util/WeakHashMap.java index e0228e2..01e15af 100644 --- a/luni/src/main/java/java/util/WeakHashMap.java +++ b/luni/src/main/java/java/util/WeakHashMap.java @@ -26,10 +26,10 @@ import java.lang.ref.WeakReference; * optional operations (adding and removing) are supported. Keys and values can * be any objects. Note that the garbage collector acts similar to a second * thread on this collection, possibly removing keys. - * + * + * @since 1.2 * @see HashMap * @see WeakReference - * @since Android 1.0 */ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { @@ -127,7 +127,7 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { } public boolean hasNext() { - if (nextEntry != null) { + if (nextEntry != null && (nextKey != null || nextEntry.isNull)) { return true; } while (true) { @@ -183,8 +183,6 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Constructs a new empty {@code WeakHashMap} instance. - * - * @since Android 1.0 */ public WeakHashMap() { this(DEFAULT_SIZE); @@ -193,12 +191,11 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Constructs a new {@code WeakHashMap} instance with the specified * capacity. - * + * * @param capacity * the initial capacity of this map. * @throws IllegalArgumentException * if the capacity is less than zero. - * @since Android 1.0 */ public WeakHashMap(int capacity) { if (capacity >= 0) { @@ -215,7 +212,7 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Constructs a new {@code WeakHashMap} instance with the specified capacity * and load factor. - * + * * @param capacity * the initial capacity of this map. * @param loadFactor @@ -223,7 +220,6 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { * @throws IllegalArgumentException * if the capacity is less than zero or the load factor is less * or equal to zero. - * @since Android 1.0 */ public WeakHashMap(int capacity, float loadFactor) { if (capacity >= 0 && loadFactor > 0) { @@ -240,10 +236,9 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Constructs a new {@code WeakHashMap} instance containing the mappings * from the specified map. - * + * * @param map * the mappings to add. - * @since Android 1.0 */ public WeakHashMap(Map<? extends K, ? extends V> map) { this(map.size() < 6 ? 11 : map.size() * 2); @@ -252,10 +247,9 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Removes all mappings from this map, leaving it empty. - * + * * @see #isEmpty() * @see #size() - * @since Android 1.0 */ @Override public void clear() { @@ -275,12 +269,11 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Returns whether this map contains the specified key. - * + * * @param key * the key to search for. * @return {@code true} if this map contains the specified key, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsKey(Object key) { @@ -292,9 +285,8 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { * an instance of {@link Map.Entry}. As the set is backed by this map, * changes in one will be reflected in the other. It does not support adding * operations. - * + * * @return a set of the mappings. - * @since Android 1.0 */ @Override public Set<Map.Entry<K, V>> entrySet() { @@ -351,9 +343,8 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { * Returns a set of the keys contained in this map. The set is backed by * this map so changes to one are reflected by the other. The set does not * support adding. - * + * * @return a set of the keys. - * @since Android 1.0 */ @Override public Set<K> keySet() { @@ -392,6 +383,26 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { } }); } + + @Override + public Object[] toArray() { + Collection<K> coll = new ArrayList<K>(size()); + + for (Iterator<K> iter = iterator(); iter.hasNext();) { + coll.add(iter.next()); + } + return coll.toArray(); + } + + @Override + public <T> T[] toArray(T[] contents) { + Collection<K> coll = new ArrayList<K>(size()); + + for (Iterator<K> iter = iterator(); iter.hasNext();) { + coll.add(iter.next()); + } + return coll.toArray(contents); + } }; } return keySet; @@ -408,16 +419,13 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { * "wrapper object" over the iterator of map's entrySet(). The size method * wraps the map's size method and the contains method wraps the map's * containsValue method. - * </p> * <p> * The collection is created when this method is called at first time and * returned in response to all subsequent calls. This method may return * different Collection when multiple calls to this method, since it has no * synchronization performed. - * </p> - * + * * @return a collection of the values contained in this map. - * @since Android 1.0 */ @Override public Collection<V> values() { @@ -454,12 +462,11 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Returns the value of the mapping with the specified key. - * + * * @param key * the key. * @return the value of the mapping with the specified key, or {@code null} * if no mapping for the specified key is found. - * @since Android 1.0 */ @Override public V get(Object key) { @@ -510,12 +517,11 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Returns whether this map contains the specified value. - * + * * @param value * the value to search for. * @return {@code true} if this map contains the specified value, * {@code false} otherwise. - * @since Android 1.0 */ @Override public boolean containsValue(Object value) { @@ -549,9 +555,8 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Returns the number of elements in this map. - * + * * @return the number of elements in this map. - * @since Android 1.0 */ @Override public boolean isEmpty() { @@ -590,14 +595,13 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Maps the specified key to the specified value. - * + * * @param key * the key. * @param value * the value. * @return the value of any previous mapping with the specified key or * {@code null} if there was no mapping. - * @since Android 1.0 */ @Override public V put(K key, V value) { @@ -658,10 +662,11 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { * Copies all the mappings in the given map to this map. These mappings will * replace all mappings that this map had for any of the keys currently in * the given map. - * + * * @param map * the map to copy mappings from. - * @since Android 1.0 + * @throws NullPointerException + * if {@code map} is {@code null}. */ @Override public void putAll(Map<? extends K, ? extends V> map) { @@ -670,12 +675,11 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Removes the mapping with the specified key from this map. - * + * * @param key * the key of the mapping to remove. * @return the value of the removed mapping or {@code null} if no mapping * for the specified key was found. - * @since Android 1.0 */ @Override public V remove(Object key) { @@ -711,9 +715,8 @@ public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { /** * Returns the number of elements in this map. - * + * * @return the number of elements in this map. - * @since Android 1.0 */ @Override public int size() { diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java index e288f1a..be6da05 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java @@ -51,7 +51,7 @@ public class MimeTable implements FileNameMap { } /** - * Contructs a MIME table using the default values defined in this class. + * Constructs a MIME table using the default values defined in this class. * * It then augments this table by reading pairs of extensions and * corresponding content types from the file "content-types.properties", diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java index 07357be..7f738d3 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java @@ -59,16 +59,9 @@ public class FileURLConnection extends URLConnection { public FileURLConnection(URL url) { super(url); fileName = url.getFile(); - if (url.getRef() != null) { - fileName += "#" + url.getRef(); //$NON-NLS-1$ - } if (fileName == null) { fileName = ""; //$NON-NLS-1$ } - String host = url.getHost(); - if (host != null && host.length() > 0) { - fileName = "//" + host + fileName; //$NON-NLS-1$ - } fileName = Util.decode(fileName, false); } @@ -131,13 +124,23 @@ public class FileURLConnection extends URLConnection { return MimeTable.UNKNOWN; } if (isDir) { - return "text/html"; //$NON-NLS-1$ + return "text/plain"; //$NON-NLS-1$ } String result = guessContentTypeFromName(url.getFile()); - if (result == null) { - return MimeTable.UNKNOWN; + if (result != null) { + return result; } - return result; + + try { + result = guessContentTypeFromStream(is); + } catch (IOException e) { + // Ignore + } + if (result != null) { + return result; + } + + return MimeTable.UNKNOWN; } /** diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java index 909e611..1b5bfb9 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java @@ -41,15 +41,15 @@ public class Handler extends URLStreamHandler { * */ @Override - public URLConnection openConnection(URL url) { - return new FileURLConnection(url); + public URLConnection openConnection(URL url) throws IOException { + return openConnection(url, null); } /** * The behaviour of this method is the same as openConnection(URL). * <code>proxy</code> is not used in FileURLConnection. * - * @param u + * @param url * the URL which the connection is pointing to * @param proxy * Proxy @@ -58,18 +58,28 @@ public class Handler extends URLStreamHandler { * @throws IOException * if this handler fails to establish a connection. * @throws IllegalArgumentException - * if any argument is null or of an invalid type. + * if the url argument is null. * @throws UnsupportedOperationException * if the protocol handler doesn't support this method. */ @Override public URLConnection openConnection(URL url, Proxy proxy) throws IOException { - if (null == url || null == proxy) { + if (null == url) { // K034b=url and proxy can not be null throw new IllegalArgumentException(Msg.getString("K034b")); //$NON-NLS-1$ } - return new FileURLConnection(url); + + String host = url.getHost(); + if (host == null || host.length() == 0 + || host.equalsIgnoreCase("localhost")) { //$NON-NLS-1$ + return new FileURLConnection(url); + } + + // If a hostname is specified try to get the resource using FTP + URL ftpURL = new URL("ftp", host, url.getFile()); //$NON-NLS-1$ + return (proxy == null) ? ftpURL.openConnection() : ftpURL + .openConnection(proxy); } /** diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java index 2d4ab0d..016d5a7 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java @@ -183,22 +183,24 @@ public class FtpURLConnection extends URLConnection { ProxySelector selector = ProxySelector.getDefault(); Iterator<Proxy> iter = proxyList.iterator(); boolean connectOK = false; + String failureReason = ""; //$NON-NLS-1$ while (iter.hasNext() && !connectOK) { currentProxy = iter.next(); try { connectInternal(); connectOK = true; } catch (IOException ioe) { + failureReason = ioe.getLocalizedMessage(); // If connect failed, callback "connectFailed" // should be invoked. if (null != selector && Proxy.NO_PROXY != currentProxy) { - selector - .connectFailed(uri, currentProxy.address(), ioe); + selector.connectFailed(uri, currentProxy.address(), ioe); } } } if (!connectOK) { - throw new IOException(Msg.getString("K0097")); //$NON-NLS-1$ + // K0097=Unable to connect to server\: {0} + throw new IOException(Msg.getString("K0097", failureReason)); //$NON-NLS-1$ } } } diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java index 1f7589d..24be092 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java @@ -118,7 +118,7 @@ public class Header implements Cloneable { /** * Set a field with the specified value. If the field is not found, it is * added. If the field is found, the existing value(s) are overwritten. - * + * * @param key * @param value */ @@ -148,8 +148,10 @@ public class Header implements Cloneable { * Provides an unmodifiable map with all String header names mapped to their * String values. The map keys are Strings and the values are unmodifiable * Lists of Strings. - * + * * @return an unmodifiable map of the headers + * + * @since 1.4 */ public Map<String, List<String>> getFieldMap() { Map<String, List<String>> result = new HashMap<String, List<String>>( @@ -164,7 +166,7 @@ public class Header implements Cloneable { /** * Returns the element at <code>pos</code>, null if no such element * exist. - * + * * @return java.lang.String the value of the key * @param pos * int the position to look for @@ -179,8 +181,8 @@ public class Header implements Cloneable { /** * Returns the key of this header at <code>pos</code>, null if there are * fewer keys in the header - * - * + * + * * @return the key the desired position * @param pos * the position to look for @@ -193,11 +195,12 @@ public class Header implements Cloneable { } /** - * Returns the value corresponding to the specified key, null if no such key - * exists. - * + * Returns the value corresponding to the specified key. + * * @param key - * @return + * the key to look up. + * @return Answers the value for the given key, or <code>null</code> if no + * such key exists. */ public String get(String key) { LinkedList<String> result = keyTable.get(key.toLowerCase()); @@ -209,8 +212,8 @@ public class Header implements Cloneable { /** * Returns the number of keys stored in this header - * - * @return + * + * @return the number of keys. */ public int length() { return props.size() / 2; diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java index 6a26365..55d762d 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java @@ -14,12 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// BEGIN android-note -// This class was copied from a newer version of harmony -// to improve reusability of URLConnections -// END android-note - package org.apache.harmony.luni.internal.net.www.protocol.http; import java.net.InetSocketAddress; @@ -141,4 +135,4 @@ public class HttpConfiguration { return uri.hashCode(); } -} +}
\ No newline at end of file diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java index f7c8d96..4c51bdc 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java @@ -14,12 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// BEGIN android-note -// This class was copied from a newer version of harmony -// to improve reusability of URLConnections -// END android-note - package org.apache.harmony.luni.internal.net.www.protocol.http; import java.io.IOException; @@ -42,6 +36,7 @@ import org.apache.harmony.luni.internal.nls.Messages; * various utility methods to access that connection. */ public class HttpConnection { + private boolean usingSecureSocket = false; private Socket socket; @@ -233,7 +228,7 @@ public class HttpConnection { * Returns whether this connection is eligible to be recycled. This * is like {@link #isStale} except that it doesn't try to actually * perform any I/O. - * + * * @return <code>true</code> if the connection is eligible to be * recycled */ @@ -272,4 +267,5 @@ public class HttpConnection { return null; } } -} + +}
\ No newline at end of file diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java index 9a90612..61d7cbe 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java @@ -14,12 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// BEGIN android-note -// This class was copied from a newer version of harmony -// to improve reusability of URLConnections -// END android-note - package org.apache.harmony.luni.internal.net.www.protocol.http; import java.io.IOException; @@ -179,4 +173,4 @@ public class HttpConnectionManager { pool.clear(); } -} +}
\ No newline at end of file diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java index 6f5a2be..505c6b2 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java @@ -15,11 +15,6 @@ * limitations under the License. */ -// BEGIN android-note -// This class and some helper classes where copied from a newer version of harmony -// to improve reusability of URLConnections -// END android-note - package org.apache.harmony.luni.internal.net.www.protocol.http; import java.io.ByteArrayOutputStream; @@ -185,7 +180,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { return is.skip(n); } - + public int available() throws IOException { if (closed) { throwClosed(); @@ -222,9 +217,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { private void throwClosed() throws IOException { throw new IOException("stream closed"); } - } + } // END android-added - + private class LimitedInputStream extends InputStream { int bytesRemaining; @@ -523,7 +518,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * size minus chunk head (which writes chunk data size in HEX and * "\r\n") size. For example, a string "abcd" use chunk whose size is 5 * must be written to socket as "2\r\nab","2\r\ncd" ... - * + * */ private int calculateChunkDataLength() { /* @@ -691,7 +686,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Creates an instance of the <code>HttpURLConnection</code> using default * port 80. - * + * * @param url * URL The URL this connection is connecting */ @@ -701,7 +696,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Creates an instance of the <code>HttpURLConnection</code> - * + * * @param url * URL The URL this connection is connecting * @param port @@ -711,7 +706,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { super(url); defaultPort = port; reqHeader = (Header) defaultReqHeader.clone(); - + try { uri = url.toURI(); } catch (URISyntaxException e) { @@ -727,7 +722,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Creates an instance of the <code>HttpURLConnection</code> - * + * * @param url * URL The URL this connection is connecting * @param port @@ -742,12 +737,12 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Establishes the connection to the remote HTTP server - * + * * Any methods that requires a valid connection to the resource will call * this method implicitly. After the connection is established, * <code>connected</code> is set to true. - * - * + * + * * @see #connected * @see java.io.IOException * @see URLStreamHandler @@ -762,9 +757,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } // BEGIN android-changed // url.toURI(); throws an URISyntaxException if the url contains - // illegal characters in e.g. the query. - // Since the query is not needed for proxy selection, we just create an - // URI that only contains the necessary information. + // illegal characters in e.g. the query. + // Since the query is not needed for proxy selection, we just create an + // URI that only contains the necessary information. try { uri = new URI(url.getProtocol(), null, @@ -817,7 +812,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } /** - * Returns connected socket to be used for this HTTP connection. + * Returns connected socket to be used for this HTTP connection. */ protected HttpConnection getHTTPConnection(Proxy proxy) throws IOException { HttpConnection connection; @@ -832,7 +827,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Sets up the data streams used to send request[s] and read response[s]. - * + * * @param connection * HttpConnection to be used */ @@ -882,8 +877,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Closes the connection with the HTTP server - * - * + * + * * @see URLConnection#connect() */ @Override @@ -940,7 +935,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * <p> * If the content type is not what stated above, * <code>FileNotFoundException</code> is thrown. - * + * * @return InputStream the error input stream returned by the server. */ @Override @@ -978,14 +973,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Returns the value of the field corresponding to the <code>key</code> * Returns <code>null</code> if there is no such field. - * + * * If there are multiple fields with that key, the last field value is * returned. - * + * * @return java.lang.String The value of the header field * @param key * java.lang.String the name of the header field - * + * * @see #getHeaderField(int) * @see #getHeaderFieldKey */ @@ -1019,8 +1014,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * Provides an unmodifiable map of the connection header values. The map * keys are the String header field names. Each map value is a list of the * header field values associated with that key name. - * + * * @return the mapping of header field names to values + * + * @since 1.4 */ @Override public Map<String, List<String>> getHeaderFields() { @@ -1172,7 +1169,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Returns a line read from the input stream. Does not include the \n - * + * * @return The line that was read. */ String readln() throws IOException { @@ -1215,7 +1212,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * Sends the request header to the remote HTTP server Not all of them are * guaranteed to have any effect on the content the server will return, * depending on if the server supports that field. - * + * * Examples : Accept: text/*, text/html, text/html;level=1, Accept-Charset: * iso-8859-5, unicode-1-1;q=0.8 */ @@ -1327,6 +1324,45 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } else { output.append("1\r\n"); //$NON-NLS-1$ } + // add user-specified request headers if any + boolean hasContentLength = false; + for (int i = 0; i < reqHeader.length(); i++) { + String key = reqHeader.getKey(i); + if (key != null) { + String lKey = key.toLowerCase(); + if ((os != null && !os.isChunked()) + || (!lKey.equals("transfer-encoding") && !lKey //$NON-NLS-1$ + .equals("content-length"))) { //$NON-NLS-1$ + output.append(key); + String value = reqHeader.get(i); + /* + * duplicates are allowed under certain conditions see + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 + */ + if (lKey.equals("content-length")) { //$NON-NLS-1$ + hasContentLength = true; + /* + * if both setFixedLengthStreamingMode and + * content-length are set, use fixedContentLength first + */ + if(fixedContentLength >= 0){ + value = String.valueOf(fixedContentLength); + } + } + if (value != null) { + output.append(": "); //$NON-NLS-1$ + output.append(value); + } + output.append("\r\n"); //$NON-NLS-1$ + } + } + } + if (fixedContentLength >= 0 && !hasContentLength) { + output.append("content-length: "); //$NON-NLS-1$ + output.append(String.valueOf(fixedContentLength)); + output.append("\r\n"); //$NON-NLS-1$ + } + if (reqHeader.get("User-Agent") == null) { //$NON-NLS-1$ output.append("User-Agent: "); //$NON-NLS-1$ String agent = getSystemProperty("http.agent"); //$NON-NLS-1$ @@ -1348,6 +1384,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } output.append("\r\n"); //$NON-NLS-1$ } + if (reqHeader.get("Accept") == null) { //$NON-NLS-1$ + output.append("Accept: *; */*\r\n"); //$NON-NLS-1$ + } if (httpVersion > 0 && reqHeader.get("Connection") == null) { //$NON-NLS-1$ output.append("Connection: Keep-Alive\r\n"); //$NON-NLS-1$ } @@ -1367,43 +1406,6 @@ public class HttpURLConnection extends java.net.HttpURLConnection { output.append("Transfer-Encoding: chunked\r\n"); //$NON-NLS-1$ } } - - boolean hasContentLength = false; - // then the user-specified request headers, if any - for (int i = 0; i < reqHeader.length(); i++) { - String key = reqHeader.getKey(i); - if (key != null) { - String lKey = key.toLowerCase(); - if ((os != null && !os.isChunked()) - || (!lKey.equals("transfer-encoding") && !lKey //$NON-NLS-1$ - .equals("content-length"))) { //$NON-NLS-1$ - output.append(key); - output.append(": "); //$NON-NLS-1$ - /* - * duplicates are allowed under certain conditions see - * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 - */ - if (lKey.equals("content-length")) { //$NON-NLS-1$ - hasContentLength = true; - /* - * if both setFixedLengthStreamingMode and - * content-length are set, use fixedContentLength first - */ - output.append((fixedContentLength >= 0) ? String - .valueOf(fixedContentLength) - : reqHeader.get(i)); - } else { - output.append(reqHeader.get(i)); - } - output.append("\r\n"); //$NON-NLS-1$ - } - } - } - if (fixedContentLength >= 0 && !hasContentLength) { - output.append("content-length: "); //$NON-NLS-1$ - output.append(String.valueOf(fixedContentLength)); - output.append("\r\n"); //$NON-NLS-1$ - } // end the headers output.append("\r\n"); //$NON-NLS-1$ return output.toString().getBytes("ISO8859_1"); //$NON-NLS-1$ @@ -1412,7 +1414,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Sets the default request header fields to be sent to the remote server. * This does not affect the current URL Connection, only newly created ones. - * + * * @param field * java.lang.String The name of the field to be changed * @param value @@ -1427,11 +1429,11 @@ public class HttpURLConnection extends java.net.HttpURLConnection { * <code>setIfModifiedSince()</code> Since this HTTP impl supports * IfModifiedSince as one of the header field, the request header is updated * with the new value. - * - * + * + * * @param newValue * the number of millisecond since epoch - * + * * @throws IllegalStateException * if already connected. */ @@ -1655,7 +1657,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Returns the authorization credentials on the base of provided * authorization challenge - * + * * @param challenge * @return authorization credentials * @throws IOException @@ -1707,4 +1709,4 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } } } -} +}
\ No newline at end of file diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java index 31c1198..4d0aff7 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.harmony.luni.internal.net.www.protocol.https; import java.io.IOException; @@ -22,10 +21,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.ProtocolException; import java.net.Proxy; -// BEGIN andorid-removed -// copied from newer version of harmony -// import java.net.Socket; -// END android-removed import java.net.URL; import java.security.Permission; import java.security.Principal; @@ -390,10 +385,7 @@ public class HttpsURLConnection extends javax.net.ssl.HttpsURLConnection { responseMessage, responseCode)); } // if there are some remaining data in the stream - read it out - // BEGIN andorid-changed - // copied from newer version of harmony InputStream is = connection.getInputStream(); - // END android-changed while (is.available() != 0) { is.read(); } @@ -403,11 +395,8 @@ public class HttpsURLConnection extends javax.net.ssl.HttpsURLConnection { super.connect(); } if (!makingSSLTunnel) { - // BEGIN andorid-changed - // copied from newer version of harmony sslSocket = connection.getSecureSocket(getSSLSocketFactory(), getHostnameVerifier()); setUpTransportIO(connection); - // END android-changed } } @@ -430,23 +419,5 @@ public class HttpsURLConnection extends javax.net.ssl.HttpsURLConnection { return super.requestString(); } - // BEGIN android-removed - // /** - // * Create the secure socket over the connected socket and verify remote - // * hostname. - // */ - // private Socket wrapConnection(Socket socket) throws IOException { - // String hostname = url.getHost(); - // // create the wrapper over connected socket - // sslSocket = (SSLSocket) getSSLSocketFactory().createSocket(socket, - // hostname, url.getPort(), true); - // sslSocket.setUseClientMode(true); - // sslSocket.startHandshake(); - // if (!getHostnameVerifier().verify(hostname, sslSocket.getSession())) { - // throw new IOException(Messages.getString("luni.02", hostname)); //$NON-NLS-1$ - // } - // return sslSocket; - // } - // END android-removed } } diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java index da34969..d299913 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java @@ -36,8 +36,9 @@ public class Handler extends URLStreamHandler { * @param u * java.net.URL The URL to which the connection is pointing to * - * @thows IOException thrown if an IO error occurs when this method tries to - * establish connection. + * @throws IOException + * thrown if an IO error occurs when this method tries to + * establish connection. */ @Override protected URLConnection openConnection(URL u) throws IOException { @@ -75,7 +76,8 @@ public class Handler extends URLStreamHandler { file = file.substring(0, file.indexOf('!') + 1) + spec; } else { int idx = file.indexOf('!'); - String tmpFile = file.substring(idx + 1, file.lastIndexOf('/') + 1) + spec; + String tmpFile = file.substring(idx + 1, file.lastIndexOf('/') + 1) + + spec; tmpFile = URLUtil.canonicalizePath(tmpFile); file = file.substring(0, idx + 1) + tmpFile; } diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java index 5f4896a..56c1f3c 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java +++ b/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java @@ -23,8 +23,6 @@ import java.io.FileOutputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; import java.net.ContentHandler; import java.net.ContentHandlerFactory; import java.net.MalformedURLException; @@ -32,120 +30,38 @@ import java.net.URL; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; -import java.util.Comparator; -import java.util.Date; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.TreeSet; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.zip.ZipFile; -// BEGIN android-removed -// import org.apache.harmony.kernel.vm.VM; -// END android-removed import org.apache.harmony.luni.util.Msg; import org.apache.harmony.luni.util.Util; /** * This subclass extends <code>URLConnection</code>. * <p> - * + * * This class is responsible for connecting and retrieving resources from a Jar * file which can be anywhere that can be refered to by an URL. */ public class JarURLConnection extends java.net.JarURLConnection { - static Hashtable<String, CacheEntry<? extends JarFile>> jarCache = new Hashtable<String, CacheEntry<?>>(); + static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>(); + + private URL jarFileURL; - InputStream jarInput; + private InputStream jarInput; private JarFile jarFile; private JarEntry jarEntry; - - private boolean closed; - - ReferenceQueue<JarFile> cacheQueue = new ReferenceQueue<JarFile>(); - - static TreeSet<LRUKey> lru = new TreeSet<LRUKey>( - new LRUComparator<LRUKey>()); - - static int Limit; - - static { - Limit = AccessController.doPrivileged(new PrivilegedAction<Integer>() { - public Integer run() { - return Integer.getInteger("jar.cacheSize", 500); //$NON-NLS-1$ - } - }); - // BEGIN android-removed - // TODO this needs to be implemented once this is available. - // VM.closeJars(); - // END android-removed - } - - static final class CacheEntry<T extends JarFile> extends WeakReference<T> { - Object key; - - CacheEntry(T jar, String key, ReferenceQueue<JarFile> queue) { - super(jar, queue); - this.key = key; - } - } - - static final class LRUKey { - JarFile jar; - - long ts; - - LRUKey(JarFile file, long time) { - jar = file; - ts = time; - } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - return (obj instanceof LRUKey) && - (jar == ((LRUKey) obj).jar); - } - - @Override - public int hashCode() { - return jar.hashCode(); - } - } - - static final class LRUComparator<T> implements Comparator<LRUKey> { - LRUComparator() { - } - - /** - * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) - */ - public int compare(LRUKey o1, LRUKey o2) { - if ((o1).ts > (o2).ts) { - return 1; - } - return (o1).ts == (o2).ts ? 0 : -1; - } + private boolean closed; - /** - * @param o1 - * an object to compare - * @param o2 - * an object to compare - * @return <code>true</code> if the objects are equal, - * <code>false</code> otherwise. - */ - public boolean equals(Object o1, Object o2) { - return o1.equals(o2); - } - } /** * @param url @@ -153,8 +69,10 @@ public class JarURLConnection extends java.net.JarURLConnection { * @throws MalformedURLException * if the URL is malformed */ - public JarURLConnection(java.net.URL url) throws MalformedURLException { + public JarURLConnection(java.net.URL url) throws MalformedURLException, IOException { super(url); + jarFileURL = getJarFileURL(); + jarFileURLConnection = jarFileURL.openConnection(); } /** @@ -162,77 +80,76 @@ public class JarURLConnection extends java.net.JarURLConnection { */ @Override public void connect() throws IOException { - jarFileURLConnection = getJarFileURL().openConnection(); - findJarFile(); // ensure the file can be found - findJarEntry(); // ensure the entry, if any, can be found - connected = true; + if (!connected) { + findJarFile(); // ensure the file can be found + findJarEntry(); // ensure the entry, if any, can be found + connected = true; + } } /** * Returns the Jar file refered by this <code>URLConnection</code> - * + * * @return the JAR file referenced by this connection - * + * * @throws IOException * thrown if an IO error occurs while connecting to the * resource. */ @Override public JarFile getJarFile() throws IOException { - if (!connected) { - connect(); - } + connect(); return jarFile; } /** * Returns the Jar file refered by this <code>URLConnection</code> - * + * * @throws IOException * if an IO error occurs while connecting to the resource. */ private void findJarFile() throws IOException { - URL jarFileURL = getJarFileURL(); - if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$ - String fileName = jarFileURL.getFile(); - if(!new File(Util.decode(fileName,false)).exists()){ - // KA026=JAR entry {0} not found in {1} - throw new FileNotFoundException(Msg.getString("KA026", //$NON-NLS-1$ - getEntryName(), fileName)); + JarFile jar = null; + if (getUseCaches()) { + synchronized(jarCache){ + jarFile = jarCache.get(jarFileURL); } - String host = jarFileURL.getHost(); - if (host != null && host.length() > 0) { - fileName = "//" + host + fileName; //$NON-NLS-1$ + if (jarFile == null) { + jar = openJarFile(); + synchronized(jarCache){ + jarFile = jarCache.get(jarFileURL); + if (jarFile == null){ + jarCache.put(jarFileURL, jar); + jarFile = jar; + }else{ + jar.close(); + } + } } - jarFile = openJarFile(fileName, fileName, false); - return; + }else{ + jarFile = openJarFile(); } - final String externalForm = jarFileURLConnection.getURL() - .toExternalForm(); - jarFile = AccessController - .doPrivileged(new PrivilegedAction<JarFile>() { - public JarFile run() { - try { - return openJarFile(null, externalForm, false); - } catch (IOException e) { - return null; - } - } - }); - if (jarFile != null) { - return; + if (jarFile == null) { + throw new IOException(); } + } - // Build a temp jar file - final InputStream is = jarFileURLConnection.getInputStream(); - try { - jarFile = AccessController + 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{ + final InputStream is = jarFileURL.openConnection().getInputStream(); + try { + jar = AccessController .doPrivileged(new PrivilegedAction<JarFile>() { public JarFile run() { try { File tempJar = File.createTempFile("hyjar_", //$NON-NLS-1$ ".tmp", null); //$NON-NLS-1$ + tempJar.deleteOnExit(); FileOutputStream fos = new FileOutputStream( tempJar); byte[] buf = new byte[4096]; @@ -241,79 +158,33 @@ public class JarURLConnection extends java.net.JarURLConnection { fos.write(buf, 0, nbytes); } fos.close(); - String path = tempJar.getPath(); - return openJarFile(path, externalForm, true); + return new JarFile(tempJar, + true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE); } catch (IOException e) { return null; } } }); - } finally { - is.close(); - } - if (jarFile == null) { - throw new IOException(); - } - } - - JarFile openJarFile(String fileString, String key, boolean temp) - throws IOException { - - JarFile jar = null; - if (useCaches) { - CacheEntry<? extends JarFile> entry; - while ((entry = (CacheEntry<? extends JarFile>) cacheQueue.poll()) != null) { - jarCache.remove(entry.key); + } finally { + if (is != null) is.close(); } - entry = jarCache.get(key); - if (entry != null) { - jar = entry.get(); - } - if (jar == null && fileString != null) { - int flags = ZipFile.OPEN_READ - + (temp ? ZipFile.OPEN_DELETE : 0); - jar = new JarFile(new File(Util.decode(fileString, false)), - true, flags); - jarCache - .put(key, new CacheEntry<JarFile>(jar, key, cacheQueue)); - } else { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(getPermission()); - } - if (temp) { - lru.remove(new LRUKey(jar, 0)); - } - } - } else if (fileString != null) { - int flags = ZipFile.OPEN_READ + (temp ? ZipFile.OPEN_DELETE : 0); - jar = new JarFile(new File(Util.decode(fileString, false)), true, - flags); } - if (temp) { - lru.add(new LRUKey(jar, new Date().getTime())); - if (lru.size() > Limit) { - lru.remove(lru.first()); - } - } return jar; } /** * Returns the JarEntry of the entry referenced by this * <code>URLConnection</code>. - * + * * @return java.util.jar.JarEntry the JarEntry referenced - * + * * @throws IOException * if an IO error occurs while getting the entry */ @Override public JarEntry getJarEntry() throws IOException { - if (!connected) { - connect(); - } + connect(); return jarEntry; } @@ -334,20 +205,19 @@ public class JarURLConnection extends java.net.JarURLConnection { /** * Creates an input stream for reading from this URL Connection. - * + * * @return the input stream - * + * * @throws IOException * if an IO error occurs while connecting to the resource. */ @Override public InputStream getInputStream() throws IOException { + if (closed) { throw new IllegalStateException(Msg.getString("KA027")); } - if (!connected) { - connect(); - } + connect(); if (jarInput != null) { return jarInput; } @@ -359,39 +229,56 @@ public class JarURLConnection extends java.net.JarURLConnection { } /** - * Returns the content type of the resource. Test cases reveal that only if - * the URL is refering to a Jar file, that this method returns a non-null - * value - x-java/jar. - * + * Returns the content type of the resource. + * For jar file itself "x-java/jar" should be returned, + * for jar entries the content type of the entry should be returned. + * Returns non-null results ("content/unknown" for unknown types). + * * @return the content type */ @Override public String getContentType() { - // it could also return "x-java/jar" which jdk returns but here, we get - // it from the URLConnection - try { - if (url.getFile().endsWith("!/")) { //$NON-NLS-1$ - return getJarFileURL().openConnection().getContentType(); + if (url.getFile().endsWith("!/")) { //$NON-NLS-1$ + // the type for jar file itself is always "x-java/jar" + return "x-java/jar"; //$NON-NLS-1$ + } else { + String cType = null; + String entryName = getEntryName(); + + if (entryName != null) { + // if there is an Jar Entry, get the content type from the name + cType = guessContentTypeFromName(entryName); + } else { + try { + connect(); + cType = jarFileURLConnection.getContentType(); + } catch (IOException ioe) { + // Ignore + } } - } catch (IOException ioe) { - // Ignore + if (cType == null) { + cType = "content/unknown"; //$NON-NLS-1$ + } + return cType; } - // if there is an Jar Entry, get the content type from the name - return guessContentTypeFromName(url.getFile()); } /** * Returns the content length of the resource. Test cases reveal that if the * URL is refering to a Jar file, this method returns a content-length - * returned by URLConnection. If not, it will return -1. - * + * returned by URLConnection. For jar entry it should return it's size. + * Otherwise, it will return -1. + * * @return the content length */ @Override public int getContentLength() { try { - if (url.getFile().endsWith("!/")) { //$NON-NLS-1$ - return getJarFileURL().openConnection().getContentLength(); + connect(); + if (jarEntry == null) { + return jarFileURLConnection.getContentLength(); + } else { + return (int) getJarEntry().getSize(); } } catch (IOException e) { //Ignored @@ -404,12 +291,12 @@ public class JarURLConnection extends java.net.JarURLConnection { * URLConnection is pointing to a Jar File (no Jar Entry), this method will * return a <code>JarFile</code> If there is a Jar Entry, it will return * the object corresponding to the Jar entry content type. - * + * * @return a non-null object - * + * * @throws IOException * if an IO error occured - * + * * @see ContentHandler * @see ContentHandlerFactory * @see java.io.IOException @@ -417,9 +304,7 @@ public class JarURLConnection extends java.net.JarURLConnection { */ @Override public Object getContent() throws IOException { - if (!connected) { - connect(); - } + connect(); // if there is no Jar Entry, return a JarFile if (jarEntry == null) { return jarFile; @@ -431,37 +316,57 @@ public class JarURLConnection extends java.net.JarURLConnection { * Returns the permission, in this case the subclass, FilePermission object * which represents the permission necessary for this URLConnection to * establish the connection. - * + * * @return the permission required for this URLConnection. - * + * * @throws IOException * thrown when an IO exception occurs while creating the * permission. */ + @Override public Permission getPermission() throws IOException { - if (jarFileURLConnection != null) { - return jarFileURLConnection.getPermission(); - } - return getJarFileURL().openConnection().getPermission(); + return jarFileURLConnection.getPermission(); + } + + @Override + public boolean getUseCaches() { + return jarFileURLConnection.getUseCaches(); + } + + @Override + public void setUseCaches(boolean usecaches) { + jarFileURLConnection.setUseCaches(usecaches); + } + + @Override + public boolean getDefaultUseCaches() { + return jarFileURLConnection.getDefaultUseCaches(); + } + + @Override + public void setDefaultUseCaches(boolean defaultusecaches) { + jarFileURLConnection.setDefaultUseCaches(defaultusecaches); } /** * Closes the cached files. */ public static void closeCachedFiles() { - Enumeration<CacheEntry<? extends JarFile>> elemEnum = jarCache - .elements(); - while (elemEnum.hasMoreElements()) { - try { - ZipFile zip = elemEnum.nextElement().get(); - if (zip != null) { - zip.close(); + Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet(); + synchronized(jarCache){ + Iterator<Map.Entry<URL, JarFile>> i = s.iterator(); + while(i.hasNext()){ + try { + ZipFile zip = i.next().getValue(); + if (zip != null) { + zip.close(); + } + } catch (IOException e) { + // Ignored } - } catch (IOException e) { - // Ignored } - } + } } private class JarURLConnectionInputStream extends FilterInputStream { @@ -478,7 +383,7 @@ public class JarURLConnection extends java.net.JarURLConnection { @Override public void close() throws IOException { super.close(); - if (!useCaches) { + if (!getUseCaches()) { closed = true; jarFile.close(); } diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties b/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties index fe392b7..2ee09f7 100644 --- a/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties +++ b/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties @@ -21,8 +21,6 @@ luni.03=The enum constant {0}.{1} is missing luni.04=this Map luni.05=Attempt to insert {0} element into collection with element type {1} luni.06=The string argument is null -# // BEGIN android-added -# // copied from newer version of harmony +luni.07=The stream is corrupted luni.08=Invalid Unicode sequence: expected format \\uxxxx luni.09=Invalid Unicode sequence: illegal character -# // END android-added diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java deleted file mode 100644 index a359b8b..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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.reflect; - -class ProxyCharArrayCache { - static boolean equals(char[] first, char[] second) { - if (first == second) { - return true; - } - if (first == null || second == null) { - return false; - } - if (first.length != second.length) { - return false; - } - - for (int i = first.length; --i >= 0;) { - if (first[i] != second[i]) { - return false; - } - } - return true; - } - - // to avoid using Enumerations, walk the individual tables skipping nulls - private char[] keyTable[]; - - private int valueTable[]; - - // number of elements in the table - private int elementSize; - - private int threshold; - - ProxyCharArrayCache(int initialCapacity) { - if (initialCapacity < 13) { - initialCapacity = 13; - } - this.elementSize = 0; - this.threshold = (int) (initialCapacity * 0.66f); - this.keyTable = new char[initialCapacity][]; - this.valueTable = new int[initialCapacity]; - } - - int get(char[] key) { - int index = hashCodeChar(key); - while (keyTable[index] != null) { - if (equals(keyTable[index], key)) { - return valueTable[index]; - } - index = (index + 1) % keyTable.length; - } - return -1; - } - - private int hashCodeChar(char[] val) { - int length = val.length; - int hash = 0; - int n = 2; // number of characters skipped - for (int i = 0; i < length; i += n) { - hash += val[i]; - } - return (hash & 0x7FFFFFFF) % keyTable.length; - } - - int put(char[] key, int value) { - int index = hashCodeChar(key); - while (keyTable[index] != null) { - if (equals(keyTable[index], key)) { - return valueTable[index] = value; - } - index = (index + 1) % keyTable.length; - } - keyTable[index] = key; - valueTable[index] = value; - - // assumes the threshold is never equal to the size of the table - if (++elementSize > threshold) { - rehash(); - } - return value; - } - - private void rehash() { - ProxyCharArrayCache newHashtable = new ProxyCharArrayCache( - keyTable.length * 2); - for (int i = keyTable.length; --i >= 0;) { - if (keyTable[i] != null) { - newHashtable.put(keyTable[i], valueTable[i]); - } - } - - this.keyTable = newHashtable.keyTable; - this.valueTable = newHashtable.valueTable; - this.threshold = newHashtable.threshold; - } - - int size() { - return elementSize; - } - - @Override - public String toString() { - int max = size(); - StringBuilder buf = new StringBuilder(); - buf.append("{"); //$NON-NLS-1$ - for (int i = 0; i < max; ++i) { - if (keyTable[i] != null) { - buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$ - } - if (i < max) { - buf.append(", "); //$NON-NLS-1$ - } - } - buf.append("}"); //$NON-NLS-1$ - return buf.toString(); - } -} diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java deleted file mode 100644 index 43fa5a3..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java +++ /dev/null @@ -1,937 +0,0 @@ -/* - * 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.reflect; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.lang.reflect.UndeclaredThrowableException; -import java.util.ArrayList; -import java.util.HashSet; - -public final class ProxyClassFile implements ProxyConstants { - - private static final int INITIAL_CONTENTS_SIZE = 1000; - - private static final int INITIAL_HEADER_SIZE = 500; - - private static final int INCREMENT_SIZE = 250; - - private static Method ObjectEqualsMethod; - - private static Method ObjectHashCodeMethod; - - private static Method ObjectToStringMethod; - - private static Method ClassForNameMethod; - - private static Method ClassGetMethod; - - private static Method HandlerInvokeMethod; - - private static Constructor<?> ProxyConstructor; - - private static Constructor<?> UndeclaredThrowableExceptionConstructor; - - private static Field ProxyHandlerField; - - public static byte[] generateBytes(String typeName, Class[] interfaces) { - ProxyClassFile classFile = new ProxyClassFile(typeName, interfaces); - classFile.addFields(); - classFile.findMethods(interfaces); - classFile.addMethods(); - classFile.addAttributes(); - return classFile.getBytes(); - } - - static char[] getConstantPoolName(Class<?> c) { - if (c.isArray()) { - // Array classes are named/ with their signature - return c.getName().replace('.', '/').toCharArray(); - } - - if (c.isPrimitive()) { - // Special cases for each base type. - if (c == void.class) { - return new char[] { 'V' }; - } - if (c == int.class) { - return new char[] { 'I' }; - } - if (c == boolean.class) { - return new char[] { 'Z' }; - } - if (c == byte.class) { - return new char[] { 'B' }; - } - if (c == char.class) { - return new char[] { 'C' }; - } - if (c == short.class) { - return new char[] { 'S' }; - } - if (c == long.class) { - return new char[] { 'J' }; - } - if (c == float.class) { - return new char[] { 'F' }; - } - if (c == double.class) { - return new char[] { 'D' }; - } - } - return ("L" + c.getName().replace('.', '/') + ";").toCharArray(); - } - - static char[] getConstantPoolName(Constructor<?> method) /* (ILjava/lang/Thread;)V */{ - Class[] parameters = method.getParameterTypes(); - StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20); - buffer.append('('); - for (Class<?> element : parameters) { - buffer.append(getConstantPoolName(element)); - } - buffer.append(')'); - buffer.append(getConstantPoolName(void.class)); - return buffer.toString().toCharArray(); - } - - static char[] getConstantPoolName(Method method) /* (ILjava/lang/Thread;)Ljava/lang/Object; */{ - Class[] parameters = method.getParameterTypes(); - StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20); - buffer.append('('); - for (Class<?> element : parameters) { - buffer.append(getConstantPoolName(element)); - } - buffer.append(')'); - buffer.append(getConstantPoolName(method.getReturnType())); - return buffer.toString().toCharArray(); - } - - private ProxyConstantPool constantPool; - - // the header contains all the bytes till the end of the constant pool - byte[] header; - - int headerOffset; - - // that collection contains all the remaining bytes of the .class file - private byte[] contents; - - private int contentsOffset; - - private int constantPoolOffset; - - private ProxyMethod[] proxyMethods; - - ProxyClassFile(String typeName, Class[] interfaces) { - super(); - header = new byte[INITIAL_HEADER_SIZE]; - // generate the magic numbers inside the header - header[headerOffset++] = (byte) (0xCAFEBABEL >> 24); - header[headerOffset++] = (byte) (0xCAFEBABEL >> 16); - header[headerOffset++] = (byte) (0xCAFEBABEL >> 8); - header[headerOffset++] = (byte) (0xCAFEBABEL >> 0); - // Compatible with JDK 1.2 - header[headerOffset++] = 0; - header[headerOffset++] = 0; - header[headerOffset++] = 0; - header[headerOffset++] = 46; - constantPoolOffset = headerOffset; - headerOffset += 2; - constantPool = new ProxyConstantPool(this); - contents = new byte[INITIAL_CONTENTS_SIZE]; - // now we continue to generate the bytes inside the contents array - int accessFlags = AccPublic | AccFinal | AccSuper; - contents[contentsOffset++] = (byte) (accessFlags >> 8); - contents[contentsOffset++] = (byte) accessFlags; - int classNameIndex = constantPool.typeIndex(typeName); - contents[contentsOffset++] = (byte) (classNameIndex >> 8); - contents[contentsOffset++] = (byte) classNameIndex; - int superclassNameIndex = constantPool - .typeIndex("java/lang/reflect/Proxy"); - contents[contentsOffset++] = (byte) (superclassNameIndex >> 8); - contents[contentsOffset++] = (byte) superclassNameIndex; - int interfacesCount = interfaces.length; - contents[contentsOffset++] = (byte) (interfacesCount >> 8); - contents[contentsOffset++] = (byte) interfacesCount; - for (int i = 0; i < interfacesCount; i++) { - int interfaceIndex = constantPool - .typeIndex(interfaces[i].getName()); - contents[contentsOffset++] = (byte) (interfaceIndex >> 8); - contents[contentsOffset++] = (byte) interfaceIndex; - } - } - - private void addAttributes() { - writeUnsignedShort(0); // classFile does not have attributes of its own - - // resynchronize all offsets of the classfile - header = constantPool.poolContent; - headerOffset = constantPool.currentOffset; - int constantPoolCount = constantPool.currentIndex; - header[constantPoolOffset++] = (byte) (constantPoolCount >> 8); - header[constantPoolOffset] = (byte) constantPoolCount; - } - - private void addFields() { - writeUnsignedShort(0); // we have no fields - } - - private void addMethods() { - int methodCount = proxyMethods.length; - writeUnsignedShort(methodCount + 1); - - // save constructor - writeUnsignedShort(AccPublic); - writeUnsignedShort(constantPool.literalIndex(Init)); - if (ProxyConstructor == null) { - try { - ProxyConstructor = Proxy.class - .getDeclaredConstructor(new Class[] { InvocationHandler.class }); - } catch (NoSuchMethodException e) { - throw new InternalError(); - } - } - writeUnsignedShort(constantPool - .literalIndex(getConstantPoolName(ProxyConstructor))); - writeUnsignedShort(1); // store just the code attribute - writeUnsignedShort(constantPool.literalIndex(CodeName)); - // save attribute_length(4), max_stack(2), max_locals(2), code_length(4) - int codeLength = 6; - writeUnsignedWord(12 + codeLength); // max_stack(2), max_locals(2), - // code_length(4), 2 zero shorts - writeUnsignedShort(2); - writeUnsignedShort(2); - writeUnsignedWord(codeLength); - writeUnsignedByte(OPC_aload_0); - writeUnsignedByte(OPC_aload_1); - writeUnsignedByte(OPC_invokespecial); - writeUnsignedShort(constantPool.literalIndex(ProxyConstructor)); - writeUnsignedByte(OPC_return); - writeUnsignedShort(0); // no exceptions table - writeUnsignedShort(0); // there are no attributes for the code - // attribute - - for (int i = 0; i < methodCount; i++) { - ProxyMethod pMethod = proxyMethods[i]; - Method method = pMethod.method; - writeUnsignedShort(AccPublic | AccFinal); - writeUnsignedShort(constantPool.literalIndex(method.getName() - .toCharArray())); - writeUnsignedShort(constantPool - .literalIndex(getConstantPoolName(method))); - Class[] thrownsExceptions = pMethod.commonExceptions; - int eLength = thrownsExceptions.length; - if (eLength > 0) { - writeUnsignedShort(2); // store the exception & code attributes - // The method has a throw clause. So we need to add an exception - // attribute - writeUnsignedShort(constantPool.literalIndex(ExceptionsName)); - // The attribute length = length * 2 + 2 in case of a exception - // attribute - writeUnsignedWord(eLength * 2 + 2); - writeUnsignedShort(eLength); - for (int e = 0; e < eLength; e++) { - writeUnsignedShort(constantPool - .typeIndex(thrownsExceptions[e].getName())); - } - } else { - writeUnsignedShort(1); // store just the code attribute - } - generateCodeAttribute(pMethod); - } - } - - private void findMethods(Class[] interfaces) { - /* - * find all methods defined by the interfaces (including inherited - * interfaces) plus hashCode, equals & toString from Object build an - * array with the methods... no duplicates - check up to the array size - * when the interface's first method was added - */ - if (ObjectEqualsMethod == null) { - try { - ObjectEqualsMethod = Object.class.getMethod("equals", - new Class[] { Object.class }); - ObjectHashCodeMethod = Object.class.getMethod("hashCode", - new Class[0]); - ObjectToStringMethod = Object.class.getMethod("toString", - new Class[0]); - } catch (NoSuchMethodException ex) { - throw new InternalError(); - } - } - - ArrayList<ProxyMethod> allMethods = new ArrayList<ProxyMethod>(25); - allMethods.add(new ProxyMethod(ObjectEqualsMethod)); - allMethods.add(new ProxyMethod(ObjectHashCodeMethod)); - allMethods.add(new ProxyMethod(ObjectToStringMethod)); - - HashSet<Class<?>> interfacesSeen = new HashSet<Class<?>>(); - for (Class<?> element : interfaces) { - findMethods(element, allMethods, interfacesSeen); - } - - proxyMethods = new ProxyMethod[allMethods.size()]; - allMethods.toArray(proxyMethods); - } - - private void findMethods(Class<?> nextInterface, - ArrayList<ProxyMethod> allMethods, HashSet<Class<?>> interfacesSeen) { - /* - * add the nextInterface's methods to allMethods if an equivalent method - * already exists then return types must be identical... don't replace - * it - */ - if (interfacesSeen.contains(nextInterface)) { - return; // already walked it - } - interfacesSeen.add(nextInterface); - - int existingMethodCount = allMethods.size(); - Method[] methods = nextInterface.getMethods(); - nextMethod: for (Method method : methods) { - for (int j = 0; j < existingMethodCount; j++) { - if (allMethods.get(j).matchMethod(method)) { - continue nextMethod; - } - } - allMethods.add(new ProxyMethod(method)); - } - - Class<?>[] superInterfaces = nextInterface.getInterfaces(); - for (Class<?> element : superInterfaces) { - // recursion should be minimal - findMethods(element, allMethods, interfacesSeen); - } - } - - private void generateCodeAttribute(ProxyMethod pMethod) { - int codeAttributeOffset = contentsOffset; - int contentsLength = contents.length; - if (contentsOffset + 20 + 100 >= contentsLength) { - System.arraycopy(contents, 0, (contents = new byte[contentsLength - + INCREMENT_SIZE]), 0, contentsLength); - } - writeUnsignedShort(constantPool.literalIndex(CodeName)); - // leave space for attribute_length(4), max_stack(2), max_locals(2), - // code_length(4) - contentsOffset += 12; - - /* - * to push the args for the call to invoke push the receiver field h 0 - * aload0 1 getfield 33 java.lang.reflect.Proxy.h - * Ljava.lang.reflect.InvocationHandler; push the receiver as the first - * arg 4 aload0 push the method push the array of args call invoke 89 - * invokeinterface 67 - * java.lang.reflect.InvocationHandler.invoke(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object; - * cast return result catch & convert exceptions if necessary - */ - - int codeStartOffset = contentsOffset; - writeUnsignedByte(OPC_aload_0); - writeUnsignedByte(OPC_getfield); - if (ProxyHandlerField == null) { - try { - ProxyHandlerField = Proxy.class.getDeclaredField("h"); - } catch (NoSuchFieldException e) { - throw new InternalError(); - } - } - writeUnsignedShort(constantPool.literalIndex(ProxyHandlerField)); - writeUnsignedByte(OPC_aload_0); - Method method = pMethod.method; - Class[] argTypes = method.getParameterTypes(); - genCallGetMethod(method.getDeclaringClass(), method.getName(), argTypes); - int maxLocals = genInvokeArgs(argTypes); - writeUnsignedByte(OPC_invokeinterface); - if (HandlerInvokeMethod == null) { - try { - HandlerInvokeMethod = InvocationHandler.class.getMethod( - "invoke", new Class[] { Object.class, Method.class, - Object[].class }); - } catch (NoSuchMethodException e) { - throw new InternalError(); - } - } - writeUnsignedShort(constantPool.literalIndex(HandlerInvokeMethod)); - writeUnsignedByte(4); // invoke has 3 args - writeUnsignedByte(0); // 4th operand must be 0 - genCastReturnType(method.getReturnType()); - int codeLength = contentsOffset - codeStartOffset; - - Class[] checkedExceptions = pMethod.getCheckedExceptions(); - int checkedLength = checkedExceptions.length; - if (checkedLength > 0) { - int codeEndIndex = contentsOffset - codeStartOffset; - writeUnsignedByte(OPC_athrow); // re-throw the caught exception - - genStoreArg(maxLocals); - writeUnsignedByte(OPC_new); - writeUnsignedShort(constantPool - .typeIndex("java/lang/reflect/UndeclaredThrowableException")); - writeUnsignedByte(OPC_dup); - genLoadArg(maxLocals); - maxLocals++; // now expecting the exception - writeUnsignedByte(OPC_invokespecial); - if (UndeclaredThrowableExceptionConstructor == null) { - try { - UndeclaredThrowableExceptionConstructor = UndeclaredThrowableException.class - .getConstructor(new Class[] { Throwable.class }); - } catch (NoSuchMethodException e) { - throw new InternalError(); - } - } - writeUnsignedShort(constantPool - .literalIndex(UndeclaredThrowableExceptionConstructor)); - writeUnsignedByte(OPC_athrow); - - codeLength = contentsOffset - codeStartOffset; - - // write the exception table - writeUnsignedShort(checkedLength + 1); - for (int i = 0; i < checkedLength; i++) { - writeUnsignedShort(0); - writeUnsignedShort(codeEndIndex); - writeUnsignedShort(codeEndIndex); - writeUnsignedShort(constantPool.typeIndex(checkedExceptions[i] - .getName())); - } - writeUnsignedShort(0); - writeUnsignedShort(codeEndIndex); - writeUnsignedShort(codeEndIndex + 1); // starts after the first - // throw - writeUnsignedShort(constantPool.typeIndex("java/lang/Throwable")); - } else { - writeUnsignedShort(0); // no exceptions table - } - // there are no attributes for the code attribute - writeUnsignedShort(0); - - /* - * Complete the creation of the code attribute by setting the - * attribute_length, max_stack max_locals, code_length & exception table - * codeAttributeOffset is the position inside contents byte array before - * we started to write That means that to write the attribute_length you - * need to offset by 2 the value of codeAttributeOffset to get the right - * position, 6 for the max_stack etc... - */ - int codeAttributeLength = contentsOffset - (codeAttributeOffset + 6); - contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24); - contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16); - contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8); - contents[codeAttributeOffset + 5] = (byte) codeAttributeLength; - - int maxStack = maxLocals + 10; // larger than the exact amount - contents[codeAttributeOffset + 6] = (byte) (maxStack >> 8); - contents[codeAttributeOffset + 7] = (byte) maxStack; - contents[codeAttributeOffset + 8] = (byte) (maxLocals >> 8); - contents[codeAttributeOffset + 9] = (byte) maxLocals; - contents[codeAttributeOffset + 10] = (byte) (codeLength >> 24); - contents[codeAttributeOffset + 11] = (byte) (codeLength >> 16); - contents[codeAttributeOffset + 12] = (byte) (codeLength >> 8); - contents[codeAttributeOffset + 13] = (byte) codeLength; - } - - /** - * Perform call to Class.getMethod(String, Class[]) receiver 13 ldc 37 - * (java.lang.String) "java.lang.Object" 15 invokestatic 43 - * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; selector 37 - * ldc 55 (java.lang.String) "equals" plus method args 39 iconst0 40 - * anewarray 39 java.lang.Class or 39 iconst1 40 anewarray 39 - * java.lang.Class 43 dup 44 iconst0 53 ldc 37 (java.lang.String) - * "java.lang.Object" 55 invokestatic 43 - * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; 77 aastore - * or 39 iconst2 40 anewarray 39 java.lang.Class 43 dup 44 iconst0 45 - * getstatic 102 java.lang.Integer.TYPE Ljava.lang.Class; 48 aastore 49 dup - * 50 iconst1 51 getstatic 104 java.lang.Boolean.TYPE Ljava.lang.Class; 54 - * aastore then 78 invokevirtual 59 - * java.lang.Class.getMethod(Ljava.lang.String;[Ljava.lang.Class;)Ljava.lang.reflect.Method; - */ - private void genCallGetMethod(Class<?> receiverType, String selector, - Class[] argTypes) { - genCallClassForName(receiverType.getName()); - writeLdc(selector); - int length = argTypes.length; - writeIntConstant(length); - writeUnsignedByte(OPC_anewarray); - writeUnsignedShort(constantPool.typeIndex("java/lang/Class")); - for (int i = 0; i < length; i++) { - writeUnsignedByte(OPC_dup); - writeIntConstant(i); - Class<?> type = argTypes[i]; - if (type.isPrimitive()) { - writeUnsignedByte(OPC_getstatic); - writeUnsignedShort(constantPool.literalIndex(typeField(type))); - } else { - genCallClassForName(type.getName()); - } - writeUnsignedByte(OPC_aastore); - } - writeUnsignedByte(OPC_invokevirtual); - if (ClassGetMethod == null) { - try { - ClassGetMethod = Class.class.getMethod("getMethod", - new Class[] { String.class, Class[].class }); - } catch (NoSuchMethodException e) { - throw new InternalError(); - } - } - writeUnsignedShort(constantPool.literalIndex(ClassGetMethod)); - } - - /** - * Add argument array for call to InvocationHandler.invoke - * - * 46 aconstnull or 81 iconst1 82 anewarray 61 java.lang.Object 85 dup 86 - * iconst0 87 aload1 88 aastore or 58 iconst2 59 anewarray 61 - * java.lang.Object 62 dup 63 iconst0 64 new 84 java.lang.Integer 67 dup 68 - * iload1 69 invokespecial 107 java.lang.Integer.<init>(I)V 72 aastore 73 - * dup 74 iconst1 75 new 69 java.lang.Boolean 78 dup 79 iload2 80 - * invokespecial 110 java.lang.Boolean.<init>(Z)V 83 aastore - */ - private int genInvokeArgs(Class[] argTypes) { - int argByteOffset = 1; // remember h is at position 0 - int length = argTypes.length; - if (length == 0) { - writeUnsignedByte(OPC_aconst_null); - } else { - writeIntConstant(length); - writeUnsignedByte(OPC_anewarray); - writeUnsignedShort(constantPool.typeIndex("java/lang/Object")); - for (int i = 0; i < length; i++) { - writeUnsignedByte(OPC_dup); - writeIntConstant(i); - argByteOffset = genInvokeArg(argTypes[i], argByteOffset); - writeUnsignedByte(OPC_aastore); - } - } - return argByteOffset; - } - - private int genInvokeArg(Class<?> type, int argByteOffset) { - // offset represents maxLocals in bytes - if (type.isPrimitive()) { - writeUnsignedByte(OPC_new); - writeUnsignedShort(constantPool.typeIndex(typeWrapperName(type))); - writeUnsignedByte(OPC_dup); - if (argByteOffset > 255) { - writeUnsignedByte(OPC_wide); - } - if (type == long.class) { - switch (argByteOffset) { - case 0: - writeUnsignedByte(OPC_lload_0); - break; - case 1: - writeUnsignedByte(OPC_lload_1); - break; - case 2: - writeUnsignedByte(OPC_lload_2); - break; - case 3: - writeUnsignedByte(OPC_lload_3); - break; - default: - writeUnsignedByte(OPC_lload); - if (argByteOffset > 255) { - writeUnsignedShort(argByteOffset); - } else { - writeUnsignedByte(argByteOffset); - } - } - argByteOffset += 2; - } else if (type == float.class) { - switch (argByteOffset) { - case 0: - writeUnsignedByte(OPC_fload_0); - break; - case 1: - writeUnsignedByte(OPC_fload_1); - break; - case 2: - writeUnsignedByte(OPC_fload_2); - break; - case 3: - writeUnsignedByte(OPC_fload_3); - break; - default: - writeUnsignedByte(OPC_fload); - if (argByteOffset > 255) { - writeUnsignedShort(argByteOffset); - } else { - writeUnsignedByte(argByteOffset); - } - } - argByteOffset++; - } else if (type == double.class) { - switch (argByteOffset) { - case 0: - writeUnsignedByte(OPC_dload_0); - break; - case 1: - writeUnsignedByte(OPC_dload_1); - break; - case 2: - writeUnsignedByte(OPC_dload_2); - break; - case 3: - writeUnsignedByte(OPC_dload_3); - break; - default: - writeUnsignedByte(OPC_dload); - if (argByteOffset > 255) { - writeUnsignedShort(argByteOffset); - } else { - writeUnsignedByte(argByteOffset); - } - } - argByteOffset += 2; - } else { // handles int, short, byte, boolean & char - switch (argByteOffset) { - case 0: - writeUnsignedByte(OPC_iload_0); - break; - case 1: - writeUnsignedByte(OPC_iload_1); - break; - case 2: - writeUnsignedByte(OPC_iload_2); - break; - case 3: - writeUnsignedByte(OPC_iload_3); - break; - default: - writeUnsignedByte(OPC_iload); - if (argByteOffset > 255) { - writeUnsignedShort(argByteOffset); - } else { - writeUnsignedByte(argByteOffset); - } - } - argByteOffset++; - } - writeUnsignedByte(OPC_invokespecial); - writeUnsignedShort(constantPool.literalIndex(typeInitMethod(type))); - } else { - genLoadArg(argByteOffset); - argByteOffset++; - } - return argByteOffset; - } - - /** - * 94 checkcast 69 java.lang.Boolean 97 invokevirtual 73 - * java.lang.Boolean.booleanValue()Z 100 ireturn or 52 checkcast 91 - * java.lang.String 55 areturn - */ - private void genCastReturnType(Class<?> type) { - if (type.isPrimitive()) { - if (type == void.class) { - writeUnsignedByte(OPC_pop); - writeUnsignedByte(OPC_return); - } else { - writeUnsignedByte(OPC_checkcast); - writeUnsignedShort(constantPool - .typeIndex(typeWrapperName(type))); - writeUnsignedByte(OPC_invokevirtual); - writeUnsignedShort(constantPool - .literalIndex(typeAccessMethod(type))); - if (type == long.class) { - writeUnsignedByte(OPC_lreturn); - } else if (type == float.class) { - writeUnsignedByte(OPC_freturn); - } else if (type == double.class) { - writeUnsignedByte(OPC_dreturn); - } else { // handles int, short, byte, boolean & char - writeUnsignedByte(OPC_ireturn); - } - } - } else { - writeUnsignedByte(OPC_checkcast); - writeUnsignedShort(constantPool.typeIndex(type.getName())); - writeUnsignedByte(OPC_areturn); - } - } - - private void genCallClassForName(String typeName) { - writeLdc(typeName); - writeUnsignedByte(OPC_invokestatic); - if (ClassForNameMethod == null) { - try { - ClassForNameMethod = Class.class.getMethod("forName", - new Class[] { String.class }); - } catch (NoSuchMethodException e) { - throw new InternalError(); - } - } - writeUnsignedShort(constantPool.literalIndex(ClassForNameMethod)); - } - - private void genLoadArg(int argByteOffset) { - if (argByteOffset > 255) { - writeUnsignedByte(OPC_wide); - writeUnsignedByte(OPC_aload); - writeUnsignedShort(argByteOffset); - } else { - switch (argByteOffset) { - case 0: - writeUnsignedByte(OPC_aload_0); - break; - case 1: - writeUnsignedByte(OPC_aload_1); - break; - case 2: - writeUnsignedByte(OPC_aload_2); - break; - case 3: - writeUnsignedByte(OPC_aload_3); - break; - default: - writeUnsignedByte(OPC_aload); - writeUnsignedByte(argByteOffset); - } - } - } - - private void genStoreArg(int argByteOffset) { - if (argByteOffset > 255) { - writeUnsignedByte(OPC_wide); - writeUnsignedByte(OPC_astore); - writeUnsignedShort(argByteOffset); - } else { - switch (argByteOffset) { - case 0: - writeUnsignedByte(OPC_astore_0); - break; - case 1: - writeUnsignedByte(OPC_astore_1); - break; - case 2: - writeUnsignedByte(OPC_astore_2); - break; - case 3: - writeUnsignedByte(OPC_astore_3); - break; - default: - writeUnsignedByte(OPC_astore); - writeUnsignedByte(argByteOffset); - } - } - } - - private byte[] getBytes() { - byte[] fullContents = new byte[headerOffset + contentsOffset]; - System.arraycopy(header, 0, fullContents, 0, headerOffset); - System.arraycopy(contents, 0, fullContents, headerOffset, - contentsOffset); - return fullContents; - } - - private Method typeAccessMethod(Class<?> baseType) { - try { - if (baseType == int.class) { - return Integer.class.getMethod("intValue", (Class[]) null); - } - if (baseType == short.class) { - return Short.class.getMethod("shortValue", (Class[]) null); - } - if (baseType == byte.class) { - return Byte.class.getMethod("byteValue", (Class[]) null); - } - if (baseType == boolean.class) { - return Boolean.class.getMethod("booleanValue", (Class[]) null); - } - if (baseType == char.class) { - return Character.class.getMethod("charValue", (Class[]) null); - } - if (baseType == long.class) { - return Long.class.getMethod("longValue", (Class[]) null); - } - if (baseType == float.class) { - return Float.class.getMethod("floatValue", (Class[]) null); - } - if (baseType == double.class) { - return Double.class.getMethod("doubleValue", (Class[]) null); - } - } catch (NoSuchMethodException e) { - throw new InternalError(); - } - return null; - } - - private Field typeField(Class<?> baseType) { - try { - if (baseType == int.class) { - return Integer.class.getField("TYPE"); - } - if (baseType == short.class) { - return Short.class.getField("TYPE"); - } - if (baseType == byte.class) { - return Byte.class.getField("TYPE"); - } - if (baseType == boolean.class) { - return Boolean.class.getField("TYPE"); - } - if (baseType == char.class) { - return Character.class.getField("TYPE"); - } - if (baseType == long.class) { - return Long.class.getField("TYPE"); - } - if (baseType == float.class) { - return Float.class.getField("TYPE"); - } - if (baseType == double.class) { - return Double.class.getField("TYPE"); - } - } catch (NoSuchFieldException e) { - throw new InternalError(); - } - return null; - } - - private Constructor<?> typeInitMethod(Class<?> baseType) { - try { - if (baseType == int.class) { - return Integer.class.getConstructor(new Class[] { int.class }); - } - if (baseType == short.class) { - return Short.class.getConstructor(new Class[] { short.class }); - } - if (baseType == byte.class) { - return Byte.class.getConstructor(new Class[] { byte.class }); - } - if (baseType == boolean.class) { - return Boolean.class - .getConstructor(new Class[] { boolean.class }); - } - if (baseType == char.class) { - return Character.class - .getConstructor(new Class[] { char.class }); - } - if (baseType == long.class) { - return Long.class.getConstructor(new Class[] { long.class }); - } - if (baseType == float.class) { - return Float.class.getConstructor(new Class[] { float.class }); - } - if (baseType == double.class) { - return Double.class - .getConstructor(new Class[] { double.class }); - } - } catch (NoSuchMethodException e) { - throw new InternalError(); - } - return null; - } - - private String typeWrapperName(Class<?> baseType) { - if (baseType == int.class) { - return "java/lang/Integer"; - } - if (baseType == short.class) { - return "java/lang/Short"; - } - if (baseType == byte.class) { - return "java/lang/Byte"; - } - if (baseType == boolean.class) { - return "java/lang/Boolean"; - } - if (baseType == char.class) { - return "java/lang/Character"; - } - if (baseType == long.class) { - return "java/lang/Long"; - } - if (baseType == float.class) { - return "java/lang/Float"; - } - if (baseType == double.class) { - return "java/lang/Double"; - } - return null; - } - - private void writeIntConstant(int b) { - switch (b) { - case 0: - writeUnsignedByte(OPC_iconst_0); - break; - case 1: - writeUnsignedByte(OPC_iconst_1); - break; - case 2: - writeUnsignedByte(OPC_iconst_2); - break; - case 3: - writeUnsignedByte(OPC_iconst_3); - break; - case 4: - writeUnsignedByte(OPC_iconst_4); - break; - case 5: - writeUnsignedByte(OPC_iconst_5); - break; - default: - writeUnsignedByte(OPC_bipush); - writeUnsignedByte(b); - } - } - - private void writeLdc(String constant) { - int index = constantPool.literalIndexForLdc(constant.toCharArray()); - if (index <= 0) { - throw new InternalError(); - } - if (index > 255) { - writeUnsignedByte(OPC_ldc_w); - writeUnsignedShort(index); - } else { - writeUnsignedByte(OPC_ldc); - writeUnsignedByte(index); - } - } - - private void writeUnsignedByte(int b) { - try { - contents[contentsOffset++] = (byte) b; - } catch (IndexOutOfBoundsException e) { - int actualLength = contents.length; - System.arraycopy(contents, 0, (contents = new byte[actualLength - + INCREMENT_SIZE]), 0, actualLength); - contents[contentsOffset - 1] = (byte) b; - } - } - - private void writeUnsignedShort(int b) { - writeUnsignedByte(b >>> 8); - writeUnsignedByte(b); - } - - private void writeUnsignedWord(int b) { - writeUnsignedByte(b >>> 24); - writeUnsignedByte(b >>> 16); - writeUnsignedByte(b >>> 8); - writeUnsignedByte(b); - } -} diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java deleted file mode 100644 index 3789730..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * 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.reflect; - - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -class ProxyConstantPool implements ProxyConstants { - public static final int UTF8_INITIAL_SIZE = 50; - - public static final int STRING_INITIAL_SIZE = 21; - - public static final int FIELD_INITIAL_SIZE = 7; - - public static final int METHOD_INITIAL_SIZE = 21; - - public static final int INTERFACE_INITIAL_SIZE = 21; - - public static final int CLASS_INITIAL_SIZE = 21; - - public static final int NAMEANDTYPE_INITIAL_SIZE = 21; - - public static final int CONSTANTPOOL_INITIAL_SIZE = 500; - - public static final int CONSTANTPOOL_GROW_SIZE = 1000; - - ProxyCharArrayCache UTF8Cache; - - ProxyCharArrayCache stringCache; - - ProxyCharArrayCache classNameCache; - - ProxyObjectCache fieldCache; - - ProxyObjectCache methodCache; - - ProxyObjectCache interfaceMethodCache; - - ProxyNameAndTypeCache nameAndTypeCache; - - byte[] poolContent; - - int currentIndex; - - int currentOffset; - - ProxyConstantPool(ProxyClassFile classFile) { - UTF8Cache = new ProxyCharArrayCache(UTF8_INITIAL_SIZE); - stringCache = new ProxyCharArrayCache(STRING_INITIAL_SIZE); - classNameCache = new ProxyCharArrayCache(CLASS_INITIAL_SIZE); - fieldCache = new ProxyObjectCache(FIELD_INITIAL_SIZE); - methodCache = new ProxyObjectCache(METHOD_INITIAL_SIZE); - interfaceMethodCache = new ProxyObjectCache(INTERFACE_INITIAL_SIZE); - nameAndTypeCache = new ProxyNameAndTypeCache(NAMEANDTYPE_INITIAL_SIZE); - poolContent = classFile.header; - currentOffset = classFile.headerOffset; - currentIndex = 1; - } - - int literalIndex(char[] utf8Constant) { - int index; - if ((index = UTF8Cache.get(utf8Constant)) < 0) { - writeU1(Utf8Tag); - int savedCurrentOffset = currentOffset; - if (currentOffset + 2 >= poolContent.length) { - int length = poolContent.length; - System.arraycopy(poolContent, 0, (poolContent = new byte[length - + CONSTANTPOOL_GROW_SIZE]), 0, length); - } - currentOffset += 2; - int length = 0; - for (int i = 0; i < utf8Constant.length; i++) { - char current = utf8Constant[i]; - if ((current >= 0x0001) && (current <= 0x007F)) { - // we only need one byte: ASCII table - writeU1(current); - length++; - } else if (current > 0x07FF) { - // we need 3 bytes - length += 3; - writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 - // 0000 - writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 - // 0000 - writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000 - } else { - // we can be 0 or between 0x0080 and 0x07FF - // In that case we only need 2 bytes - length += 2; - writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 - // 0000 - writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000 - } - } - if (length >= 65535) { - currentOffset = savedCurrentOffset - 1; - return -1; - } - index = UTF8Cache.put(utf8Constant, currentIndex++); - // Now we know the length that we have to write in the constant pool - // we use savedCurrentOffset to do that - poolContent[savedCurrentOffset] = (byte) (length >> 8); - poolContent[savedCurrentOffset + 1] = (byte) length; - } - return index; - } - - int literalIndex(Field aField) { - int index; - if ((index = fieldCache.get(aField)) < 0) { - int classIndex = typeIndex(aField.getDeclaringClass().getName()); - int nameAndTypeIndex = literalIndexForNameAndType( - literalIndex(aField.getName().toCharArray()), - literalIndex(ProxyClassFile.getConstantPoolName(aField - .getType()))); - index = fieldCache.put(aField, currentIndex++); - writeU1(FieldRefTag); - writeU2(classIndex); - writeU2(nameAndTypeIndex); - } - return index; - } - - int literalIndex(Constructor<?> aMethod) { - int index; - if ((index = methodCache.get(aMethod)) < 0) { - int classIndex = typeIndex(aMethod.getDeclaringClass().getName()); - int nameAndTypeIndex = literalIndexForNameAndType( - literalIndex(Init), literalIndex(ProxyClassFile - .getConstantPoolName(aMethod))); - index = methodCache.put(aMethod, currentIndex++); - writeU1(MethodRefTag); - writeU2(classIndex); - writeU2(nameAndTypeIndex); - } - return index; - } - - int literalIndex(Method aMethod) { - int index; - if (aMethod.getDeclaringClass().isInterface()) { - if ((index = interfaceMethodCache.get(aMethod)) < 0) { - int classIndex = typeIndex(aMethod.getDeclaringClass() - .getName()); - int nameAndTypeIndex = literalIndexForNameAndType( - literalIndex(aMethod.getName().toCharArray()), - literalIndex(ProxyClassFile - .getConstantPoolName(aMethod))); - index = interfaceMethodCache.put(aMethod, currentIndex++); - writeU1(InterfaceMethodRefTag); - writeU2(classIndex); - writeU2(nameAndTypeIndex); - } - } else if ((index = methodCache.get(aMethod)) < 0) { - int classIndex = typeIndex(aMethod.getDeclaringClass().getName()); - int nameAndTypeIndex = literalIndexForNameAndType( - literalIndex(aMethod.getName().toCharArray()), - literalIndex(ProxyClassFile.getConstantPoolName(aMethod))); - index = methodCache.put(aMethod, currentIndex++); - writeU1(MethodRefTag); - writeU2(classIndex); - writeU2(nameAndTypeIndex); - } - return index; - } - - int literalIndex(String stringConstant) { - int index; - char[] stringCharArray = stringConstant.toCharArray(); - if ((index = stringCache.get(stringCharArray)) < 0) { - int stringIndex = literalIndex(stringCharArray); - index = stringCache.put(stringCharArray, currentIndex++); - writeU1(StringTag); - writeU2(stringIndex); - } - return index; - } - - int literalIndexForLdc(char[] stringCharArray) { - int index; - if ((index = stringCache.get(stringCharArray)) < 0) { - int stringIndex; - if ((stringIndex = UTF8Cache.get(stringCharArray)) < 0) { - writeU1(Utf8Tag); - int savedCurrentOffset = currentOffset; - if (currentOffset + 2 >= poolContent.length) { - int length = poolContent.length; - System.arraycopy(poolContent, 0, - (poolContent = new byte[length - + CONSTANTPOOL_GROW_SIZE]), 0, length); - } - currentOffset += 2; - int length = 0; - for (int i = 0; i < stringCharArray.length; i++) { - char current = stringCharArray[i]; - if ((current >= 0x0001) && (current <= 0x007F)) { - // we only need one byte: ASCII table - writeU1(current); - length++; - } else if (current > 0x07FF) { - // we need 3 bytes - length += 3; - writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = - // 1110 0000 - writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = - // 1000 0000 - writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000 - } else { - // we can be 0 or between 0x0080 and 0x07FF - // In that case we only need 2 bytes - length += 2; - writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = - // 1100 0000 - writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000 - } - } - if (length >= 65535) { - currentOffset = savedCurrentOffset - 1; - return -1; - } - stringIndex = UTF8Cache.put(stringCharArray, currentIndex++); - // Now we know the length that we have to write in the constant - // pool - // we use savedCurrentOffset to do that - if (length > 65535) - return 0; - poolContent[savedCurrentOffset] = (byte) (length >> 8); - poolContent[savedCurrentOffset + 1] = (byte) length; - } - index = stringCache.put(stringCharArray, currentIndex++); - writeU1(StringTag); - writeU2(stringIndex); - } - return index; - } - - private int literalIndexForNameAndType(int nameIndex, int typeIndex) { - int index; - int[] key = new int[] { nameIndex, typeIndex }; - if ((index = nameAndTypeCache.get(key)) == -1) { - index = nameAndTypeCache.put(key, currentIndex++); - writeU1(NameAndTypeTag); - writeU2(nameIndex); - writeU2(typeIndex); - } - return index; - } - - int typeIndex(String typeName) { - int index; - if (typeName.indexOf('.') != -1) - typeName = typeName.replace('.', '/'); - char[] charArray = typeName.toCharArray(); - if ((index = classNameCache.get(charArray)) < 0) { - int nameIndex = literalIndex(charArray); - index = classNameCache.put(charArray, currentIndex++); - writeU1(ClassTag); - writeU2(nameIndex); - } - return index; - } - - private final void writeU1(int value) { - try { - poolContent[currentOffset++] = (byte) value; - } catch (IndexOutOfBoundsException e) { - // currentOffset has been ++ already (see the -1) - int length = poolContent.length; - System.arraycopy(poolContent, 0, (poolContent = new byte[length - + CONSTANTPOOL_GROW_SIZE]), 0, length); - poolContent[currentOffset - 1] = (byte) value; - } - } - - private final void writeU2(int value) { - try { - poolContent[currentOffset++] = (byte) (value >> 8); - } catch (IndexOutOfBoundsException e) { - // currentOffset has been ++ already (see the -1) - int length = poolContent.length; - System.arraycopy(poolContent, 0, (poolContent = new byte[length - + CONSTANTPOOL_GROW_SIZE]), 0, length); - poolContent[currentOffset - 1] = (byte) (value >> 8); - } - try { - poolContent[currentOffset++] = (byte) value; - } catch (IndexOutOfBoundsException e) { - // currentOffset has been ++ already (see the -1) - int length = poolContent.length; - System.arraycopy(poolContent, 0, (poolContent = new byte[length - + CONSTANTPOOL_GROW_SIZE]), 0, length); - poolContent[currentOffset - 1] = (byte) value; - } - } -} diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java deleted file mode 100644 index 93db394..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java +++ /dev/null @@ -1,464 +0,0 @@ -/* - * 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.reflect; - - -interface ProxyConstants { - final char[] CodeName = new char[] { 'C', 'o', 'd', 'e' }; - - final char[] ExceptionsName = new char[] { 'E', 'x', 'c', 'e', 'p', 't', - 'i', 'o', 'n', 's' }; - - final char[] Init = new char[] { '<', 'i', 'n', 'i', 't', '>' }; - - final int AccPublic = 0x0001; - - final int AccPrivate = 0x0002; - - final int AccProtected = 0x0004; - - final int AccStatic = 0x0008; - - final int AccFinal = 0x0010; - - final int AccSuper = 0x0020; - - final int Utf8Tag = 1; - - final int IntegerTag = 3; - - final int FloatTag = 4; - - final int LongTag = 5; - - final int DoubleTag = 6; - - final int ClassTag = 7; - - final int StringTag = 8; - - final int FieldRefTag = 9; - - final int MethodRefTag = 10; - - final int InterfaceMethodRefTag = 11; - - final int NameAndTypeTag = 12; - - final int OPC_nop = 0; - - final int OPC_aconst_null = 1; - - final int OPC_iconst_m1 = 2; - - final int OPC_iconst_0 = 3; - - final int OPC_iconst_1 = 4; - - final int OPC_iconst_2 = 5; - - final int OPC_iconst_3 = 6; - - final int OPC_iconst_4 = 7; - - final int OPC_iconst_5 = 8; - - final int OPC_lconst_0 = 9; - - final int OPC_lconst_1 = 10; - - final int OPC_fconst_0 = 11; - - final int OPC_fconst_1 = 12; - - final int OPC_fconst_2 = 13; - - final int OPC_dconst_0 = 14; - - final int OPC_dconst_1 = 15; - - final int OPC_bipush = 16; - - final int OPC_sipush = 17; - - final int OPC_ldc = 18; - - final int OPC_ldc_w = 19; - - final int OPC_ldc2_w = 20; - - final int OPC_iload = 21; - - final int OPC_lload = 22; - - final int OPC_fload = 23; - - final int OPC_dload = 24; - - final int OPC_aload = 25; - - final int OPC_iload_0 = 26; - - final int OPC_iload_1 = 27; - - final int OPC_iload_2 = 28; - - final int OPC_iload_3 = 29; - - final int OPC_lload_0 = 30; - - final int OPC_lload_1 = 31; - - final int OPC_lload_2 = 32; - - final int OPC_lload_3 = 33; - - final int OPC_fload_0 = 34; - - final int OPC_fload_1 = 35; - - final int OPC_fload_2 = 36; - - final int OPC_fload_3 = 37; - - final int OPC_dload_0 = 38; - - final int OPC_dload_1 = 39; - - final int OPC_dload_2 = 40; - - final int OPC_dload_3 = 41; - - final int OPC_aload_0 = 42; - - final int OPC_aload_1 = 43; - - final int OPC_aload_2 = 44; - - final int OPC_aload_3 = 45; - - final int OPC_iaload = 46; - - final int OPC_laload = 47; - - final int OPC_faload = 48; - - final int OPC_daload = 49; - - final int OPC_aaload = 50; - - final int OPC_baload = 51; - - final int OPC_caload = 52; - - final int OPC_saload = 53; - - final int OPC_istore = 54; - - final int OPC_lstore = 55; - - final int OPC_fstore = 56; - - final int OPC_dstore = 57; - - final int OPC_astore = 58; - - final int OPC_istore_0 = 59; - - final int OPC_istore_1 = 60; - - final int OPC_istore_2 = 61; - - final int OPC_istore_3 = 62; - - final int OPC_lstore_0 = 63; - - final int OPC_lstore_1 = 64; - - final int OPC_lstore_2 = 65; - - final int OPC_lstore_3 = 66; - - final int OPC_fstore_0 = 67; - - final int OPC_fstore_1 = 68; - - final int OPC_fstore_2 = 69; - - final int OPC_fstore_3 = 70; - - final int OPC_dstore_0 = 71; - - final int OPC_dstore_1 = 72; - - final int OPC_dstore_2 = 73; - - final int OPC_dstore_3 = 74; - - final int OPC_astore_0 = 75; - - final int OPC_astore_1 = 76; - - final int OPC_astore_2 = 77; - - final int OPC_astore_3 = 78; - - final int OPC_iastore = 79; - - final int OPC_lastore = 80; - - final int OPC_fastore = 81; - - final int OPC_dastore = 82; - - final int OPC_aastore = 83; - - final int OPC_bastore = 84; - - final int OPC_castore = 85; - - final int OPC_sastore = 86; - - final int OPC_pop = 87; - - final int OPC_pop2 = 88; - - final int OPC_dup = 89; - - final int OPC_dup_x1 = 90; - - final int OPC_dup_x2 = 91; - - final int OPC_dup2 = 92; - - final int OPC_dup2_x1 = 93; - - final int OPC_dup2_x2 = 94; - - final int OPC_swap = 95; - - final int OPC_iadd = 96; - - final int OPC_ladd = 97; - - final int OPC_fadd = 98; - - final int OPC_dadd = 99; - - final int OPC_isub = 100; - - final int OPC_lsub = 101; - - final int OPC_fsub = 102; - - final int OPC_dsub = 103; - - final int OPC_imul = 104; - - final int OPC_lmul = 105; - - final int OPC_fmul = 106; - - final int OPC_dmul = 107; - - final int OPC_idiv = 108; - - final int OPC_ldiv = 109; - - final int OPC_fdiv = 110; - - final int OPC_ddiv = 111; - - final int OPC_irem = 112; - - final int OPC_lrem = 113; - - final int OPC_frem = 114; - - final int OPC_drem = 115; - - final int OPC_ineg = 116; - - final int OPC_lneg = 117; - - final int OPC_fneg = 118; - - final int OPC_dneg = 119; - - final int OPC_ishl = 120; - - final int OPC_lshl = 121; - - final int OPC_ishr = 122; - - final int OPC_lshr = 123; - - final int OPC_iushr = 124; - - final int OPC_lushr = 125; - - final int OPC_iand = 126; - - final int OPC_land = 127; - - final int OPC_ior = 128; - - final int OPC_lor = 129; - - final int OPC_ixor = 130; - - final int OPC_lxor = 131; - - final int OPC_iinc = 132; - - final int OPC_i2l = 133; - - final int OPC_i2f = 134; - - final int OPC_i2d = 135; - - final int OPC_l2i = 136; - - final int OPC_l2f = 137; - - final int OPC_l2d = 138; - - final int OPC_f2i = 139; - - final int OPC_f2l = 140; - - final int OPC_f2d = 141; - - final int OPC_d2i = 142; - - final int OPC_d2l = 143; - - final int OPC_d2f = 144; - - final int OPC_i2b = 145; - - final int OPC_i2c = 146; - - final int OPC_i2s = 147; - - final int OPC_lcmp = 148; - - final int OPC_fcmpl = 149; - - final int OPC_fcmpg = 150; - - final int OPC_dcmpl = 151; - - final int OPC_dcmpg = 152; - - final int OPC_ifeq = 153; - - final int OPC_ifne = 154; - - final int OPC_iflt = 155; - - final int OPC_ifge = 156; - - final int OPC_ifgt = 157; - - final int OPC_ifle = 158; - - final int OPC_if_icmpeq = 159; - - final int OPC_if_icmpne = 160; - - final int OPC_if_icmplt = 161; - - final int OPC_if_icmpge = 162; - - final int OPC_if_icmpgt = 163; - - final int OPC_if_icmple = 164; - - final int OPC_if_acmpeq = 165; - - final int OPC_if_acmpne = 166; - - final int OPC_goto = 167; - - final int OPC_jsr = 168; - - final int OPC_ret = 169; - - final int OPC_tableswitch = 170; - - final int OPC_lookupswitch = 171; - - final int OPC_ireturn = 172; - - final int OPC_lreturn = 173; - - final int OPC_freturn = 174; - - final int OPC_dreturn = 175; - - final int OPC_areturn = 176; - - final int OPC_return = 177; - - final int OPC_getstatic = 178; - - final int OPC_putstatic = 179; - - final int OPC_getfield = 180; - - final int OPC_putfield = 181; - - final int OPC_invokevirtual = 182; - - final int OPC_invokespecial = 183; - - final int OPC_invokestatic = 184; - - final int OPC_invokeinterface = 185; - - final int OPC_new = 187; - - final int OPC_newarray = 188; - - final int OPC_anewarray = 189; - - final int OPC_arraylength = 190; - - final int OPC_athrow = 191; - - final int OPC_checkcast = 192; - - final int OPC_instanceof = 193; - - final int OPC_monitorenter = 194; - - final int OPC_monitorexit = 195; - - final int OPC_wide = 196; - - final int OPC_multianewarray = 197; - - final int OPC_ifnull = 198; - - final int OPC_ifnonnull = 199; - - final int OPC_goto_w = 200; - - final int OPC_jsr_w = 201; -} diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java deleted file mode 100644 index cd112b5..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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.reflect; - -import java.lang.reflect.Method; - -import org.apache.harmony.luni.util.Msg; - -class ProxyMethod { - Method method; - - Class[] commonExceptions; - - ProxyMethod(Method method) { - this.method = method; - this.commonExceptions = method.getExceptionTypes(); - } - - Class[] getCheckedExceptions() { - Class[] newExceptions = commonExceptions.clone(); - int cLength = newExceptions.length; - for (int c = 0, cL = cLength; c < cL; c++) { - Class<?> ex = newExceptions[c]; - if (Throwable.class == ex) { - // if Throwable is included then treat as if no exceptions are - // checked - return new Class[0]; - } - if (Error.class.isAssignableFrom(ex) || RuntimeException.class.isAssignableFrom(ex)) { - newExceptions[c] = null; - cLength--; - } - } - - // All errors & runtime exceptions are passed back without being wrapped - Class[] result = new Class[cLength + 2]; - int index = 0; - result[index++] = Error.class; - result[index++] = RuntimeException.class; - for (Class<?> ex : newExceptions) { - if (ex != null) { - result[index++] = ex; - } - } - return result; - } - - boolean matchMethod(Method otherMethod) { - if (!method.getName().equals(otherMethod.getName())) { - return false; - } - - Class[] params1 = method.getParameterTypes(); - Class[] params2 = otherMethod.getParameterTypes(); - int p = params1.length; - if (p != params2.length) { - return false; - } - while (--p >= 0) { - if (params1[p] != params2[p]) { - return false; - } - } - - Class<?> thisMethodReturnType = method.getReturnType(); - Class<?> otherMethodReturnType = otherMethod.getReturnType(); - if (!thisMethodReturnType.isAssignableFrom(otherMethodReturnType)) { - if (otherMethodReturnType.isAssignableFrom(thisMethodReturnType)) { - // substitute returnType of method with that of otherMethod - method = otherMethod; - } else { - throw new IllegalArgumentException(Msg.getString("K00f2", - method.getName())); - } - } - - if (commonExceptions.length != 0) { - Class[] otherExceptions = otherMethod.getExceptionTypes(); - if (otherExceptions.length == 0) { - commonExceptions = otherExceptions; - } else { - int cLength = commonExceptions.length; - nextException: for (int c = 0, cL = cLength, oL = otherExceptions.length; c < cL; c++) { - Class<?> cException = commonExceptions[c]; - for (int o = 0; o < oL; o++) { - Class<?> oException = otherExceptions[o]; - if (cException == oException) { - continue nextException; - } - if (oException.isAssignableFrom(cException)) { - continue nextException; // cException is a subclass - } - if (cException.isAssignableFrom(oException)) { - // oException is a subclass, keep it instead - commonExceptions[c] = cException = oException; - continue nextException; - } - } - commonExceptions[c] = null; - cLength--; - } - if (cLength != commonExceptions.length) { - Class[] newExceptions = new Class[cLength]; - for (int i = 0, j = 0, length = commonExceptions.length; i < length; i++) { - Class<?> ex = commonExceptions[i]; - if (ex != null) { - newExceptions[j++] = ex; - } - } - commonExceptions = newExceptions; - } - } - } - return true; - } - -} diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java deleted file mode 100644 index 09eb23e..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.reflect; - -class ProxyNameAndTypeCache { - int[][] keyTable; - - int[] valueTable; - - int elementSize; - - int threshold; - - ProxyNameAndTypeCache(int initialCapacity) { - if (initialCapacity < 13) { - initialCapacity = 13; - } - this.elementSize = 0; - this.threshold = (int) (initialCapacity * 0.66f); - this.keyTable = new int[initialCapacity][]; - this.valueTable = new int[initialCapacity]; - } - - int get(int[] key) { - int index = hashCode(key); - while (keyTable[index] != null) { - if (keyTable[index][0] == key[0] && keyTable[index][1] == key[1]) { - return valueTable[index]; - } - index = (index + 1) % keyTable.length; - } - return -1; - } - - int hashCode(int[] key) { - return (key[0] + key[1]) % keyTable.length; - } - - int put(int[] key, int value) { - int index = hashCode(key); - while (keyTable[index] != null) { - if (keyTable[index][0] == key[0] && keyTable[index][1] == key[1]) { - return valueTable[index] = value; - } - index = (index + 1) % keyTable.length; - } - keyTable[index] = key; - valueTable[index] = value; - - // assumes the threshold is never equal to the size of the table - if (++elementSize > threshold) { - rehash(); - } - return value; - } - - private void rehash() { - ProxyNameAndTypeCache newHashtable = new ProxyNameAndTypeCache(keyTable.length * 2); - for (int i = keyTable.length; --i >= 0;) { - if (keyTable[i] != null) { - newHashtable.put(keyTable[i], valueTable[i]); - } - } - - this.keyTable = newHashtable.keyTable; - this.valueTable = newHashtable.valueTable; - this.threshold = newHashtable.threshold; - } - - int size() { - return elementSize; - } - - @Override - public String toString() { - int max = size(); - StringBuilder buf = new StringBuilder(); - buf.append("{"); - for (int i = 0; i < max; ++i) { - if (keyTable[i] != null) { - buf.append(keyTable[i]).append("->").append(valueTable[i]); - } - if (i < max) { - buf.append(", "); - } - } - buf.append("}"); - return buf.toString(); - } -} diff --git a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java b/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java deleted file mode 100644 index b3089c5..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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.reflect; - -class ProxyObjectCache { - Object keyTable[]; - - int valueTable[]; - - int elementSize; - - int threshold; - - ProxyObjectCache(int initialCapacity) { - if (initialCapacity < 13) { - initialCapacity = 13; - } - this.elementSize = 0; - this.threshold = (int) (initialCapacity * 0.66f); - this.keyTable = new Object[initialCapacity]; - this.valueTable = new int[initialCapacity]; - } - - int get(Object key) { - int index = hashCode(key); - while (keyTable[index] != null) { - if (keyTable[index].equals(key)) { - return valueTable[index]; - } - index = (index + 1) % keyTable.length; - } - return -1; - } - - int hashCode(Object key) { - return (key.hashCode() & 0x7FFFFFFF) % keyTable.length; - } - - int put(Object key, int value) { - int index = hashCode(key); - while (keyTable[index] != null) { - if (keyTable[index].equals(key)) { - return valueTable[index] = value; - } - index = (index + 1) % keyTable.length; - } - keyTable[index] = key; - valueTable[index] = value; - - // assumes the threshold is never equal to the size of the table - if (++elementSize > threshold) { - rehash(); - } - return value; - } - - private void rehash() { - ProxyObjectCache newHashtable = new ProxyObjectCache( - keyTable.length * 2); - for (int i = keyTable.length; --i >= 0;) { - if (keyTable[i] != null) { - newHashtable.put(keyTable[i], valueTable[i]); - } - } - - this.keyTable = newHashtable.keyTable; - this.valueTable = newHashtable.valueTable; - this.threshold = newHashtable.threshold; - } - - int size() { - return elementSize; - } - - @Override - public String toString() { - int max = size(); - StringBuilder buf = new StringBuilder(); - buf.append("{"); //$NON-NLS-1$ - for (int i = 0; i < max; ++i) { - if (keyTable[i] != null) { - buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$ - } - if (i < max) { - buf.append(", "); //$NON-NLS-1$ - } - } - buf.append("}"); //$NON-NLS-1$ - return buf.toString(); - } -} diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java index 230df13..ac0c877 100644 --- a/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java +++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java @@ -42,7 +42,7 @@ import org.apache.harmony.luni.util.PriviAction; * support security checks. Alternative types of DatagramSocketImpl's may be * used by setting the <code>impl.prefix</code> system property. */ -class PlainDatagramSocketImpl extends DatagramSocketImpl { +public class PlainDatagramSocketImpl extends DatagramSocketImpl { static final int MULTICAST_IF = 1; @@ -70,7 +70,8 @@ class PlainDatagramSocketImpl extends DatagramSocketImpl { */ static final int REUSEADDR_AND_REUSEPORT = 10001; - private boolean bindToDevice; + // Ignored in native code + private boolean bindToDevice = false; private byte[] ipaddress = { 0, 0, 0, 0 }; @@ -116,7 +117,7 @@ class PlainDatagramSocketImpl extends DatagramSocketImpl { public void bind(int port, InetAddress addr) throws SocketException { String prop = AccessController.doPrivileged(new PriviAction<String>("bindToDevice")); //$NON-NLS-1$ boolean useBindToDevice = prop != null && prop.toLowerCase().equals("true"); //$NON-NLS-1$ - bindToDevice = netImpl.bind2(fd, port, useBindToDevice, addr); + netImpl.bind(fd, addr, port); if (0 != port) { localPort = port; } else { diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java deleted file mode 100644 index 7f5ac50..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.net; - -import java.net.SocketException; - -import org.apache.harmony.luni.platform.Platform; - -/** - * This class was added so we can create sockets with options that are needed - * for server sockets. It just overrides create so that we call new natives - * which only set the options required for server sockets. In order to preserve - * behaviour of older versions the create PlainSocketImpl was left as is and - * this new class was added. For newer versions an instance of this class is - * used, for earlier versions the original PlainSocketImpl is used. - */ -class PlainMulticastSocketImpl extends PlainDatagramSocketImpl { - - @Override - public void create() throws SocketException { - Platform.getNetworkSystem().createMulticastSocket(fd, NetUtil.preferIPv4Stack()); - } -} diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java index de6cb8f..4343ffb 100644 --- a/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java +++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java @@ -24,14 +24,10 @@ import org.apache.harmony.luni.net.NetUtil; import org.apache.harmony.luni.net.PlainSocketImpl; /** - * This class was added so we can create sockets with options that are needed - * for server sockets. It just overrides create so that we call new natives - * which only set the options required for server sockets. In order to preserve - * behaviour of older versions the create PlainSocketImpl was left as is and - * this new class was added. For newer versions an instance of this class is - * used, for earlier versions the original PlainSocketImpl is used. + * This class overrides create to call natives that set the options required + * for server sockets. */ -class PlainServerSocketImpl extends PlainSocketImpl { +public class PlainServerSocketImpl extends PlainSocketImpl { public PlainServerSocketImpl() { super(); diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java index 4fb8b91..9a3ae6e 100644 --- a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java +++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java @@ -43,7 +43,7 @@ import org.apache.harmony.luni.util.Msg; /** * A concrete connected-socket implementation. */ -class PlainSocketImpl extends SocketImpl { +public class PlainSocketImpl extends SocketImpl { // Const copy from socket @@ -89,6 +89,27 @@ class PlainSocketImpl extends SocketImpl { fd = new FileDescriptor(); } + public PlainSocketImpl(FileDescriptor fd) { + super(); + this.fd = fd; + } + + /** + * creates an instance with specified proxy. + */ + public PlainSocketImpl(Proxy proxy) { + this(); + this.proxy = proxy; + } + + public PlainSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port) { + super(); + this.fd = fd; + this.localport = localport; + this.address = addr; + this.port = port; + } + @Override protected void accept(SocketImpl newImpl) throws IOException { if (NetUtil.usingSocks(proxy)) { @@ -160,7 +181,7 @@ class PlainSocketImpl extends SocketImpl { @Override protected void bind(InetAddress anAddr, int aPort) throws IOException { - netImpl.bind(fd, aPort, anAddr); + netImpl.bind(fd, anAddr, aPort); // PlainSocketImpl2.socketBindImpl2(fd, aPort, anAddr); address = anAddr; if (0 != aPort) { @@ -201,7 +222,7 @@ class PlainSocketImpl extends SocketImpl { /** * Connects this socket to the specified remote host address/port. - * + * * @param anAddr * the remote host address to connect to * @param aPort @@ -211,13 +232,10 @@ class PlainSocketImpl extends SocketImpl { * @throws IOException * if an error occurs while connecting */ - // BEGIN android-changed - // copied from a newer harmony revision private void connect(InetAddress anAddr, int aPort, int timeout) throws IOException { - InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress - .getLocalHost() : anAddr; + InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress.getLocalHost() : anAddr; try { if (streaming) { if (NetUtil.usingSocks(proxy)) { @@ -231,7 +249,7 @@ class PlainSocketImpl extends SocketImpl { } } } else { - netImpl.connectDatagram(fd, aPort, trafficClass, normalAddr); + netImpl.connectDatagram(fd, aPort, trafficClass, normalAddr); } } catch (ConnectException e) { throw new ConnectException(anAddr + ":" + aPort + " - " @@ -240,16 +258,12 @@ class PlainSocketImpl extends SocketImpl { super.address = normalAddr; super.port = aPort; } - // END android-changed @Override protected void create(boolean streaming) throws IOException { this.streaming = streaming; if (streaming) { - // BEGIN android-changed - // call createSocket instead of createStreamSocket - netImpl.createSocket(fd, NetUtil.preferIPv4Stack()); - // END android-changed + netImpl.createStreamSocket(fd, NetUtil.preferIPv4Stack()); } else { netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack()); } @@ -546,16 +560,19 @@ class PlainSocketImpl extends SocketImpl { if (shutdownInput) { return -1; } - try { - int read = netImpl.receiveStream(fd, buffer, offset, count, - receiveTimeout); - if (read == -1) { - shutdownInput = true; - } - return read; - } catch (InterruptedIOException e) { - throw new SocketTimeoutException(e.getMessage()); + // BEGIN android-changed + // call receiveStream() instead of read() + int read = netImpl.receiveStream(fd, buffer, offset, count, receiveTimeout); + // END android-changed + // Return of zero bytes for a blocking socket means a timeout occurred + if (read == 0) { + throw new SocketTimeoutException(); + } + // Return of -1 indicates the peer was closed + if (read == -1) { + shutdownInput = true; } + return read; } int write(byte[] buffer, int offset, int count) throws IOException { @@ -563,6 +580,9 @@ class PlainSocketImpl extends SocketImpl { return netImpl.sendDatagram2(fd, buffer, offset, count, port, address); } + // BEGIN android-changed + // call sendStream() instead of write() return netImpl.sendStream(fd, buffer, offset, count); + // END android-changed } } diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java deleted file mode 100644 index 160de7c..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.net; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.InetAddress; -import java.net.Proxy; - -/** - * This class was added so we can create sockets without options that were - * needed for server sockets. It just overrides create so that we call new - * natives which only set the options required for plain sockets. In order to - * preserve behaviour of older versions the create PlainSocketImpl was left as - * is and this new class was added. For newer versions an instance of this class - * is used, for earlier versions the original PlainSocketImpl is used. - */ -class PlainSocketImpl2 extends PlainSocketImpl { - - public PlainSocketImpl2(FileDescriptor fd, int localport, InetAddress addr, int port) { - super(); - super.fd = fd; - super.localport = localport; - super.address = addr; - super.port = port; - } - - public PlainSocketImpl2() { - super(); - } - - /** - * creates an instance with specified proxy. - */ - public PlainSocketImpl2(Proxy proxy) { - super(); - this.proxy = proxy; - } - - @Override - protected void create(boolean isStreaming) throws IOException { - streaming = isStreaming; - if (isStreaming) { - netImpl.createSocket(fd, NetUtil.preferIPv4Stack()); - } else { - netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack()); - } - } -} diff --git a/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java b/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java deleted file mode 100644 index e8e7dc3..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java +++ /dev/null @@ -1,62 +0,0 @@ -/* 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.net; - -import java.io.FileDescriptor; -import java.net.DatagramSocketImpl; -import java.net.InetAddress; -import java.net.Proxy; -import java.net.SocketImpl; - -public class SocketImplProvider { - - public static SocketImpl getSocketImpl() { - return new PlainSocketImpl2(); - } - - /** - * gets a SocketImpl with specified proxy. - */ - public static SocketImpl getSocketImpl(Proxy proxy) { - return new PlainSocketImpl2(proxy); - } - - public static SocketImpl getSocketImpl(FileDescriptor fd, int localport, InetAddress addr, - int port) { - return new PlainSocketImpl2(fd, localport, addr, port); - } - - public static SocketImpl getServerSocketImpl() { - return new PlainServerSocketImpl(); - } - - public static SocketImpl getServerSocketImpl(FileDescriptor fd) { - return new PlainServerSocketImpl(fd); - } - - public static DatagramSocketImpl getDatagramSocketImpl() { - return new PlainDatagramSocketImpl(); - } - - public static DatagramSocketImpl getMulticastSocketImpl() { - return new PlainMulticastSocketImpl(); - } - - public static DatagramSocketImpl getDatagramSocketImpl(FileDescriptor fd, int localPort) { - return new PlainDatagramSocketImpl(fd, localPort); - } - -} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java b/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java index 130454f..5462cf0 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java @@ -30,84 +30,82 @@ import java.util.Map; */ abstract class AbstractMemorySpy implements IMemorySpy { - // TODO: figure out how to prevent this being a synchronization bottleneck - protected Map<PlatformAddress,AddressWrapper> memoryInUse = new HashMap<PlatformAddress, AddressWrapper>(); // Shadow to Wrapper + // TODO: figure out how to prevent this being a synchronization bottleneck + protected Map<PlatformAddress,AddressWrapper> memoryInUse = new HashMap<PlatformAddress, AddressWrapper>(); // Shadow to Wrapper - protected Map<Reference,PlatformAddress> refToShadow = new HashMap<Reference, PlatformAddress>(); // Reference to Shadow + protected Map<Reference,PlatformAddress> refToShadow = new HashMap<Reference, PlatformAddress>(); // Reference to Shadow - protected ReferenceQueue<Object> notifyQueue = new ReferenceQueue<Object>(); + protected ReferenceQueue<Object> notifyQueue = new ReferenceQueue<Object>(); - final class AddressWrapper { - final PlatformAddress shadow; + final class AddressWrapper { + final PlatformAddress shadow; - final PhantomReference<PlatformAddress> wrAddress; + final PhantomReference<PlatformAddress> wrAddress; - volatile boolean autoFree = false; + volatile boolean autoFree = false; - AddressWrapper(PlatformAddress address) { - super(); - this.shadow = address.duplicate(); - this.wrAddress = new PhantomReference<PlatformAddress>(address, notifyQueue); - } - } + AddressWrapper(PlatformAddress address) { + super(); + this.shadow = address.duplicate(); + this.wrAddress = new PhantomReference<PlatformAddress>(address, notifyQueue); + } + } - public AbstractMemorySpy() { - super(); - } + public AbstractMemorySpy() { + super(); + } - public void alloc(PlatformAddress address) { - AddressWrapper wrapper = new AddressWrapper(address); - synchronized (this) { - memoryInUse.put(wrapper.shadow, wrapper); - refToShadow.put(wrapper.wrAddress, wrapper.shadow); - } - } + public void alloc(PlatformAddress address) { + AddressWrapper wrapper = new AddressWrapper(address); + synchronized (this) { + memoryInUse.put(wrapper.shadow, wrapper); + refToShadow.put(wrapper.wrAddress, wrapper.shadow); + } + } - public boolean free(PlatformAddress address) { - AddressWrapper wrapper; - synchronized (this) { - wrapper = memoryInUse.remove(address); + public boolean free(PlatformAddress address) { + AddressWrapper wrapper; + synchronized (this) { + wrapper = memoryInUse.remove(address); // BEGIN android-added if (wrapper != null) { refToShadow.remove(wrapper.wrAddress); } // END android-added - } - if (wrapper == null) { - // Attempt to free memory we didn't alloc - System.err - .println("Memory Spy! Fixed attempt to free memory that was not allocated " + address); //$NON-NLS-1$ - } - return wrapper != null; - } - - public void rangeCheck(PlatformAddress address, int offset, int length) - throws IndexOutOfBoundsException { - // Do nothing - } - - /* - * (non-Javadoc) - * - * @see org.apache.harmony.luni.platform.struct.IMemorySpy#autoFree(org.apache.harmony.luni.platform.struct.PlatformAddress) - */ - public void autoFree(PlatformAddress address) { - AddressWrapper wrapper; - synchronized (this) { - wrapper = memoryInUse.get(address); - } - if (wrapper != null) { - wrapper.autoFree = true; - } - } - - protected void orphanedMemory(Reference ref) { - AddressWrapper wrapper; - // BEGIN android-changed - // copied from newer version of harmony - synchronized (this) { - PlatformAddress shadow = refToShadow.remove(ref); - wrapper = memoryInUse.get(shadow); + } + if (wrapper == null) { + // Attempt to free memory we didn't alloc + System.err + .println("Memory Spy! Fixed attempt to free memory that was not allocated " + address); //$NON-NLS-1$ + } + return wrapper != null; + } + + public void rangeCheck(PlatformAddress address, int offset, int length) + throws IndexOutOfBoundsException { + // Do nothing + } + + /* + * (non-Javadoc) + * + * @see org.apache.harmony.luni.platform.struct.IMemorySpy#autoFree(org.apache.harmony.luni.platform.struct.PlatformAddress) + */ + public void autoFree(PlatformAddress address) { + AddressWrapper wrapper; + synchronized (this) { + wrapper = memoryInUse.get(address); + } + if (wrapper != null) { + wrapper.autoFree = true; + } + } + + protected void orphanedMemory(Reference ref) { + AddressWrapper wrapper; + synchronized (this) { + PlatformAddress shadow = refToShadow.remove(ref); + wrapper = memoryInUse.get(shadow); if (wrapper != null) { // There is a leak if we were not auto-freeing this memory. if (!wrapper.autoFree) { @@ -116,8 +114,7 @@ abstract class AbstractMemorySpy implements IMemorySpy { } wrapper.shadow.free(); } - } + } ref.clear(); - // END android-changed - } + } } diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java b/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java deleted file mode 100644 index 2380fbc..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java +++ /dev/null @@ -1,79 +0,0 @@ -/* 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.platform; - - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; - -/** - * Adapter Manager - * - */ -final class AdapterManager implements IAdapterManager { - - /* - * key is adaptable type, and value is list of adapter factories for that - * type. - */ - private final HashMap<Class, List<IAdapterFactory>> factories = new HashMap<Class, List<IAdapterFactory>>(); - - public Object getAdapter(IAdaptable adaptable, Class adapterType) { - List factoryList = factories.get(adapterType); - if (factoryList != null) { - for (Iterator factoryItr = factoryList.iterator(); factoryItr - .hasNext();) { - IAdapterFactory factory = (IAdapterFactory) factoryItr.next(); - Object adapter = factory.getAdapter(adaptable, adapterType); - if (adapter != null) { - return adapter; - } - } - } - return null; - } - - public boolean hasAdapter(IAdaptable adaptable, Class adapterType) { - return null == getAdapter(adaptable, adapterType); - } - - public void registerAdapters(IAdapterFactory factory, Class adaptable) { - List<IAdapterFactory> factoryList = factories.get(adaptable); - if (factoryList == null) { - factoryList = new ArrayList<IAdapterFactory>(); - factories.put(adaptable, factoryList); - } - factoryList.add(factory); - } - - public void unregisterAdapters(IAdapterFactory factory, Class adaptable) { - List factoryList = factories.get(adaptable); - if (factoryList != null) { - factoryList.remove(factory); - } - } - - public void unregisterAdapters(IAdapterFactory factory) { - for (Iterator<Class> knownAdaptablesItr = factories.keySet().iterator(); knownAdaptablesItr - .hasNext();) { - Class adaptable = knownAdaptablesItr.next(); - unregisterAdapters(factory, adaptable); - } - } -} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java b/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java deleted file mode 100644 index e4c72ea..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java +++ /dev/null @@ -1,54 +0,0 @@ -/* 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.platform; - - -/** - * The interface to extensible objects. - * <p> - * Classes can implement this interface (a single method) to provide interfaces - * that are not API -- each interface type has to be handled in the - * implementation of <code>getAdapter(Class)</code>. This is a good way to - * extend the class without breaking existing API. - * </p> - * <p> - * In addition, classes can be augmented by interfaces that are defined by other - * classes (which requires the <code>getAdapter(Class)</code> to be - * implemented by a factory. - * - */ -public interface IAdaptable { - - /** - * Returns the adapter corresponding to the given class. - * <p> - * The adapter is typically obtained using the class literal, like this: - * - * <pre> - * ... - * IAdaptable = (IAdaptable) foo; - * IMyInterface bar = (IMyInterface)foo.getAdapter(IMyInterface.class); - * bar.doMyThing(); - * ... - * </pre> - * - * @param adapter - * the type of adapter requested - * @return the adapter - */ - public Object getAdapter(Class adapter); -} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java b/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java deleted file mode 100644 index 49fcd15..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/* 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.platform; - - -/** - * IAdapterFactory - * - */ -public interface IAdapterFactory { - - /** - * Answer the adapter of the given type for the given object. - * - * @param adaptableObject - * the object that implements IAdaptable. - * @param adapterType - * the type of adapter to return. - * @return the adapter of the requested type. - */ - public Object getAdapter(IAdaptable adaptableObject, Class adapterType); - - /** - * Returns the adapters that this factory provides. - * - * @return the list of adapters as an array of classes. - */ - public Class[] getAdapterList(); -} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java b/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java deleted file mode 100644 index 886dda7..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java +++ /dev/null @@ -1,34 +0,0 @@ -/* 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.platform; - - -/** - * IAdapterManager - * - */ -public interface IAdapterManager { - public Object getAdapter(IAdaptable adaptable, Class adapterType); - - public boolean hasAdapter(IAdaptable adaptable, Class adapterType); - - public void registerAdapters(IAdapterFactory factory, Class adaptable); - - public void unregisterAdapters(IAdapterFactory factory); - - public void unregisterAdapters(IAdapterFactory factory, Class adaptable); -} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java index fb2ff9d..7613f0e 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java @@ -29,7 +29,7 @@ import java.io.IOException; * TODO Type description * */ -public interface IFileSystem extends ISystemComponent { +public interface IFileSystem { public final int SHARED_LOCK_TYPE = 1; diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java index 9f70515..eae5261 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java @@ -29,17 +29,12 @@ import java.net.SocketException; import java.net.SocketImpl; import java.net.UnknownHostException; import java.nio.channels.Channel; -import java.nio.channels.SelectableChannel; /* * The interface for network methods. */ public interface INetworkSystem { - // ----------------------------------------------- - // Class Const - // ----------------------------------------------- - /* * Socket connect Step start */ @@ -50,34 +45,24 @@ public interface INetworkSystem { */ public final int SOCKET_CONNECT_STEP_CHECK = 1; - // ----------------------------------------------- - // Methods - // ----------------------------------------------- - /* * socket accept */ public void accept(FileDescriptor fdServer, SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout) throws IOException; - public void bind(FileDescriptor aFD, int port, InetAddress inetAddress) + public void bind(FileDescriptor aFD, InetAddress inetAddress, int port) throws SocketException; - public boolean bind2(FileDescriptor aFD, int port, boolean bindToDevice, - InetAddress inetAddress) throws SocketException; - - public void createSocket(FileDescriptor fd, boolean preferIPv4Stack) - throws IOException; - public int read(FileDescriptor aFD, byte[] data, int offset, int count, int timeout) throws IOException; - + public int readDirect(FileDescriptor aFD, int address, int offset, int count, int timeout) throws IOException; public int write(FileDescriptor fd, byte[] data, int offset, int count) throws IOException; - + public int writeDirect(FileDescriptor fd, int address, int offset, int count) throws IOException; @@ -96,7 +81,7 @@ public interface INetworkSystem { public int sendDatagram(FileDescriptor fd, byte[] data, int offset, int length, int port, boolean bindToDevice, int trafficClass, InetAddress inetAddress) throws IOException; - + public int sendDatagramDirect(FileDescriptor fd, int address, int offset, int length, int port, boolean bindToDevice, int trafficClass, InetAddress inetAddress) throws IOException; @@ -104,7 +89,7 @@ public interface INetworkSystem { public int receiveDatagram(FileDescriptor aFD, DatagramPacket packet, byte[] data, int offset, int length, int receiveTimeout, boolean peek) throws IOException; - + public int receiveDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address, int offset, int length, int receiveTimeout, boolean peek) throws IOException; @@ -112,17 +97,17 @@ public interface INetworkSystem { public int recvConnectedDatagram(FileDescriptor aFD, DatagramPacket packet, byte[] data, int offset, int length, int receiveTimeout, boolean peek) throws IOException; - + public int recvConnectedDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address, int offset, int length, int receiveTimeout, boolean peek) throws IOException; - + public int peekDatagram(FileDescriptor aFD, InetAddress sender, int receiveTimeout) throws IOException; public int sendConnectedDatagram(FileDescriptor fd, byte[] data, int offset, int length, boolean bindToDevice) throws IOException; - + public int sendConnectedDatagramDirect(FileDescriptor fd, int address, int offset, int length, boolean bindToDevice) throws IOException; @@ -134,17 +119,17 @@ public interface INetworkSystem { public void connectDatagram(FileDescriptor aFD, int port, int trafficClass, InetAddress inetAddress) throws SocketException; - public void createMulticastSocket(FileDescriptor aFD, - boolean preferIPv4Stack) throws SocketException; - - public void createServerStreamSocket(FileDescriptor aFD, - boolean preferIPv4Stack) throws SocketException; - + /** + * @deprecated Use {@link #read(FileDescriptor, byte[], int, int, int)} + */ + @Deprecated public int receiveStream(FileDescriptor aFD, byte[] data, int offset, int count, int timeout) throws IOException; + // BEGIN android-added public int sendStream(FileDescriptor fd, byte[] data, int offset, int count) throws IOException; + // END android-added public void shutdownInput(FileDescriptor descriptor) throws IOException; @@ -160,11 +145,14 @@ public interface INetworkSystem { // public void acceptStreamSocket(FileDescriptor fdServer, // SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout) // throws IOException; - // - // public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack) - // throws SocketException; // END android-removed + public void createServerStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack) + throws SocketException; + + public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack) + throws SocketException; + public void listenStreamSocket(FileDescriptor aFD, int backlog) throws SocketException; @@ -184,7 +172,7 @@ public interface INetworkSystem { /* * Query the IP stack for the local port to which this socket is bound. - * + * * @param aFD the socket descriptor @param preferIPv6Addresses address * preference for nodes that support both IPv4 and IPv6 @return int the * local port to which the socket is bound @@ -194,10 +182,10 @@ public interface INetworkSystem { /* * Query the IP stack for the nominated socket option. - * + * * @param aFD the socket descriptor @param opt the socket option type * @return the nominated socket option value - * + * * @throws SocketException if the option is invalid */ public Object getSocketOption(FileDescriptor aFD, int opt) @@ -205,10 +193,10 @@ public interface INetworkSystem { /* * Set the nominated socket option in the IP stack. - * + * * @param aFD the socket descriptor @param opt the option selector @param * optVal the nominated option value - * + * * @throws SocketException if the option is invalid or cannot be set */ public void setSocketOption(FileDescriptor aFD, int opt, Object optVal) @@ -218,7 +206,7 @@ public interface INetworkSystem { /* * Close the socket in the IP stack. - * + * * @param aFD the socket descriptor */ public void socketClose(FileDescriptor aFD) throws IOException; @@ -233,8 +221,8 @@ public interface INetworkSystem { // BEGIN android-removed // public boolean isReachableByICMP(InetAddress dest,InetAddress source,int ttl,int timeout); // END android-removed - + public Channel inheritedChannel(); - + public void oneTimeInitialization(boolean jcl_supports_ipv6); } diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java b/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java deleted file mode 100644 index 29cf555..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java +++ /dev/null @@ -1,26 +0,0 @@ -/* 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.platform; - - -/** - * ISystemComponent - * - */ -public interface ISystemComponent extends IAdaptable { - /*empty*/ -} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java deleted file mode 100644 index b5f14f2..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java +++ /dev/null @@ -1,51 +0,0 @@ -/* 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.platform; - - -//BEGIN android-changed -import dalvik.system.VMStack; -// END android-changed - -/** - * OSComponent - * - */ -class OSComponent implements IAdaptable { - - /** - * - */ - public OSComponent() { - super(); - // BEGIN android-changed - if (VMStack.getCallingClassLoader() != null) { - throw new SecurityException(); - } - // END android-changed - } - - /* - * (non-Javadoc) - * - * @see org.apache.harmony.luni.platform.IAdaptable#getAdapter(java.lang.Class) - */ - public Object getAdapter(Class adapter) { - return Platform.getAdapterManager().getAdapter(this, adapter); - } - -} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java deleted file mode 100644 index a883ee0..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -/* 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.platform; - - -/** - * OSComponentFactory - * - */ -class OSComponentFactory { - - /** - * @return OSFileSystem - */ - public static IFileSystem getFileSystem() { - // Auto-generated method stub - return new OSFileSystem(); - } - - /** - * @return OSMemory - */ - public static IMemorySystem getMemorySystem() { - // Auto-generated method stub - return new OSMemory(); - } - - /** - * @return OSNetwork - */ - public static INetworkSystem getNetworkSystem() { - return OSNetworkSystem.getOSNetworkSystem(); - } - -} diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java index 2759d6b..20cf7cb 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java @@ -27,14 +27,17 @@ import java.io.IOException; /** * This is the portable implementation of the file system interface. - * + * */ -class OSFileSystem extends OSComponent implements IFileSystem { +class OSFileSystem implements IFileSystem { - /** - * - */ - public OSFileSystem() { + private static final OSFileSystem singleton = new OSFileSystem(); + + public static OSFileSystem getOSFileSystem() { + return singleton; + } + + private OSFileSystem() { super(); } @@ -153,6 +156,14 @@ class OSFileSystem extends OSComponent implements IFileSystem { } long bytesRead = readImpl(fileDescriptor, bytes, offset, length); if (bytesRead < -1) { + /* + * TODO: bytesRead is never less than -1 so this code + * does nothing? + * The native code throws an exception in only one case + * so perhaps this should be 'bytesRead < 0' to handle + * any other cases. But the other cases have been + * ignored until now so fixing this could break things + */ throw new IOException(); } return bytesRead; @@ -203,7 +214,7 @@ class OSFileSystem extends OSComponent implements IFileSystem { /* * (non-Javadoc) - * + * * @see org.apache.harmony.luni.platform.IFileSystem#close(long) */ public void close(int fileDescriptor) throws IOException { @@ -238,7 +249,8 @@ class OSFileSystem extends OSComponent implements IFileSystem { public long transfer(int fileHandler, FileDescriptor socketDescriptor, long offset, long count) throws IOException { long result = transferImpl(fileHandler, socketDescriptor, offset, count); - if (result < 0) throw new IOException(); + if (result < 0) + throw new IOException(); return result; } @@ -268,7 +280,7 @@ class OSFileSystem extends OSComponent implements IFileSystem { } private native long ttyReadImpl(byte[] bytes, int offset, int length); - + // BEGIN android-added public native int ioctlAvailable(int fileDescriptor) throws IOException; // END android-added diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java index e3e7c46..0061d2a 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java @@ -43,7 +43,7 @@ import java.io.IOException; * above. * </p> */ -final class OSMemory extends OSComponent implements IMemorySystem { +final class OSMemory implements IMemorySystem { /** * Defines the size, in bytes, of a native pointer type for the underlying @@ -74,142 +74,150 @@ final class OSMemory extends OSComponent implements IMemorySystem { } /** - * This class is not designed to be publically instantiated. - * + * This class is not designed to be publicly instantiated. + * * @see #getOSMemory() */ - OSMemory() { + private OSMemory() { super(); } - // BEGIN android-note - // changed to private - // END android-note /** * Returns whether the byte order of this machine is little endian or not.. - * - * @return <code>false</code> for Big Endian, and - * <code>true</code. for Little Endian. + * + * @return <code>false</code> for Big Endian, and + * <code>true</code. for Little Endian. */ + // BEGIN android-changed + /*public*/ private static native boolean isLittleEndianImpl(); + // END android-changed public boolean isLittleEndian() { return isLittleEndianImpl(); } - /** - * Returns the natural byte order for this machine. - * - * @return the native byte order for the current platform. - */ - public Endianness getNativeOrder() { - return NATIVE_ORDER; - } - - /** - * Returns the size of a native pointer type for the underlying platform. - * - * @return the size of a pointer, in bytes. - */ - private static native int getPointerSizeImpl(); - - public int getPointerSize() { - return POINTER_SIZE; - } + /** + * Returns the natural byte order for this machine. + * + * @return the native byte order for the current platform. + */ + public Endianness getNativeOrder() { + return NATIVE_ORDER; + } + + /** + * Returns the size of a native pointer type for the underlying platform. + * + * @return the size of a pointer, in bytes. + */ + private static native int getPointerSizeImpl(); + + public int getPointerSize() { + return POINTER_SIZE; + } /** * Allocates and returns a pointer to space for a memory block of * <code>length</code> bytes. The space is uninitialized and may be larger * than the number of bytes requested; however, the guaranteed usable memory * block is exactly <code>length</code> bytes int. - * - * @param length - * number of bytes requested. + * + * @param length + * number of bytes requested. * @return the address of the start of the memory block. - * @throws OutOfMemoryError - * if the request cannot be satisfied. + * @throws OutOfMemoryError + * if the request cannot be satisfied. */ + // BEGIN android-changed + // public long malloc(long length) throws OutOfMemoryError + // { + // OSResourcesMonitor.ensurePhysicalMemoryCapacity(); + // return mallocNative(length); + // } + // private native long mallocNative(long length) throws OutOfMemoryError; public native int malloc(int length) throws OutOfMemoryError; + // END android-changed /** * Deallocates space for a memory block that was previously allocated by a * call to {@link #malloc(int) malloc(int)}. The number of bytes freed is * identical to the number of bytes acquired when the memory block was - * allocated. If <code>address</code> is zero the method does nothing. - * <p> + * allocated. If <code>address</code> is zero the method does nothing. + * <p> * Freeing a pointer to a memory block that was not allocated by - * <code>malloc()</code> has unspecified effect. - * </p> - * - * @param address - * the address of the memory block to deallocate. + * <code>malloc()</code> has unspecified effect. + * </p> + * + * @param address + * the address of the memory block to deallocate. */ public native void free(int address); /** * Places <code>value</code> into first <code>length</code> bytes of the - * memory block starting at <code>address</code>. - * <p> - * The behavior is unspecified if - * <code>(address ... address + length)</code> is not wholly within the - * range that was previously allocated using <code>malloc()</code>. - * </p> - * - * @param address - * the address of the first memory location. - * @param value - * the byte value to set at each location. - * @param length - * the number of byte-length locations to set. + * memory block starting at <code>address</code>. + * <p> + * The behavior is unspecified if + * <code>(address ... address + length)</code> is not wholly within the + * range that was previously allocated using <code>malloc()</code>. + * </p> + * + * @param address + * the address of the first memory location. + * @param value + * the byte value to set at each location. + * @param length + * the number of byte-length locations to set. */ public native void memset(int address, byte value, long length); /** * Copies <code>length</code> bytes from <code>srcAddress</code> to - * <code>destAddress</code>. Where any part of the source memory block - * and the destination memory block overlap <code>memmove()</code> ensures - * that the original source bytes in the overlapping region are copied - * before being overwritten. - * <p> - * The behavior is unspecified if - * <code>(srcAddress ... srcAddress + length)</code> and - * <code>(destAddress ... destAddress + length)</code> are not both wholly - * within the range that was previously allocated using - * <code>malloc()</code>. - * </p> - * - * @param destAddress - * the address of the destination memory block. - * @param srcAddress - * the address of the source memory block. - * @param length - * the number of bytes to move. + * <code>destAddress</code>. Where any part of the source memory block + * and the destination memory block overlap <code>memmove()</code> ensures + * that the original source bytes in the overlapping region are copied + * before being overwritten. + * <p> + * The behavior is unspecified if + * <code>(srcAddress ... srcAddress + length)</code> and + * <code>(destAddress ... destAddress + length)</code> are not both wholly + * within the range that was previously allocated using + * <code>malloc()</code>. + * </p> + * + * @param destAddress + * the address of the destination memory block. + * @param srcAddress + * the address of the source memory block. + * @param length + * the number of bytes to move. */ public native void memmove(int destAddress, int srcAddress, long length); /** * Copies <code>length</code> bytes from the memory block at - * <code>address</code> into the byte array <code>bytes</code> starting - * at element <code>offset</code> within the byte array. - * <p> - * The behavior of this method is undefined if the range - * <code>(address ... address + length)</code> is not within a memory + * <code>address</code> into the byte array <code>bytes</code> starting + * at element <code>offset</code> within the byte array. + * <p> + * The behavior of this method is undefined if the range + * <code>(address ... address + length)</code> is not within a memory * block that was allocated using {@link #malloc(int) malloc(int)}. - * </p> - * - * @param address - * the address of the OS memory block from which to copy bytes. - * @param bytes - * the byte array into which to copy the bytes. - * @param offset - * the index of the first element in <code>bytes</code> that - * will be overwritten. - * @param length - * the total number of bytes to copy into the byte array. - * @throws NullPointerException - * if <code>bytes</code> is <code>null</code>. - * @throws IndexOutOfBoundsException - * if <code>offset + length > bytes.length</code>. + * </p> + * + * @param address + * the address of the OS memory block from which to copy bytes. + * @param bytes + * the byte array into which to copy the bytes. + * @param offset + * the index of the first element in <code>bytes</code> that + * will be overwritten. + * @param length + * the total number of bytes to copy into the byte array. + * @throws NullPointerException + * if <code>bytes</code> is <code>null</code>. + * @throws IndexOutOfBoundsException + * if <code>offset + length > bytes.length</code>. */ public native void getByteArray(int address, byte[] bytes, int offset, int length) throws NullPointerException, IndexOutOfBoundsException; @@ -217,32 +225,32 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Copies <code>length</code> bytes from the byte array <code>bytes</code> * into the memory block at <code>address</code>, starting at element - * <code>offset</code> within the byte array. - * <p> - * The behavior of this method is undefined if the range - * <code>(address ... address + length)</code> is not within a memory + * <code>offset</code> within the byte array. + * <p> + * The behavior of this method is undefined if the range + * <code>(address ... address + length)</code> is not within a memory * block that was allocated using {@link #malloc(int) malloc(int)}. - * </p> - * - * @param address - * the address of the OS memory block into which to copy the - * bytes. - * @param bytes - * the byte array from which to copy the bytes. - * @param offset - * the index of the first element in <code>bytes</code> that - * will be read. - * @param length - * the total number of bytes to copy from <code>bytes</code> - * into the memory block. - * @throws NullPointerException - * if <code>bytes</code> is <code>null</code>. - * @throws IndexOutOfBoundsException - * if <code>offset + length > bytes.length</code>. + * </p> + * + * @param address + * the address of the OS memory block into which to copy the + * bytes. + * @param bytes + * the byte array from which to copy the bytes. + * @param offset + * the index of the first element in <code>bytes</code> that + * will be read. + * @param length + * the total number of bytes to copy from <code>bytes</code> + * into the memory block. + * @throws NullPointerException + * if <code>bytes</code> is <code>null</code>. + * @throws IndexOutOfBoundsException + * if <code>offset + length > bytes.length</code>. */ public native void setByteArray(int address, byte[] bytes, int offset, int length) throws NullPointerException, IndexOutOfBoundsException; - + // BEGIN android-added /** * Copies <code>length</code> shorts from the short array <code>shorts</code> @@ -253,7 +261,7 @@ final class OSMemory extends OSComponent implements IMemorySystem { * <code>(address ... address + 2*length)</code> is not within a memory * block that was allocated using {@link #malloc(int) malloc(int)}. * </p> - * + * * @param address * the address of the OS memory block into which to copy the * shorts. @@ -285,7 +293,7 @@ final class OSMemory extends OSComponent implements IMemorySystem { * <code>(address ... address + 2*length)</code> is not within a memory * block that was allocated using {@link #malloc(int) malloc(int)}. * </p> - * + * * @param address * the address of the OS memory block into which to copy the * ints. @@ -312,43 +320,43 @@ final class OSMemory extends OSComponent implements IMemorySystem { // Primitive get & set methods /** - * Gets the value of the 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 platform address of the byte. + * Gets the value of the 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 platform address of the byte. * @return the byte value. */ public native byte getByte(int address); /** - * Sets the given single byte value 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 set the byte value. - * @param value - * the value to set. + * Sets the given single byte value 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 set the byte value. + * @param value + * the value to set. */ public native void setByte(int address, byte value); /** * Gets the value of the signed two-byte integer stored in platform 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. + * 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. * @return the value of the two-byte integer as a Java <code>short</code>. */ public native short getShort(int address); @@ -360,17 +368,17 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Sets the value of the signed two-byte integer at the given address in - * platform byte order. - * <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 value - * the value of the two-byte integer as a Java <code>short</code>. + * platform byte order. + * <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 value + * the value of the two-byte integer as a Java <code>short</code>. */ public native void setShort(int address, short value); @@ -384,15 +392,15 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Gets the value of the signed four-byte integer stored in platform - * byte-order at the given address. - * <p> - * The behavior is unspecified if <code>(address ... address + 4)</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 four-byte value. + * byte-order at the given address. + * <p> + * The behavior is unspecified if <code>(address ... address + 4)</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 four-byte value. * @return the value of the four-byte integer as a Java <code>int</code>. */ public native int getInt(int address); @@ -404,17 +412,17 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Sets the value of the signed four-byte integer at the given address in - * platform byte order. - * <p> - * The behavior is unspecified if <code>(address ... address + 4)</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 four-byte value. - * @param value - * the value of the four-byte integer as a Java <code>int</code>. + * platform byte order. + * <p> + * The behavior is unspecified if <code>(address ... address + 4)</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 four-byte value. + * @param value + * the value of the four-byte integer as a Java <code>int</code>. */ public native void setInt(int address, int value); @@ -428,15 +436,15 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Gets the value of the signed eight-byte integer stored in platform byte - * order at the given address. - * <p> - * The behavior is unspecified if <code>(address ... address + 8)</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 eight-byte value. + * order at the given address. + * <p> + * The behavior is unspecified if <code>(address ... address + 8)</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 eight-byte value. * @return the value of the eight-byte integer as a Java <code>long</code>. */ public native long getLong(int address); @@ -448,17 +456,17 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Sets the value of the signed eight-byte integer at the given address in - * the platform byte order. - * <p> - * The behavior is unspecified if <code>(address ... address + 8)</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 eight-byte value. - * @param value - * the value of the eight-byte integer as a Java + * the platform byte order. + * <p> + * The behavior is unspecified if <code>(address ... address + 8)</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 eight-byte value. + * @param value + * the value of the eight-byte integer as a Java * <code>long</code>. */ public native void setLong(int address, long value); @@ -473,15 +481,15 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Gets the value of the IEEE754-format four-byte float stored in platform - * byte order at the given address. - * <p> - * The behavior is unspecified if <code>(address ... address + 4)</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 eight-byte value. + * byte order at the given address. + * <p> + * The behavior is unspecified if <code>(address ... address + 4)</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 eight-byte value. * @return the value of the four-byte float as a Java <code>float</code>. */ public native float getFloat(int address); @@ -496,17 +504,17 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Sets the value of the IEEE754-format four-byte float stored in platform - * byte order at the given address. - * <p> - * The behavior is unspecified if <code>(address ... address + 4)</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 eight-byte value. - * @param value - * the value of the four-byte float as a Java <code>float</code>. + * byte order at the given address. + * <p> + * The behavior is unspecified if <code>(address ... address + 4)</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 eight-byte value. + * @param value + * the value of the four-byte float as a Java <code>float</code>. */ public native void setFloat(int address, float value); @@ -521,15 +529,15 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Gets the value of the IEEE754-format eight-byte float stored in platform - * byte order at the given address. - * <p> - * The behavior is unspecified if <code>(address ... address + 8)</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 eight-byte value. + * byte order at the given address. + * <p> + * The behavior is unspecified if <code>(address ... address + 8)</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 eight-byte value. * @return the value of the eight-byte float as a Java <code>double</code>. */ public native double getDouble(int address); @@ -544,17 +552,17 @@ final class OSMemory extends OSComponent implements IMemorySystem { /** * Sets the value of the IEEE754-format eight-byte float store in platform - * byte order at the given address. - * <p> - * The behavior is unspecified if <code>(address ... address + 8)</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 eight-byte value. - * @param value - * the value of the eight-byte float as a Java + * byte order at the given address. + * <p> + * The behavior is unspecified if <code>(address ... address + 8)</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 eight-byte value. + * @param value + * the value of the eight-byte float as a Java * <code>double</code>. */ public native void setDouble(int address, double value); @@ -569,44 +577,44 @@ final class OSMemory extends OSComponent implements IMemorySystem { } /** - * Gets the value of the platform pointer at the given address. - * <p> - * The length of the platform pointer is defined by - * <code>POINTER_SIZE</code>. - * </p> - * The behavior is unspecified if - * <code>(address ... address + POINTER_SIZE)</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 platform pointer. + * Gets the value of the platform pointer at the given address. + * <p> + * The length of the platform pointer is defined by + * <code>POINTER_SIZE</code>. + * </p> + * The behavior is unspecified if + * <code>(address ... address + POINTER_SIZE)</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 platform pointer. * @return the value of the platform pointer as a Java <code>int</code>. */ public native int getAddress(int address); /** - * Sets the value of the platform pointer at the given address. - * <p> - * The length of the platform pointer is defined by - * <code>POINTER_SIZE</code>. This method only sets - * <code>POINTER_SIZE</code> bytes at the given address. - * </p> - * The behavior is unspecified if - * <code>(address ... address + POINTER_SIZE)</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 platform pointer. - * @param value + * Sets the value of the platform pointer at the given address. + * <p> + * The length of the platform pointer is defined by + * <code>POINTER_SIZE</code>. This method only sets + * <code>POINTER_SIZE</code> bytes at the given address. + * </p> + * The behavior is unspecified if + * <code>(address ... address + POINTER_SIZE)</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 platform pointer. + * @param value * the value of the platform pointer as a Java <code>int</code>. */ public native void setAddress(int address, int value); /* - * Memory mapped file - */ + * Memory mapped file + */ private native int mmapImpl(int fileDescriptor, long alignment, long size, int mapMode); @@ -632,39 +640,48 @@ final class OSMemory extends OSComponent implements IMemorySystem { private native int loadImpl(int l, long size); public boolean isLoaded(int addr, long size) { - return size == 0 ? true : isLoadedImpl(addr, size); - } + return size == 0 ? true : isLoadedImpl(addr, size); + } private native boolean isLoadedImpl(int l, long size); public void flush(int addr, long size) { - flushImpl(addr, size); - } + flushImpl(addr, size); + } private native int flushImpl(int l, long size); - /* - * Helper methods to change byte order. - */ - private short swap(short value) { - int topEnd = value << 8; - int btmEnd = (value >> 8) & 0xFF; - return (short) (topEnd | btmEnd); - } - - private int swap(int value) { - short left = (short) (value >> 16); - short right = (short) value; - int topEnd = swap(right) << 16; - int btmEnd = swap(left) & 0xFFFF; - return topEnd | btmEnd; - } - - private long swap(long value) { - int left = (int) (value >> 32); - int right = (int) value; - long topEnd = ((long) swap(right)) << 32; - long btmEnd = swap(left) & 0xFFFFFFFFL; - return topEnd | btmEnd; - } + /* + * Helper methods to change byte order. + */ + private short swap(short value) { + // BEGIN android-note + // is Integer.reverseBytes() >>> 16 be faster? + // END android-note + int topEnd = value << 8; + int btmEnd = (value >> 8) & 0xFF; + return (short) (topEnd | btmEnd); + } + + private int swap(int value) { + // BEGIN android-note + // is Integer.reverseBytes() be faster? + // END android-note + short left = (short) (value >> 16); + short right = (short) value; + int topEnd = swap(right) << 16; + int btmEnd = swap(left) & 0xFFFF; + return topEnd | btmEnd; + } + + private long swap(long value) { + // BEGIN android-note + // is Long.reverseBytes() be faster? + // END android-note + int left = (int) (value >> 32); + int right = (int) value; + long topEnd = ((long) swap(right)) << 32; + long btmEnd = swap(left) & 0xFFFFFFFFL; + return topEnd | btmEnd; + } } diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java index c153428..0c9ac8a 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java @@ -16,7 +16,10 @@ */ // BEGIN android-note -// address length was changed from long to int for performance reasons. +// Address length was changed from long to int for performance reasons. +// Harmony implements INetworkSystem's methods with native methods; Android +// implements them with Java that call through to native wrappers. +// TODO: change the native code to eliminate the wrappers // END android-note package org.apache.harmony.luni.platform; @@ -32,715 +35,779 @@ import java.nio.channels.Channel; // BEGIN android-removed // import java.nio.channels.SelectableChannel; // END android-removed -/* - * - * This Class is used for native code wrap, the implement class of - * INetworkSystem. - * + +/** + * This wraps native code that implements the INetworkSystem interface. */ final class OSNetworkSystem implements INetworkSystem { - // ---------------------------------------------------- - // Class Variables - // ---------------------------------------------------- - private static final int ERRORCODE_SOCKET_TIMEOUT = -209; + private static final int ERRORCODE_SOCKET_INTERRUPTED = -208; - private static OSNetworkSystem ref = new OSNetworkSystem(); - private static final int INETADDR_REACHABLE = 0; - + private static boolean isNetworkInited = false; - - // ---------------------------------------------------- - // Class Constructor - // ---------------------------------------------------- + private static OSNetworkSystem singleton = new OSNetworkSystem(); - // can not be instantiated. - private OSNetworkSystem() { - super(); - } - - /* - * @return a static ref of this class + /** + * Answers the unique instance of the OSNetworkSystem. + * + * @return the network system interface instance */ public static OSNetworkSystem getOSNetworkSystem() { - return ref; - } - - // Useing when cache set/get is OK - // public static native void oneTimeInitializationDatagram( - // boolean jcl_IPv6_support); - // - // public static native void oneTimeInitializationSocket( - // boolean jcl_IPv6_support); - - // -------------------------------------------------- - // java codes that wrap native codes - // -------------------------------------------------- - - public void createSocket(FileDescriptor fd, boolean preferIPv4Stack) - throws IOException { - createSocketImpl(fd, preferIPv4Stack); - } - - public void createDatagramSocket(FileDescriptor fd, boolean preferIPv4Stack) - throws SocketException { - createDatagramSocketImpl(fd, preferIPv4Stack); + return singleton; } - public int read(FileDescriptor aFD, byte[] data, int offset, int count, - int timeout) throws IOException { - return readSocketImpl(aFD, data, offset, count, timeout); - } - - public int readDirect(FileDescriptor aFD, int address, int offset, int count, - int timeout) throws IOException { - return readSocketDirectImpl(aFD, address, offset, count, timeout); + // Can not be instantiated. + private OSNetworkSystem() { + super(); } - public int write(FileDescriptor aFD, byte[] data, int offset, int count) - throws IOException { - return writeSocketImpl(aFD, data, offset, count); - } - - public int writeDirect(FileDescriptor aFD, int address, int offset, - int count) throws IOException { - return writeSocketDirectImpl(aFD, address, offset, count); + public void accept(FileDescriptor fdServer, SocketImpl newSocket, + FileDescriptor fdnewSocket, int timeout) throws IOException { + acceptSocketImpl(fdServer, newSocket, fdnewSocket, timeout); } - public void setNonBlocking(FileDescriptor aFD, boolean block) - throws IOException { - setNonBlockingImpl(aFD, block); - } + static native void acceptSocketImpl(FileDescriptor fdServer, + SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout) + throws IOException; - public void connectDatagram(FileDescriptor aFD, int port, int trafficClass, - InetAddress inetAddress) throws SocketException { - connectDatagramImpl2(aFD, port, trafficClass, inetAddress); - } + // BEGIN android-removed + // public void acceptStreamSocket(FileDescriptor fdServer, + // SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout) + // throws IOException { + // acceptStreamSocketImpl(fdServer, newSocket, fdnewSocket, timeout); + // } - public int connect(FileDescriptor aFD, int trafficClass, - InetAddress inetAddress, int port) throws IOException{ - return connectSocketImpl(aFD, trafficClass, inetAddress, port); - } + // static native void acceptStreamSocketImpl(FileDescriptor fdServer, + // SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout) + // throws IOException; + // END android-removed - // BEGIN android-changed - public int connectWithTimeout(FileDescriptor aFD, int timeout, - int trafficClass, InetAddress inetAddress, int port, int step, - byte[] context) throws IOException{ - return connectWithTimeoutSocketImpl(aFD, timeout, trafficClass, - inetAddress, port, step, context); + public int availableStream(FileDescriptor fd) throws SocketException { + return availableStreamImpl(fd); } - // END android-changed - public void connectStreamWithTimeoutSocket(FileDescriptor aFD, int aport, - int timeout, int trafficClass, InetAddress inetAddress) - throws IOException { - connectStreamWithTimeoutSocketImpl(aFD, aport, timeout, trafficClass, - inetAddress); - } + static native int availableStreamImpl(FileDescriptor aFD) throws SocketException; - public void bind(FileDescriptor aFD, int port, InetAddress inetAddress) - throws SocketException { - socketBindImpl(aFD, port, inetAddress); + /** + * Associates a local address with a socket. + * + * @param fd + * the socket descriptor + * @param port + * the port number + * @param inetAddress + * address to bind + * @throws SocketException + * thrown if bind operation fails + */ + public void bind(FileDescriptor fd, InetAddress inetAddress, int port) throws SocketException { + socketBindImpl(fd, port, inetAddress); } - public boolean bind2(FileDescriptor aFD, int port, boolean bindToDevice, - InetAddress inetAddress) throws SocketException { - return socketBindImpl2(aFD, port, bindToDevice, inetAddress); - } + static native void socketBindImpl(FileDescriptor aFD, int port, InetAddress inetAddress) throws SocketException; - public void accept(FileDescriptor fdServer, SocketImpl newSocket, - FileDescriptor fdnewSocket, int timeout) throws IOException { - acceptSocketImpl(fdServer, newSocket, fdnewSocket, timeout); + public int connect(FileDescriptor fd, int trafficClass, + InetAddress inetAddress, int port) throws IOException{ + return connectSocketImpl(fd, trafficClass, inetAddress, port); } - public int sendDatagram(FileDescriptor fd, byte[] data, int offset, - int length, int port, boolean bindToDevice, int trafficClass, - InetAddress inetAddress) throws IOException { - return sendDatagramImpl(fd, data, offset, length, port, bindToDevice, - trafficClass, inetAddress); - } - - public int sendDatagramDirect(FileDescriptor fd, int address, int offset, - int length, int port, boolean bindToDevice, int trafficClass, - InetAddress inetAddress) throws IOException { - return sendDatagramDirectImpl(fd, address, offset, length, port, bindToDevice, - trafficClass, inetAddress); - } + static native int connectSocketImpl(FileDescriptor aFD, + int trafficClass, InetAddress inetAddress, int port); - public int sendDatagram2(FileDescriptor fd, byte[] data, int offset, - int length, int port, InetAddress inetAddress) throws IOException { - return sendDatagramImpl2(fd, data, offset, length, port, inetAddress); + public void connectDatagram(FileDescriptor fd, int port, + int trafficClass, InetAddress inetAddress) throws SocketException { + connectDatagramImpl2(fd, port, trafficClass, inetAddress); } - public int receiveDatagram(FileDescriptor aFD, DatagramPacket packet, - byte[] data, int offset, int length, int receiveTimeout, - boolean peek) throws IOException { - return receiveDatagramImpl(aFD, packet, data, offset, length, - receiveTimeout, peek); - } - - public int receiveDatagramDirect(FileDescriptor aFD, DatagramPacket packet, - int address, int offset, int length, int receiveTimeout, - boolean peek) throws IOException { - return receiveDatagramDirectImpl(aFD, packet, address, offset, length, - receiveTimeout, peek); - } + static native void connectDatagramImpl2(FileDescriptor aFD, int port, + int trafficClass, InetAddress inetAddress) throws SocketException; - public int recvConnectedDatagram(FileDescriptor aFD, DatagramPacket packet, - byte[] data, int offset, int length, int receiveTimeout, - boolean peek) throws IOException { - return recvConnectedDatagramImpl(aFD, packet, data, offset, length, - receiveTimeout, peek); - } - - public int recvConnectedDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address, - int offset, int length, int receiveTimeout, boolean peek) + public void connectStreamWithTimeoutSocket(FileDescriptor aFD, + int aport, int timeout, int trafficClass, InetAddress inetAddress) throws IOException { - return recvConnectedDatagramDirectImpl(aFD, packet, address, offset, length, receiveTimeout, peek); + connectStreamWithTimeoutSocketImpl(aFD, aport, timeout, trafficClass, + inetAddress); } - public int peekDatagram(FileDescriptor aFD, InetAddress sender, - int receiveTimeout) throws IOException { - return peekDatagramImpl(aFD, sender, receiveTimeout); - } + static native void connectStreamWithTimeoutSocketImpl(FileDescriptor aFD, + int aport, int timeout, int trafficClass, InetAddress inetAddress) + throws IOException; - public int sendConnectedDatagram(FileDescriptor fd, byte[] data, - int offset, int length, boolean bindToDevice) throws IOException { - return sendConnectedDatagramImpl(fd, data, offset, length, bindToDevice); - } - - public int sendConnectedDatagramDirect(FileDescriptor fd, int address, - int offset, int length, boolean bindToDevice) throws IOException { - return sendConnectedDatagramDirectImpl(fd, address, offset, length, bindToDevice); + // BEGIN android-changed + // changed context from Long to byte[] + public int connectWithTimeout(FileDescriptor fd, int timeout, + int trafficClass, InetAddress inetAddress, int port, int step, + byte[] context) throws IOException { + return connectWithTimeoutSocketImpl(fd, timeout, trafficClass, + inetAddress, port, step, context); } - public void disconnectDatagram(FileDescriptor aFD) throws SocketException { - disconnectDatagramImpl(aFD); - } + static native int connectWithTimeoutSocketImpl(FileDescriptor aFD, + int timeout, int trafficClass, InetAddress hostname, int port, int step, + byte[] context); + // END android-changed - public void createMulticastSocket(FileDescriptor aFD, + public void createDatagramSocket(FileDescriptor fd, boolean preferIPv4Stack) throws SocketException { - createMulticastSocketImpl(aFD, preferIPv4Stack); + createDatagramSocketImpl(fd, preferIPv4Stack); } - public void createServerStreamSocket(FileDescriptor aFD, + /* + * Allocate a datagram socket in the IP stack. The socket is associated with + * the <code>aFD</code>. + * + * @param aFD the FileDescriptor to associate with the socket @param + * preferIPv4Stack IP stack preference if underlying platform is V4/V6 + * @exception SocketException upon an allocation error + */ + static native void createDatagramSocketImpl(FileDescriptor aFD, + boolean preferIPv4Stack) throws SocketException; + + public void createServerStreamSocket(FileDescriptor fd, boolean preferIPv4Stack) throws SocketException { - createServerStreamSocketImpl(aFD, preferIPv4Stack); + createServerStreamSocketImpl(fd, preferIPv4Stack); } - public int receiveStream(FileDescriptor aFD, byte[] data, int offset, - int count, int timeout) throws IOException { - return receiveStreamImpl(aFD, data, offset, count, timeout); - } + /* + * Answer the result of attempting to create a server stream socket in the + * IP stack. Any special options required for server sockets will be set by + * this method. + * + * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4 + * @exception SocketException if an error occurs while creating the socket + */ + static native void createServerStreamSocketImpl(FileDescriptor aFD, + boolean preferIPv4Stack) throws SocketException; - public int sendStream(FileDescriptor fd, byte[] data, int offset, int count) - throws IOException { - return sendStreamImpl(fd, data, offset, count); + public void createStreamSocket(FileDescriptor fd, + boolean preferIPv4Stack) throws SocketException { + createStreamSocketImpl(fd, preferIPv4Stack); } - public void shutdownInput(FileDescriptor descriptor) throws IOException { - shutdownInputImpl(descriptor); - } + static native void createStreamSocketImpl(FileDescriptor aFD, + boolean preferIPv4Stack) throws SocketException; - public void shutdownOutput(FileDescriptor descriptor) throws IOException { - shutdownOutputImpl(descriptor); + /** + * Disconnect the socket to a port and address + *a + * @param fd + * the FileDescriptor associated with the socket + * + * @throws SocketException + * if the disconnect fails + */ + public void disconnectDatagram(FileDescriptor fd) + throws SocketException { + disconnectDatagramImpl(fd); } - public boolean supportsUrgentData(FileDescriptor fd) { - return supportsUrgentDataImpl(fd); - } + static native void disconnectDatagramImpl(FileDescriptor aFD) + throws SocketException; - public void sendUrgentData(FileDescriptor fd, byte value) { - sendUrgentDataImpl(fd, value); + public InetAddress getHostByAddr(byte[] addr) + throws UnknownHostException { + return getHostByAddrImpl(addr); } + static native InetAddress getHostByAddrImpl(byte[] addr) + throws UnknownHostException; - public int availableStream(FileDescriptor aFD) throws SocketException { - return availableStreamImpl(aFD); + public InetAddress getHostByName(String addr, + boolean preferIPv6Addresses) throws UnknownHostException { + return getHostByNameImpl(addr, preferIPv6Addresses); } - // BEGIN android-removed - // public void acceptStreamSocket(FileDescriptor fdServer, - // SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout) - // throws IOException { - // acceptStreamSocketImpl(fdServer, newSocket, fdnewSocket, timeout); - // } - // - // public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack) - // throws SocketException { - // createStreamSocketImpl(aFD, preferIPv4Stack); - // } - // END android-removed + static native InetAddress getHostByNameImpl(String addr, + boolean preferIPv6Addresses) throws UnknownHostException; - public void listenStreamSocket(FileDescriptor aFD, int backlog) - throws SocketException { - listenStreamSocketImpl(aFD, backlog); + public int getSocketFlags() { + return getSocketFlagsImpl(); } - - // BEGIN android-removed - // public boolean isReachableByICMP(final InetAddress dest, - // InetAddress source, final int ttl, final int timeout) { - // return INETADDR_REACHABLE == isReachableByICMPImpl(dest, source, ttl, - // timeout); - // } - // END android-removed - /* - * - * @param - * readChannels all channels interested in read and accept - * @param - * writeChannels all channels interested in write and connect - * @param timeout - * timeout in millis @return a set of channels that are ready for operation - * @throws - * SocketException @return int array, each int approve one of the * channel if OK - */ - - public int[] select(FileDescriptor[] readFDs, - FileDescriptor[] writeFDs, long timeout) - throws SocketException { - int countRead = readFDs.length; - int countWrite = writeFDs.length; - int result = 0; - if (0 == countRead + countWrite) { - return (new int[0]); - } - int[] flags = new int[countRead + countWrite]; - - // handle timeout in native - result = selectImpl(readFDs, writeFDs, countRead, countWrite, flags, - timeout); - - if (0 <= result) { - return flags; - } - if (ERRORCODE_SOCKET_TIMEOUT == result) { - return new int[0]; - } - throw new SocketException(); - - } + static native int getSocketFlagsImpl(); - public InetAddress getSocketLocalAddress(FileDescriptor aFD, + public InetAddress getSocketLocalAddress(FileDescriptor fd, boolean preferIPv6Addresses) { - return getSocketLocalAddressImpl(aFD, preferIPv6Addresses); + return getSocketLocalAddressImpl(fd, preferIPv6Addresses); } + static native InetAddress getSocketLocalAddressImpl(FileDescriptor aFD, + boolean preferIPv6Addresses); - /* + /** * Query the IP stack for the local port to which this socket is bound. - * - * @param aFD the socket descriptor @param preferIPv6Addresses address - * preference for nodes that support both IPv4 and IPv6 @return int the - * local port to which the socket is bound + * + * @param aFD + * the socket descriptor + * @param preferIPv6Addresses + * address preference for nodes that support both IPv4 and IPv6 + * @return the local port to which the socket is bound */ public int getSocketLocalPort(FileDescriptor aFD, boolean preferIPv6Addresses) { return getSocketLocalPortImpl(aFD, preferIPv6Addresses); } - /* + static native int getSocketLocalPortImpl(FileDescriptor aFD, + boolean preferIPv6Addresses); + + /** * Query the IP stack for the nominated socket option. - * - * @param aFD the socket descriptor @param opt the socket option type + * + * @param fd + * the socket descriptor + * @param opt + * the socket option type * @return the nominated socket option value - * - * @throws SocketException if the option is invalid + * @throws SocketException + * if the option is invalid */ - public Object getSocketOption(FileDescriptor aFD, int opt) + public Object getSocketOption(FileDescriptor fd, int opt) throws SocketException { - return getSocketOptionImpl(aFD, opt); + return getSocketOptionImpl(fd, opt); } - /* - * Set the nominated socket option in the IP stack. - * - * @param aFD the socket descriptor @param opt the option selector @param - * optVal the nominated option value - * - * @throws SocketException if the option is invalid or cannot be set - */ - public void setSocketOption(FileDescriptor aFD, int opt, Object optVal) - throws SocketException { - setSocketOptionImpl(aFD, opt, optVal); - } + static native Object getSocketOptionImpl(FileDescriptor aFD, int opt) + throws SocketException; - public int getSocketFlags() { - return getSocketFlagsImpl(); + public Channel inheritedChannel() { + return inheritedChannelImpl(); } - /* - * Close the socket in the IP stack. - * - * @param aFD the socket descriptor - */ - public void socketClose(FileDescriptor aFD) throws IOException { - socketCloseImpl(aFD); - } + native Channel inheritedChannelImpl(); - public InetAddress getHostByAddr(byte[] addr) throws UnknownHostException { - return getHostByAddrImpl(addr); - } + // BEGIN android-removed + // public boolean isReachableByICMP(final InetAddress dest, + // InetAddress source, final int ttl, final int timeout) { + // return INETADDR_REACHABLE == isReachableByICMPImpl(dest, source, ttl, + // timeout); + // } - public InetAddress getHostByName(String addr, boolean preferIPv6Addresses) - throws UnknownHostException { - return getHostByNameImpl(addr, preferIPv6Addresses); - } + // native int isReachableByICMPImpl(InetAddress addr, + // InetAddress local, int ttl, int timeout); + // END android-removed - public void setInetAddress(InetAddress sender, byte[] address) { - setInetAddressImpl(sender, address); + public void listenStreamSocket(FileDescriptor aFD, int backlog) + throws SocketException { + listenStreamSocketImpl(aFD, backlog); } - // --------------------------------------------------- - // Native Codes - // --------------------------------------------------- - - static native void createSocketImpl(FileDescriptor fd, - boolean preferIPv4Stack); - - /* - * Allocate a datagram socket in the IP stack. The socket is associated with - * the <code>aFD</code>. - * - * @param aFD the FileDescriptor to associate with the socket @param - * preferIPv4Stack IP stack preference if underlying platform is V4/V6 - * @exception SocketException upon an allocation error - */ - static native void createDatagramSocketImpl(FileDescriptor aFD, - boolean preferIPv4Stack) throws SocketException; - - static native int readSocketImpl(FileDescriptor aFD, byte[] data, - int offset, int count, int timeout) throws IOException; - - static native int readSocketDirectImpl(FileDescriptor aFD, int address, - int offset, int count, int timeout) throws IOException; - - static native int writeSocketImpl(FileDescriptor fd, byte[] data, - int offset, int count) throws IOException; - - static native int writeSocketDirectImpl(FileDescriptor fd, int address, - int offset, int count) throws IOException; - - static native void setNonBlockingImpl(FileDescriptor aFD, - boolean block); - - static native int connectSocketImpl(FileDescriptor aFD, - int trafficClass, InetAddress inetAddress, int port); - - // BEGIN android-changed - static native int connectWithTimeoutSocketImpl( - FileDescriptor aFD, int timeout, int trafficClass, - InetAddress hostname, int port, int step, byte[] context); - // END android-changed - - static native void connectStreamWithTimeoutSocketImpl(FileDescriptor aFD, - int aport, int timeout, int trafficClass, InetAddress inetAddress) - throws IOException; - - static native void socketBindImpl(FileDescriptor aFD, int port, - InetAddress inetAddress) throws SocketException; - static native void listenStreamSocketImpl(FileDescriptor aFD, int backlog) throws SocketException; - static native int availableStreamImpl(FileDescriptor aFD) - throws SocketException; - - static native void acceptSocketImpl(FileDescriptor fdServer, - SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout) - throws IOException; - - static native boolean supportsUrgentDataImpl(FileDescriptor fd); + public void oneTimeInitialization(boolean jcl_supports_ipv6) { + if (!isNetworkInited) { + oneTimeInitializationImpl(jcl_supports_ipv6); + isNetworkInited = true; + } + } - static native void sendUrgentDataImpl(FileDescriptor fd, byte value); + native void oneTimeInitializationImpl (boolean jcl_supports_ipv6); - /* - * Connect the socket to a port and address - * - * @param aFD the FileDescriptor to associate with the socket @param port - * the port to connect to @param trafficClass the traffic Class to be used - * then the connection is made @param inetAddress address to connect to. - * - * @exception SocketException if the connect fails + /** + * Peek on the socket, update <code>sender</code> address and answer the + * sender port. + * + * @param fd + * the socket FileDescriptor + * @param sender + * an InetAddress, to be updated with the sender's address + * @param receiveTimeout + * the maximum length of time the socket should block, reading + * @return the sender port + * + * @throws IOException + * upon an read error or timeout */ - static native void connectDatagramImpl2(FileDescriptor aFD, - int port, int trafficClass, InetAddress inetAddress) - throws SocketException; + public int peekDatagram(FileDescriptor fd, InetAddress sender, + int receiveTimeout) throws IOException { + return peekDatagramImpl(fd, sender, receiveTimeout); + } - /* - * Disconnect the socket to a port and address - * - * @param aFD the FileDescriptor to associate with the socket - * - * @exception SocketException if the disconnect fails - */ - static native void disconnectDatagramImpl(FileDescriptor aFD) - throws SocketException; + static native int peekDatagramImpl(FileDescriptor aFD, + InetAddress sender, int receiveTimeout) throws IOException; - /* - * Allocate a datagram socket in the IP stack. The socket is associated with - * the <code>aFD</code>. - * - * @param aFD the FileDescriptor to associate with the socket @param - * preferIPv4Stack IP stack preference if underlying platform is V4/V6 - * @exception SocketException upon an allocation error + /** + * Read available bytes from the given file descriptor into a byte array. + * + * The read has an optional timeout parameter, which if non-zero is the + * length of time that the read will wait on a select call to see if any + * bytes are available for reading. If the timeout expires the method + * returns zero to indicate no bytes were read. + * + * @param fd + * the socket file descriptor to read + * @param data + * the byte array in which to store the results + * @param offset + * the offset into the byte array in which to start reading the + * results + * @param count + * the maximum number of bytes to read + * @param timeout + * the length of time to wait for the bytes, in milliseconds; or + * zero to indicate no timeout applied. When there is no timeout + * applied the read may block based upon socket options. + * @return number of bytes read, or zero if there were no bytes available + * before the timeout occurred, or -1 to indicate the socket is + * closed + * @throws IOException + * if an underlying socket exception occurred */ + public int read(FileDescriptor fd, byte[] data, int offset, int count, + int timeout) throws IOException { + return readSocketImpl(fd, data, offset, count, timeout); + } - /* - * Bind the socket to the port/localhost in the IP stack. - * - * @param aFD the socket descriptor @param port the option selector @param - * bindToDevice bind the socket to the specified interface @param - * inetAddress address to connect to. @return if bind successful @exception - * SocketException thrown if bind operation fails - */ - static native boolean socketBindImpl2(FileDescriptor aFD, - int port, boolean bindToDevice, InetAddress inetAddress) - throws SocketException; + static native int readSocketImpl(FileDescriptor aFD, byte[] data, + int offset, int count, int timeout) throws IOException; - /* - * Peek on the socket, update <code>sender</code> address and answer the - * sender port. - * - * @param aFD the socket FileDescriptor @param sender an InetAddress, to be - * updated with the sender's address @param receiveTimeout the maximum - * length of time the socket should block, reading @return int the sender - * port - * - * @exception IOException upon an read error or timeout + /** + * Read available bytes from the given file descriptor into OS memory at a + * given address. + * + * @param fd + * the socket file descriptor to read + * @param address + * the address of the memory in which to store the results + * @param count + * the maximum number of bytes to read + * @param timeout + * the length of time to wait for the bytes, in milliseconds + * @return number of bytes read, or zero if there were no bytes available + * before the timeout occurred, or -1 to indicate the socket is + * closed + * @throws IOException + * if an underlying socket exception occurred */ - static native int peekDatagramImpl(FileDescriptor aFD, - InetAddress sender, int receiveTimeout) throws IOException; + public int readDirect(FileDescriptor fd, int address, int offset, int count, + int timeout) throws IOException { + return readSocketDirectImpl(fd, address, offset, count, timeout); + } - /* - * Recieve data on the socket into the specified buffer. The packet fields + static native int readSocketDirectImpl(FileDescriptor aFD, int address, int offset, int count, + int timeout) throws IOException; + + /** + * Receive data on the socket into the specified buffer. The packet fields * <code>data</code> & <code>length</code> are passed in addition to * <code>packet</code> to eliminate the JNI field access calls. - * - * @param aFD the socket FileDescriptor @param packet the DatagramPacket to - * receive into @param data the data buffer of the packet @param offset the - * offset in the data buffer @param length the length of the data buffer in - * the packet @param receiveTimeout the maximum length of time the socket - * should block, reading @param peek indicates to peek at the data @return - * number of data received @exception IOException upon an read error or - * timeout + * + * @param fd + * the socket FileDescriptor + * @param packet + * the DatagramPacket to receive into + * @param data + * the data buffer of the packet + * @param offset + * the offset in the data buffer + * @param length + * the length of the data buffer in the packet + * @param receiveTimeout + * the maximum length of time the socket should block, reading + * @param peek + * indicates to peek at the data + * @return number of data received + * @throws IOException + * upon an read error or timeout */ + public int receiveDatagram(FileDescriptor fd, DatagramPacket packet, + byte[] data, int offset, int length, int receiveTimeout, + boolean peek) throws IOException { + return receiveDatagramImpl(fd, packet, data, offset, length, + receiveTimeout, peek); + } + static native int receiveDatagramImpl(FileDescriptor aFD, DatagramPacket packet, byte[] data, int offset, int length, int receiveTimeout, boolean peek) throws IOException; - + + public int receiveDatagramDirect(FileDescriptor fd, + DatagramPacket packet, int address, int offset, int length, + int receiveTimeout, boolean peek) throws IOException { + return receiveDatagramDirectImpl(fd, packet, address, offset, length, + receiveTimeout, peek); + } + static native int receiveDatagramDirectImpl(FileDescriptor aFD, DatagramPacket packet, int address, int offset, int length, int receiveTimeout, boolean peek) throws IOException; - /* + /** + * Receive at most <code>count</code> bytes into the buffer + * <code>data</code> at the <code>offset</code> on the socket. + * + * @param aFD + * the socket FileDescriptor + * @param data + * the receive buffer + * @param offset + * the offset into the buffer + * @param count + * the max number of bytes to receive + * @param timeout + * the max time the read operation should block waiting for data + * @return the actual number of bytes read + * @throws IOException + * @throws SocketException + * if an error occurs while reading + * @deprecated use {@link #read(FileDescriptor, byte[], int, int, int)} + */ + public int receiveStream(FileDescriptor aFD, byte[] data, + int offset, int count, int timeout) throws IOException { + return receiveStreamImpl(aFD, data, offset, count, timeout); + } + + static native int receiveStreamImpl(FileDescriptor aFD, byte[] data, + int offset, int count, int timeout) throws IOException; + + // BEGIN android-added + /** + * Send <code>count</code> bytes from the buffer <code>data</code> at + * the <code>offset</code>, on the socket. + * + * @param fd + * + * @param data the send buffer @param offset the offset into the buffer + * @param count the number of bytes to receive @return int the actual number + * of bytes sent @throws IOException @exception SocketException if an error + * occurs while writing + */ + public int sendStream(FileDescriptor fd, byte[] data, int offset, int count) + throws IOException { + return sendStreamImpl(fd, data, offset, count); + } + + static native int sendStreamImpl(FileDescriptor fd, byte[] data, + int offset, int count) throws IOException; + // END android-added + + /** * Recieve data on the connected socket into the specified buffer. The - * packet fields <code>data</code> & <code>length</code> are passed in - * addition to <code>packet</code> to eliminate the JNI field access - * calls. - * - * @param aFD the socket FileDescriptor @param packet the DatagramPacket to - * receive into @param data the data buffer of the packet @param offset the - * offset in the data buffer @param length the length of the data buffer in - * the packet @param receiveTimeout the maximum length of time the socket - * should block, reading @param peek indicates to peek at the data @return - * number of data received @exception IOException upon an read error or - * timeout + * packet fields <code>data</code> and <code>length</code> are passed in + * addition to <code>packet</code> to eliminate the JNI field access calls. + * + * @param fd + * the socket FileDescriptor + * @param packet + * the DatagramPacket to receive into + * @param data + * the data buffer of the packet + * @param offset + * the offset in the data buffer + * @param length + * the length of the data buffer in the packet + * @param receiveTimeout + * the maximum length of time the socket should block, reading + * @param peek + * indicates to peek at the data + * @return number of data received + * @throws IOException + * upon an read error or timeout */ + public int recvConnectedDatagram(FileDescriptor fd, + DatagramPacket packet, byte[] data, int offset, int length, + int receiveTimeout, boolean peek) throws IOException { + return recvConnectedDatagramImpl(fd, packet, data, offset, length, + receiveTimeout, peek); + } + static native int recvConnectedDatagramImpl(FileDescriptor aFD, DatagramPacket packet, byte[] data, int offset, int length, int receiveTimeout, boolean peek) throws IOException; - + + public int recvConnectedDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address, + int offset, int length, int receiveTimeout, boolean peek) + throws IOException { + return recvConnectedDatagramDirectImpl(aFD, packet, address, offset, length, receiveTimeout, peek); + } + static native int recvConnectedDatagramDirectImpl(FileDescriptor aFD, DatagramPacket packet, int address, int offset, int length, int receiveTimeout, boolean peek) throws IOException; - /* - * Send the <code>data</code> to the nominated target <code>address</code> - * and <code>port</code>. These values are derived from the - * DatagramPacket to reduce the field calls within JNI. - * - * @param fd the socket FileDescriptor @param data the data buffer of the - * packet @param offset the offset in the data buffer @param length the - * length of the data buffer in the packet @param port the target host port - * @param bindToDevice if bind to device @param trafficClass the traffic - * class to be used when the datagram is sent @param inetAddress address to - * connect to. @return number of data send - * - * @exception IOException upon an read error or timeout + /** + * Select the given file descriptors for read and write operations. + * + * The file descriptors passed in as readFDs will be selected for read-ready + * operations, and those in the writeFDs will be selected for write-ready + * operations. A file descriptor can appear in either or both array, and + * must not be <code>null</code>. If the file descriptor is closed during + * the select the behavior depends upon the underlying OS. + * + * Upon return the result is a single array of length + * <code>readFDs.length</code> + <code>writeFDs.length</code> laid out as + * the result of the select operation on the corresponding file descriptors. + * + * @param readFDs + * all sockets interested in read and accept + * @param writeFDs + * 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. + * @throws SocketException */ - static native int sendDatagramImpl(FileDescriptor fd, - byte[] data, int offset, int length, int port, - boolean bindToDevice, int trafficClass, InetAddress inetAddress) - throws IOException; - - static native int sendDatagramDirectImpl(FileDescriptor fd, - int address, int offset, int length, int port, - boolean bindToDevice, int trafficClass, InetAddress inetAddress) - throws IOException; + public int[] select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs, + long timeout) throws SocketException { + int countRead = readFDs.length; + int countWrite = writeFDs.length; + int result = 0; + if (0 == countRead + countWrite) { + return (new int[0]); + } + int[] flags = new int[countRead + countWrite]; - /* + assert validateFDs(readFDs, writeFDs) : "Invalid file descriptor arrays"; //$NON-NLS-1$ + + // handle timeout in native + result = selectImpl(readFDs, writeFDs, countRead, countWrite, flags, + timeout); + + if (0 <= result) { + return flags; + } + if (ERRORCODE_SOCKET_TIMEOUT == result || + ERRORCODE_SOCKET_INTERRUPTED == result) { + return new int[0]; + } + throw new SocketException(); + } + + static native int selectImpl(FileDescriptor[] readfd, + FileDescriptor[] writefd, int cread, int cwirte, int[] flags, + long timeout); + + /** * Send the <code>data</code> to the address and port to which the was - * connnected and <code>port</code>. - * - * @param fd the socket FileDescriptor @param data the data buffer of the - * packet @param offset the offset in the data buffer @param length the - * length of the data buffer in the packet @param bindToDevice not used, - * current kept in case needed as was the case for sendDatagramImpl @return - * number of data send @exception IOException upon an read error or timeout + * connected and <code>port</code>. + * + * @param fd + * the socket FileDescriptor + * @param data + * the data buffer of the packet + * @param offset + * the offset in the data buffer + * @param length + * the length of the data buffer in the packet + * @param bindToDevice + * not used, current kept in case needed as was the case for + * sendDatagramImpl + * @return number of data send + * @throws IOException + * upon an read error or timeout */ + public int sendConnectedDatagram(FileDescriptor fd, byte[] data, + int offset, int length, boolean bindToDevice) throws IOException { + return sendConnectedDatagramImpl(fd, data, offset, length, bindToDevice); + } + static native int sendConnectedDatagramImpl(FileDescriptor fd, byte[] data, int offset, int length, boolean bindToDevice) throws IOException; - + + public int sendConnectedDatagramDirect(FileDescriptor fd, + int address, int offset, int length, boolean bindToDevice) + throws IOException { + return sendConnectedDatagramDirectImpl(fd, address, offset, length, bindToDevice); + } static native int sendConnectedDatagramDirectImpl(FileDescriptor fd, int address, int offset, int length, boolean bindToDevice) throws IOException; - /* - * Answer the result of attempting to create a server stream socket in the - * IP stack. Any special options required for server sockets will be set by - * this method. - * - * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4 - * @exception SocketException if an error occurs while creating the socket + /** + * Send the <code>data</code> to the nominated target <code>address</code> + * and <code>port</code>. These values are derived from the DatagramPacket + * to reduce the field calls within JNI. + * + * @param fd + * the socket FileDescriptor + * @param data + * the data buffer of the packet + * @param offset + * the offset in the data buffer + * @param length + * the length of the data buffer in the packet + * @param port + * the target host port + * @param bindToDevice + * if bind to device + * @param trafficClass + * the traffic class to be used when the datagram is sent + * @param inetAddress + * address to connect to. + * @return number of data send + * + * @throws IOException + * upon an read error or timeout */ - static native void createServerStreamSocketImpl(FileDescriptor aFD, - boolean preferIPv4Stack) throws SocketException; + public int sendDatagram(FileDescriptor fd, byte[] data, int offset, + int length, int port, boolean bindToDevice, int trafficClass, + InetAddress inetAddress) throws IOException { + return sendDatagramImpl(fd, data, offset, length, port, bindToDevice, + trafficClass, inetAddress); + } - /* - * Answer the result of attempting to create a multicast socket in the IP - * stack. Any special options required for server sockets will be set by - * this method. - * - * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4 - * @exception SocketException if an error occurs while creating the socket - */ - static native void createMulticastSocketImpl(FileDescriptor aFD, - boolean preferIPv4Stack) throws SocketException; + static native int sendDatagramImpl(FileDescriptor fd, byte[] data, int offset, + int length, int port, boolean bindToDevice, int trafficClass, + InetAddress inetAddress) throws IOException; - /* - * Recieve at most <code>count</code> bytes into the buffer <code>data</code> - * at the <code>offset</code> on the socket. - * - * @param aFD the socket FileDescriptor @param data the receive buffer - * @param offset the offset into the buffer @param count the max number of - * bytes to receive @param timeout the max time the read operation should - * block waiting for data @return int the actual number of bytes read - * @throws IOException @exception SocketException if an error occurs while - * reading - */ - static native int receiveStreamImpl(FileDescriptor aFD, byte[] data, - int offset, int count, int timeout) throws IOException; + public int sendDatagram2(FileDescriptor fd, byte[] data, int offset, + int length, int port, InetAddress inetAddress) throws IOException { + return sendDatagramImpl2(fd, data, offset, length, port, inetAddress); + } - /* - * Send <code>count</code> bytes from the buffer <code>data</code> at - * the <code>offset</code>, on the socket. - * - * @param fd - * - * @param data the send buffer @param offset the offset into the buffer - * @param count the number of bytes to receive @return int the actual number - * of bytes sent @throws IOException @exception SocketException if an error - * occurs while writing - */ - static native int sendStreamImpl(FileDescriptor fd, byte[] data, - int offset, int count) throws IOException; + static native int sendDatagramImpl2(FileDescriptor fd, byte[] data, + int offset, int length, int port, InetAddress inetAddress) throws IOException; - private native void shutdownInputImpl(FileDescriptor descriptor) - throws IOException; - private native void shutdownOutputImpl(FileDescriptor descriptor) - throws IOException; + public int sendDatagramDirect(FileDescriptor fd, int address, + int offset, int length, int port, boolean bindToDevice, + int trafficClass, InetAddress inetAddress) throws IOException { + return sendDatagramDirectImpl(fd, address, offset, length, port, bindToDevice, + trafficClass, inetAddress); + } - // BEGIN android-removed - // static native void acceptStreamSocketImpl(FileDescriptor fdServer, - // SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout) - // throws IOException; - // - // static native void createStreamSocketImpl(FileDescriptor aFD, - // boolean preferIPv4Stack) throws SocketException; - // END android-removed + static native int sendDatagramDirectImpl(FileDescriptor fd, int address, + int offset, int length, int port, boolean bindToDevice, + int trafficClass, InetAddress inetAddress) throws IOException; - static native int sendDatagramImpl2(FileDescriptor fd, byte[] data, - int offset, int length, int port, InetAddress inetAddress) - throws IOException; + public void sendUrgentData(FileDescriptor fd, byte value) { + sendUrgentDataImpl(fd, value); + } - static native int selectImpl(FileDescriptor[] readfd, - FileDescriptor[] writefd, int cread, int cwirte, int[] flags, - long timeout); + static native void sendUrgentDataImpl(FileDescriptor fd, byte value); - static native InetAddress getSocketLocalAddressImpl(FileDescriptor aFD, - boolean preferIPv6Addresses); + public void setInetAddress(InetAddress sender, byte[] address) { + setInetAddressImpl(sender, address); + } - /* - * Query the IP stack for the local port to which this socket is bound. - * - * @param aFD the socket descriptor @param preferIPv6Addresses address - * preference for nodes that support both IPv4 and IPv6 @return int the - * local port to which the socket is bound - */ - static native int getSocketLocalPortImpl(FileDescriptor aFD, - boolean preferIPv6Addresses); + native void setInetAddressImpl(InetAddress sender, byte[] address); - /* - * Query the IP stack for the nominated socket option. - * - * @param aFD the socket descriptor @param opt the socket option type - * @return the nominated socket option value - * - * @throws SocketException if the option is invalid - */ - static native Object getSocketOptionImpl(FileDescriptor aFD, int opt) - throws SocketException; + public void setNonBlocking(FileDescriptor fd, boolean block) + throws IOException { + setNonBlockingImpl(fd, block); + } - /* + static native void setNonBlockingImpl(FileDescriptor aFD, boolean block); + + /** * Set the nominated socket option in the IP stack. - * - * @param aFD the socket descriptor @param opt the option selector @param - * optVal the nominated option value - * - * @throws SocketException if the option is invalid or cannot be set + * + * @param aFD + * the socket descriptor @param opt the option selector @param + * optVal the nominated option value + * + * @throws SocketException + * if the option is invalid or cannot be set */ + public void setSocketOption(FileDescriptor aFD, int opt, + Object optVal) throws SocketException { + setSocketOptionImpl(aFD, opt, optVal); + } + static native void setSocketOptionImpl(FileDescriptor aFD, int opt, Object optVal) throws SocketException; - static native int getSocketFlagsImpl(); + public void shutdownInput(FileDescriptor descriptor) throws IOException { + shutdownInputImpl(descriptor); + } - /* + private native void shutdownInputImpl(FileDescriptor descriptor) + throws IOException; + + public void shutdownOutput(FileDescriptor fd) throws IOException { + shutdownOutputImpl(fd); + } + + private native void shutdownOutputImpl(FileDescriptor descriptor) + throws IOException; + /** * Close the socket in the IP stack. - * - * @param aFD the socket descriptor + * + * @param fd + * the socket descriptor */ - static native void socketCloseImpl(FileDescriptor aFD); + public void socketClose(FileDescriptor fd) throws IOException { + socketCloseImpl(fd); + } - static native InetAddress getHostByAddrImpl(byte[] addr) - throws UnknownHostException; + static native void socketCloseImpl(FileDescriptor fD); - static native InetAddress getHostByNameImpl(String addr, - boolean preferIPv6Addresses) throws UnknownHostException; + public boolean supportsUrgentData(FileDescriptor fd) { + return supportsUrgentDataImpl(fd); + } - native void setInetAddressImpl(InetAddress sender, byte[] address); + static native boolean supportsUrgentDataImpl(FileDescriptor fd); - // BEGIN android-removed - // native int isReachableByICMPImpl(InetAddress addr, InetAddress local, - // int ttl, int timeout); - // END android-removed - - native Channel inheritedChannelImpl(); + /* + * Used to check if the file descriptor arrays are valid before passing them + * into the select native call. + */ + private boolean validateFDs(FileDescriptor[] readFDs, + FileDescriptor[] writeFDs) { + for (FileDescriptor fd : readFDs) { + // Also checks fd not null + if (!fd.valid()) { + return false; + } + } + for (FileDescriptor fd : writeFDs) { + if (!fd.valid()) { + return false; + } + } + return true; + } - public Channel inheritedChannel() { - return inheritedChannelImpl(); + /** + * Write bytes from a byte array to a socket. + * + * @param fd + * the socket on which to write the bytes + * @param data + * the array containing the bytes to be written + * @param offset + * the offset in the byte array from which to take the bytes + * @param count + * the maximum number of bytes to be written. Callers are trusted + * not to send values of length+count that are larger than + * data.length + * @return the actual number of bytes written, which will be between zero + * and count + * @throws IOException + * if there is an underlying socket problem + */ + public int write(FileDescriptor fd, byte[] data, int offset, int count) + throws IOException { + return writeSocketImpl(fd, data, offset, count); } - - public void oneTimeInitialization(boolean jcl_supports_ipv6){ - if (!isNetworkInited){ - oneTimeInitializationImpl(jcl_supports_ipv6); - isNetworkInited = true; - } + + static native int writeSocketImpl(FileDescriptor fd, byte[] data, int offset, + int count) throws IOException; + + + /** + * Write bytes from the given address to a socket. + * + * @param fd + * the socket on which to write the bytes + * @param address + * the start address of the bytes to be written + * @param count + * the maximum number of bytes to be written + * @return the actual number of bytes written, which will be between zero + * and count + * @throws IOException + * if there is an underlying socket problem + */ + public int writeDirect(FileDescriptor fd, int address, int offset, int count) + throws IOException { + return writeSocketDirectImpl(fd, address, offset, count); } - - native void oneTimeInitializationImpl (boolean jcl_supports_ipv6); + + static native int writeSocketDirectImpl(FileDescriptor fd, int address, int offset, int count) + throws IOException; } diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java b/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java index 68d2515..ab71a00 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java @@ -21,25 +21,33 @@ import dalvik.system.VMStack; // END android-changed /** - * Platform - * + * The Platform class gives access to the low-level underlying capabilities of + * the operating system. + * + * The platform is structured into operations on the process heap memory, + * network subsystem, and file system through different OS components. + * + * OS components are 'dangerous' in that they pass through the calls and + * arguments to the OS with very little checking, and as such may cause fatal + * exceptions in the runtime. Access to the OS components is restricted to + * trusted code running on the system classpath. + * + * @see IFileSystem + * @see INetworkSystem + * @see IMemorySystem */ public class Platform { - static final IAdapterManager ADAPTER_MANAGER = new AdapterManager(); + static final IFileSystem FILE_SYSTEM = OSFileSystem.getOSFileSystem(); - static final IFileSystem FILE_SYSTEM = OSComponentFactory.getFileSystem(); + static final IMemorySystem MEMORY_SYSTEM = OSMemory.getOSMemory(); - static final IMemorySystem MEMORY_SYSTEM = OSComponentFactory - .getMemorySystem(); - - static final INetworkSystem NETWORK_SYSTEM = OSComponentFactory - .getNetworkSystem(); - - public static IAdapterManager getAdapterManager() { - return ADAPTER_MANAGER; - } + static final INetworkSystem NETWORK_SYSTEM = OSNetworkSystem.getOSNetworkSystem(); + /** + * Checks to ensure that whoever is asking for the OS component is running + * on the system classpath. + */ private static final void accessCheck() { // BEGIN android-changed if (VMStack.getCallingClassLoader() != null) { @@ -48,16 +56,31 @@ public class Platform { // END android-changed } + /** + * Answers the instance that interacts directly with the OS file system. + * + * @return a low-level file system interface. + */ public static IFileSystem getFileSystem() { accessCheck(); return FILE_SYSTEM; } + /** + * Answers the instance that interacts directly with the OS memory system. + * + * @return a low-level memory system interface. + */ public static IMemorySystem getMemorySystem() { accessCheck(); return MEMORY_SYSTEM; } + /** + * Answers the instance that interacts directly with the OS network system. + * + * @return a low-level network system interface. + */ public static INetworkSystem getNetworkSystem() { accessCheck(); return NETWORK_SYSTEM; diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java b/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java index e897506..3692819 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java @@ -20,17 +20,18 @@ import java.lang.ref.Reference; final class RuntimeMemorySpy extends AbstractMemorySpy { - public RuntimeMemorySpy() { - super(); - } + public RuntimeMemorySpy() { + super(); + } + + public void alloc(PlatformAddress address) { + // Pay a tax on the allocation to see if there are any frees pending. + Reference ref = notifyQueue.poll(); // non-blocking check + while (ref != null) { + orphanedMemory(ref); + ref = notifyQueue.poll(); + } - public void alloc(PlatformAddress address) { super.alloc(address); - // Pay a tax on the allocation to see if there are any frees pending. - Reference ref = notifyQueue.poll(); // non-blocking check - while (ref != null) { - orphanedMemory(ref); - ref = notifyQueue.poll(); - } - } + } } diff --git a/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java b/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java new file mode 100644 index 0000000..ac3275e --- /dev/null +++ b/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java @@ -0,0 +1,80 @@ +/* + * 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.util; + + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; + +// BEGIN android-changed +/** + * Implements the actual DeleteOnExit mechanism. Is registered as a shutdown + * hook in the Runtime, once it is actually being used. + */ +public class DeleteOnExit extends Thread { + + /** + * Our singleton instance. + */ + private static DeleteOnExit instance; + + /** + * Our list of files scheduled for deletion. + */ + private ArrayList<String> files = new ArrayList<String>(); + + /** + * Returns our singleton instance, creating it if necessary. + */ + public static synchronized DeleteOnExit getInstance() { + if (instance == null) { + instance = new DeleteOnExit(); + Runtime.getRuntime().addShutdownHook(instance); + } + + return instance; + } + + /** + * Schedules a file for deletion. + * + * @param filename The file to delete. + */ + public void addFile(String filename) { + synchronized(files) { + if (!files.contains(filename)) { + files.add(filename); + } + } + } + + /** + * Does the actual work. Note we (a) first sort the files lexicographically + * and then (b) delete them in reverse order. This is to make sure files + * get deleted before their parent directories. + */ + @Override + public void run() { + Collections.sort(files); + for (int i = files.size() - 1; i >= 0; i--) { + new File(files.get(i)).delete(); + } + } +} +// END android-changed diff --git a/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java b/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java new file mode 100644 index 0000000..0ff073c --- /dev/null +++ b/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java @@ -0,0 +1,57 @@ +/* + * 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.util; + +import java.io.ByteArrayInputStream; + +/** + * The extension of <code>ByteArrayInputStream</code> which exposes an + * underlying buffer. + */ +public class ExposedByteArrayInputStream extends ByteArrayInputStream { + + /** + * @see java.io.ByteArrayInputStream(byte[]) + */ + public ExposedByteArrayInputStream(byte buf[]) { + super(buf); + } + + /** + * @see java.io.ByteArrayInputStream(byte[], int, int) + */ + public ExposedByteArrayInputStream(byte buf[], int offset, int length) { + super(buf, offset, length); + } + + /** + * Reads the whole stream and returns the stream snapshot. + */ + public synchronized byte[] expose() { + if (pos == 0 && count == buf.length) { + skip(count); + return buf; + } + + final int available = available(); + final byte[] buffer = new byte[available]; + System.arraycopy(buf, pos, buffer, 0, available); + skip(available); + return buffer; + } +} diff --git a/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties b/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties index bc1688f..c740ae9 100644 --- a/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties +++ b/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties @@ -61,8 +61,8 @@ K0045=Attempted to set a negative SoLinger K0046=Local port declared out of range K0047=buffer is null K0048=Invalid action specified\: {0} -K0049=MinPort is greater than MaxPort -K004a=Invalid port number specified +K0049=MinPort is greater than MaxPort\: {0} +K004a=Invalid port number specified\: {0} K004b=Attempt to set factory more than once. K004c=Package is sealed K004d=Does not support writing to the input stream @@ -288,6 +288,7 @@ K034c=proxy should not be null K034d=method has not been implemented yet K034e=Build rules empty K0351=format is null +K0352=package is sealed KA000=Line too long KA001=Argument must not be null KA002=Unshared read of back reference @@ -322,3 +323,5 @@ KA024=One of urls is null KA025=Method has not been implemented 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} diff --git a/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java b/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java index 820de0f..642d309 100644 --- a/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java +++ b/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java @@ -17,8 +17,6 @@ package org.apache.harmony.luni.util; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Used to parse a string and return either a single or double precision diff --git a/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java b/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java index 93bd9da..8072165 100644 --- a/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java +++ b/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java @@ -304,13 +304,13 @@ final class HexStringParser { private int getOffset(String strIntegerPart, String strDecimalPart) { strIntegerPart = strIntegerPart.replaceFirst("^0+", ""); //$NON-NLS-1$ //$NON-NLS-2$ - //If the Interger part is a nonzero number. + //If the Integer part is a nonzero number. if (strIntegerPart.length() != 0) { String leadingNumber = strIntegerPart.substring(0, 1); return (strIntegerPart.length() - 1) * 4 + countBitsLength(Long.parseLong(leadingNumber,HEX_RADIX)) - 1; } - //If the Interger part is a zero number. + //If the Integer part is a zero number. int i; for (i = 0; i < strDecimalPart.length() && strDecimalPart.charAt(i) == '0'; i++); if (i == strDecimalPart.length()) { diff --git a/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java b/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java new file mode 100644 index 0000000..f32f976 --- /dev/null +++ b/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java @@ -0,0 +1,170 @@ +/* + * 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.util; + +import java.util.HashMap; + +public class HistoricalNamesUtil { + private static HashMap<String, String> historicalNames = new HashMap<String, String>(); + + static { + historicalNames.put("Big5-HKSCS", "Big5_HKSCS"); + historicalNames.put("EUC-JP", "EUC_JP"); + historicalNames.put("EUC-KR", "EUC_KR"); + historicalNames.put("GB2312", "EUC_CN"); + historicalNames.put("IBM-Thai", "Cp838"); + historicalNames.put("IBM00858", "Cp858"); + historicalNames.put("IBM01140", "Cp1140"); + historicalNames.put("IBM01141", "Cp1141"); + historicalNames.put("IBM01142", "Cp1142"); + historicalNames.put("IBM01143", "Cp1143"); + historicalNames.put("IBM01144", "Cp1144"); + historicalNames.put("IBM01145", "Cp1145"); + historicalNames.put("IBM01146", "Cp1146"); + historicalNames.put("IBM01147", "Cp1147"); + historicalNames.put("IBM01148", "Cp1148"); + historicalNames.put("IBM01149", "Cp1149"); + historicalNames.put("IBM037", "Cp037"); + historicalNames.put("IBM1026", "Cp1026"); + historicalNames.put("IBM1047", "Cp1047"); + historicalNames.put("IBM273", "Cp273"); + historicalNames.put("IBM277", "Cp277"); + historicalNames.put("IBM278", "Cp278"); + historicalNames.put("IBM280", "Cp280"); + historicalNames.put("IBM284", "Cp284"); + historicalNames.put("IBM285", "Cp285"); + historicalNames.put("IBM297", "Cp297"); + historicalNames.put("IBM420", "Cp420"); + historicalNames.put("IBM424", "Cp424"); + historicalNames.put("IBM437", "Cp437"); + historicalNames.put("IBM500", "Cp500"); + historicalNames.put("IBM775", "Cp775"); + historicalNames.put("IBM850", "Cp850"); + historicalNames.put("IBM852", "Cp852"); + historicalNames.put("IBM855", "Cp855"); + historicalNames.put("IBM857", "Cp857"); + historicalNames.put("IBM860", "Cp860"); + historicalNames.put("IBM861", "Cp861"); + historicalNames.put("IBM862", "Cp862"); + historicalNames.put("IBM863", "Cp863"); + historicalNames.put("IBM864", "Cp864"); + historicalNames.put("IBM865", "Cp865"); + historicalNames.put("IBM866", "Cp866"); + historicalNames.put("IBM868", "Cp868"); + historicalNames.put("IBM869", "Cp869"); + historicalNames.put("IBM870", "Cp870"); + historicalNames.put("IBM871", "Cp871"); + historicalNames.put("IBM918", "Cp918"); + historicalNames.put("ISO-2022-CN", "ISO2022CN"); + historicalNames.put("ISO-2022-JP", "ISO2022JP"); + historicalNames.put("ISO-2022-KR", "ISO2022KR"); + historicalNames.put("ISO-8859-1", "ISO8859_1"); + historicalNames.put("ISO-8859-13", "ISO8859_13"); + historicalNames.put("ISO-8859-15", "ISO8859_15"); + historicalNames.put("ISO-8859-2", "ISO8859_2"); + historicalNames.put("ISO-8859-3", "ISO8859_3"); + historicalNames.put("ISO-8859-4", "ISO8859_4"); + historicalNames.put("ISO-8859-5", "ISO8859_5"); + historicalNames.put("ISO-8859-6", "ISO8859_6"); + historicalNames.put("ISO-8859-7", "ISO8859_7"); + historicalNames.put("ISO-8859-8", "ISO8859_8"); + historicalNames.put("ISO-8859-9", "ISO8859_9"); + historicalNames.put("KOI8-R", "KOI8_R"); + historicalNames.put("Shift_JIS", "SJIS"); + historicalNames.put("TIS-620", "TIS620"); + historicalNames.put("US-ASCII", "ASCII"); + historicalNames.put("UTF-16BE", "UnicodeBigUnmarked"); + historicalNames.put("UTF-16LE", "UnicodeLittleUnmarked"); + historicalNames.put("UTF-8", "UTF8"); + historicalNames.put("windows-1250", "Cp1250"); + historicalNames.put("windows-1251", "Cp1251"); + historicalNames.put("windows-1252", "Cp1252"); + historicalNames.put("windows-1253", "Cp1253"); + historicalNames.put("windows-1254", "Cp1254"); + historicalNames.put("windows-1255", "Cp1255"); + historicalNames.put("windows-1256", "Cp1256"); + historicalNames.put("windows-1257", "Cp1257"); + historicalNames.put("windows-1258", "Cp1258"); + historicalNames.put("windows-31j", "MS932"); + historicalNames.put("x-Big5-Solaris", "Big5_Solaris"); + historicalNames.put("x-euc-jp-linux", "EUC_JP_LINUX"); + historicalNames.put("x-EUC-TW", "EUC_TW"); + historicalNames.put("x-eucJP-Open", "EUC_JP_Solaris"); + historicalNames.put("x-IBM1006", "Cp1006"); + historicalNames.put("x-IBM1025", "Cp1025"); + historicalNames.put("x-IBM1046", "Cp1046"); + historicalNames.put("x-IBM1097", "Cp1097"); + historicalNames.put("x-IBM1098", "Cp1098"); + historicalNames.put("x-IBM1112", "Cp1112"); + historicalNames.put("x-IBM1122", "Cp1122"); + historicalNames.put("x-IBM1123", "Cp1123"); + historicalNames.put("x-IBM1124", "Cp1124"); + historicalNames.put("x-IBM1381", "Cp1381"); + historicalNames.put("x-IBM1383", "Cp1383"); + historicalNames.put("x-IBM33722", "Cp33722"); + historicalNames.put("x-IBM737", "Cp737"); + historicalNames.put("x-IBM856", "Cp856"); + historicalNames.put("x-IBM874", "Cp874"); + historicalNames.put("x-IBM875", "Cp875"); + historicalNames.put("x-IBM921", "Cp921"); + historicalNames.put("x-IBM922", "Cp922"); + historicalNames.put("x-IBM930", "Cp930"); + historicalNames.put("x-IBM933", "Cp933"); + historicalNames.put("x-IBM935", "Cp935"); + historicalNames.put("x-IBM937", "Cp937"); + historicalNames.put("x-IBM939", "Cp939"); + historicalNames.put("x-IBM942", "Cp942"); + historicalNames.put("x-IBM942C", "Cp942C"); + historicalNames.put("x-IBM943", "Cp943"); + historicalNames.put("x-IBM943C", "Cp943C"); + historicalNames.put("x-IBM948", "Cp948"); + historicalNames.put("x-IBM949", "Cp949"); + historicalNames.put("x-IBM949C", "Cp949C"); + historicalNames.put("x-IBM950", "Cp950"); + historicalNames.put("x-IBM964", "Cp964"); + historicalNames.put("x-IBM970", "Cp970"); + historicalNames.put("x-ISCII91", "ISCII91"); + historicalNames.put("x-ISO-2022-CN-CNS", "ISO2022CN"); + historicalNames.put("x-ISO-2022-CN-GB", "ISO2022CN"); + historicalNames.put("x-JISAutoDetect", "JISAutoDetect"); + historicalNames.put("x-MacArabic", "MacArabic"); + historicalNames.put("x-MacCentralEurope", "MacCentralEurope"); + historicalNames.put("x-MacCroatian", "MacCroatian"); + historicalNames.put("x-MacCyrillic", "MacCyrillic"); + historicalNames.put("x-MacDingbat", "MacDingbat"); + historicalNames.put("x-MacGreek", "MacGreek"); + historicalNames.put("x-MacHebrew", "MacHebrew"); + historicalNames.put("x-MacIceland", "MacIceland"); + historicalNames.put("x-MacRoman", "MacRoman"); + historicalNames.put("x-MacRomania", "MacRomania"); + historicalNames.put("x-MacSymbol", "MacSymbol"); + historicalNames.put("x-MacThai", "MacThai"); + historicalNames.put("x-MacTurkish", "MacTurkish"); + historicalNames.put("x-MacUkraine", "MacUkraine"); + historicalNames.put("x-MS950-HKSCS", "MS950_HKSCS"); + historicalNames.put("x-mswin-936", "MS936"); + historicalNames.put("x-PCK", "PCK"); + historicalNames.put("x-windows-874", "MS874"); + historicalNames.put("x-windows-949", "MS949"); + historicalNames.put("x-windows-950", "MS950"); + } + + public static String getHistoricalName(String name) { + return (!historicalNames.containsKey(name) ? name : historicalNames + .get(name)); + } +} diff --git a/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java b/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java index 8c8257b..d8b261d 100644 --- a/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java +++ b/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java @@ -24,28 +24,28 @@ import java.util.StringTokenizer; */ public class Inet6Util { - /** - * Creates an byte[] based on an ipAddressString. No error handling is - * performed here. - */ - public static byte[] createByteArrayFromIPAddressString( - String ipAddressString) { - - if (isValidIPV4Address(ipAddressString)) { + /** + * Creates an byte[] based on an ipAddressString. No error handling is + * performed here. + */ + public static byte[] createByteArrayFromIPAddressString( + String ipAddressString) { + + if (isValidIPV4Address(ipAddressString)) { StringTokenizer tokenizer = new StringTokenizer(ipAddressString, "."); - String token = ""; - int tempInt = 0; - byte[] byteAddress = new byte[4]; - for (int i = 0; i < 4; i++) { - token = tokenizer.nextToken(); - tempInt = Integer.parseInt(token); - byteAddress[i] = (byte) tempInt; - } - - return byteAddress; - } - - if (ipAddressString.charAt(0) == '[') { + String token = ""; + int tempInt = 0; + byte[] byteAddress = new byte[4]; + for (int i = 0; i < 4; i++) { + token = tokenizer.nextToken(); + tempInt = Integer.parseInt(token); + byteAddress[i] = (byte) tempInt; + } + + return byteAddress; + } + + if (ipAddressString.charAt(0) == '[') { ipAddressString = ipAddressString.substring(1, ipAddressString.length() - 1); } @@ -63,105 +63,105 @@ public class Inet6Util { * or decimal list. In the case where we hit a :: we will save the index * of the hexStrings so we can add zeros in to fill out the string */ - while (tokenizer.hasMoreTokens()) { - prevToken = token; - token = tokenizer.nextToken(); - - if (token.equals(":")) { - if (prevToken.equals(":")) { - doubleColonIndex = hexStrings.size(); - } else if (!prevToken.equals("")) { - hexStrings.add(prevToken); - } - } else if (token.equals(".")) { - decStrings.add(prevToken); - } - } - - if (prevToken.equals(":")) { - if (token.equals(":")) { - doubleColonIndex = hexStrings.size(); - } else { - hexStrings.add(token); - } - } else if (prevToken.equals(".")) { - decStrings.add(token); - } - - // figure out how many hexStrings we should have - // also check if it is a IPv4 address - int hexStringsLength = 8; - - // If we have an IPv4 address tagged on at the end, subtract - // 4 bytes, or 2 hex words from the total - if (decStrings.size() > 0) { - hexStringsLength -= 2; - } - - // if we hit a double Colon add the appropriate hex strings - if (doubleColonIndex != -1) { - int numberToInsert = hexStringsLength - hexStrings.size(); - for (int i = 0; i < numberToInsert; i++) { - hexStrings.add(doubleColonIndex, "0"); - } - } - - byte ipByteArray[] = new byte[16]; - - // Finally convert these strings to bytes... - for (int i = 0; i < hexStrings.size(); i++) { - convertToBytes(hexStrings.get(i), ipByteArray, i * 2); - } - - // Now if there are any decimal values, we know where they go... - for (int i = 0; i < decStrings.size(); i++) { + while (tokenizer.hasMoreTokens()) { + prevToken = token; + token = tokenizer.nextToken(); + + if (token.equals(":")) { + if (prevToken.equals(":")) { + doubleColonIndex = hexStrings.size(); + } else if (!prevToken.equals("")) { + hexStrings.add(prevToken); + } + } else if (token.equals(".")) { + decStrings.add(prevToken); + } + } + + if (prevToken.equals(":")) { + if (token.equals(":")) { + doubleColonIndex = hexStrings.size(); + } else { + hexStrings.add(token); + } + } else if (prevToken.equals(".")) { + decStrings.add(token); + } + + // figure out how many hexStrings we should have + // also check if it is a IPv4 address + int hexStringsLength = 8; + + // If we have an IPv4 address tagged on at the end, subtract + // 4 bytes, or 2 hex words from the total + if (decStrings.size() > 0) { + hexStringsLength -= 2; + } + + // if we hit a double Colon add the appropriate hex strings + if (doubleColonIndex != -1) { + int numberToInsert = hexStringsLength - hexStrings.size(); + for (int i = 0; i < numberToInsert; i++) { + hexStrings.add(doubleColonIndex, "0"); + } + } + + byte ipByteArray[] = new byte[16]; + + // Finally convert these strings to bytes... + for (int i = 0; i < hexStrings.size(); i++) { + convertToBytes(hexStrings.get(i), ipByteArray, i * 2); + } + + // Now if there are any decimal values, we know where they go... + for (int i = 0; i < decStrings.size(); i++) { ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings.get(i)) & 255); } - // now check to see if this guy is actually and IPv4 address - // an ipV4 address is ::FFFF:d.d.d.d - boolean ipV4 = true; - for (int i = 0; i < 10; i++) { - if (ipByteArray[i] != 0) { - ipV4 = false; - break; - } - } + // now check to see if this guy is actually and IPv4 address + // an ipV4 address is ::FFFF:d.d.d.d + boolean ipV4 = true; + for (int i = 0; i < 10; i++) { + if (ipByteArray[i] != 0) { + ipV4 = false; + break; + } + } - if (ipByteArray[10] != -1 || ipByteArray[11] != -1) { - ipV4 = false; - } + if (ipByteArray[10] != -1 || ipByteArray[11] != -1) { + ipV4 = false; + } - if (ipV4) { - byte ipv4ByteArray[] = new byte[4]; - for (int i = 0; i < 4; i++) { - ipv4ByteArray[i] = ipByteArray[i + 12]; - } - return ipv4ByteArray; - } - - return ipByteArray; + if (ipV4) { + byte ipv4ByteArray[] = new byte[4]; + for (int i = 0; i < 4; i++) { + ipv4ByteArray[i] = ipByteArray[i + 12]; + } + return ipv4ByteArray; + } - } + return ipByteArray; + + } // BEGIN android-changed static char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; // END android-changed - public static String createIPAddrStringFromByteArray(byte ipByteArray[]) { - if (ipByteArray.length == 4) { - return addressToString(bytesToInt(ipByteArray, 0)); - } - - if (ipByteArray.length == 16) { - if (isIPv4MappedAddress(ipByteArray)) { - byte ipv4ByteArray[] = new byte[4]; - for (int i = 0; i < 4; i++) { - ipv4ByteArray[i] = ipByteArray[i + 12]; - } - return addressToString(bytesToInt(ipv4ByteArray, 0)); - } + public static String createIPAddrStringFromByteArray(byte ipByteArray[]) { + if (ipByteArray.length == 4) { + return addressToString(bytesToInt(ipByteArray, 0)); + } + + if (ipByteArray.length == 16) { + if (isIPv4MappedAddress(ipByteArray)) { + byte ipv4ByteArray[] = new byte[4]; + for (int i = 0; i < 4; i++) { + ipv4ByteArray[i] = ipByteArray[i + 12]; + } + return addressToString(bytesToInt(ipv4ByteArray, 0)); + } StringBuilder buffer = new StringBuilder(); // BEGIN android-changed for (int i = 0; i < 8; i++) { // ipByteArray.length / 2 @@ -189,131 +189,129 @@ public class Inet6Util { } // END android-changed return buffer.toString(); - } - return null; - } - - /** Converts a 4 character hex word into a 2 byte word equivalent */ - public static void convertToBytes(String hexWord, byte ipByteArray[], - int byteIndex) { - - int hexWordLength = hexWord.length(); - int hexWordIndex = 0; - ipByteArray[byteIndex] = 0; - ipByteArray[byteIndex + 1] = 0; - int charValue; - - // high order 4 bits of first byte - if (hexWordLength > 3) { - charValue = getIntValue(hexWord.charAt(hexWordIndex++)); - ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | (charValue << 4)); - } - - // low order 4 bits of the first byte - if (hexWordLength > 2) { - charValue = getIntValue(hexWord.charAt(hexWordIndex++)); - ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | charValue); - } - - // high order 4 bits of second byte - if (hexWordLength > 1) { - charValue = getIntValue(hexWord.charAt(hexWordIndex++)); - ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | (charValue << 4)); - } - - // low order 4 bits of the first byte - charValue = getIntValue(hexWord.charAt(hexWordIndex)); - ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | charValue & 15); - } - - static int getIntValue(char c) { - - switch (c) { - case '0': - return 0; - case '1': - return 1; - case '2': - return 2; - case '3': - return 3; - case '4': - return 4; - case '5': - return 5; - case '6': - return 6; - case '7': - return 7; - case '8': - return 8; - case '9': - return 9; - } - - c = Character.toLowerCase(c); - switch (c) { - case 'a': - return 10; - case 'b': - return 11; - case 'c': - return 12; - case 'd': - return 13; - case 'e': - return 14; - case 'f': - return 15; - } - return 0; - } - - private static boolean isIPv4MappedAddress(byte ipAddress[]) { - - // Check if the address matches ::FFFF:d.d.d.d - // The first 10 bytes are 0. The next to are -1 (FF). - // The last 4 bytes are varied. - for (int i = 0; i < 10; i++) { - if (ipAddress[i] != 0) { - return false; - } - } - - if (ipAddress[10] != -1 || ipAddress[11] != -1) { - return false; - } - - return true; - - } - - /** - * Takes the byte array and creates an integer out of four bytes starting at - * start as the high-order byte. This method makes no checks on the validity - * of the parameters. - */ - public static int bytesToInt(byte bytes[], int start) { - // First mask the byte with 255, as when a negative - // signed byte converts to an integer, it has bits - // on in the first 3 bytes, we are only concerned - // about the right-most 8 bits. - // Then shift the rightmost byte to align with its - // position in the integer. - int value = ((bytes[start + 3] & 255)) - | ((bytes[start + 2] & 255) << 8) - | ((bytes[start + 1] & 255) << 16) - | ((bytes[start] & 255) << 24); - return value; - } - - public static String addressToString(int value) { - return ((value >> 24) & 0xff) + "." + ((value >> 16) & 0xff) + "." - + ((value >> 8) & 0xff) + "." + (value & 0xff); - } + } + return null; + } + + /** Converts a 4 character hex word into a 2 byte word equivalent */ + public static void convertToBytes(String hexWord, byte ipByteArray[], + int byteIndex) { + + int hexWordLength = hexWord.length(); + int hexWordIndex = 0; + ipByteArray[byteIndex] = 0; + ipByteArray[byteIndex + 1] = 0; + int charValue; + + // high order 4 bits of first byte + if (hexWordLength > 3) { + charValue = getIntValue(hexWord.charAt(hexWordIndex++)); + ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | (charValue << 4)); + } + + // low order 4 bits of the first byte + if (hexWordLength > 2) { + charValue = getIntValue(hexWord.charAt(hexWordIndex++)); + ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | charValue); + } + + // high order 4 bits of second byte + if (hexWordLength > 1) { + charValue = getIntValue(hexWord.charAt(hexWordIndex++)); + ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | (charValue << 4)); + } + + // low order 4 bits of the first byte + charValue = getIntValue(hexWord.charAt(hexWordIndex)); + ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | charValue & 15); + } + + static int getIntValue(char c) { + + switch (c) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + } + + c = Character.toLowerCase(c); + switch (c) { + case 'a': + return 10; + case 'b': + return 11; + case 'c': + return 12; + case 'd': + return 13; + case 'e': + return 14; + case 'f': + return 15; + } + return 0; + } + + private static boolean isIPv4MappedAddress(byte ipAddress[]) { + + // Check if the address matches ::FFFF:d.d.d.d + // The first 10 bytes are 0. The next to are -1 (FF). + // The last 4 bytes are varied. + for (int i = 0; i < 10; i++) { + if (ipAddress[i] != 0) { + return false; + } + } + + if (ipAddress[10] != -1 || ipAddress[11] != -1) { + return false; + } + + return true; + + } + + /** + * Takes the byte array and creates an integer out of four bytes starting at + * start as the high-order byte. This method makes no checks on the validity + * of the parameters. + */ + public static int bytesToInt(byte bytes[], int start) { + // First mask the byte with 255, as when a negative + // signed byte converts to an integer, it has bits + // on in the first 3 bytes, we are only concerned + // about the right-most 8 bits. + // Then shift the rightmost byte to align with its + // position in the integer. + int value = ((bytes[start + 3] & 255)) + | ((bytes[start + 2] & 255) << 8) + | ((bytes[start + 1] & 255) << 16) + | ((bytes[start] & 255) << 24); + return value; + } + + public static String addressToString(int value) { + return ((value >> 24) & 0xff) + "." + ((value >> 16) & 0xff) + "." + + ((value >> 8) & 0xff) + "." + (value & 0xff); + } - // BEGIN android-added - // copied from a newer version of harmony public static boolean isIP6AddressInFullForm(String ipAddress) { if (isValidIP6Address(ipAddress)) { int doubleColonIndex = ipAddress.indexOf("::"); @@ -325,215 +323,214 @@ public class Inet6Util { } return false; } - // END android-added - - public static boolean isValidIP6Address(String ipAddress) { - int length = ipAddress.length(); - boolean doubleColon = false; - int numberOfColons = 0; - int numberOfPeriods = 0; - int numberOfPercent = 0; - String word = ""; - char c = 0; - char prevChar = 0; - int offset = 0; // offset for [] IP addresses - - if (length < 2) { + + public static boolean isValidIP6Address(String ipAddress) { + int length = ipAddress.length(); + boolean doubleColon = false; + int numberOfColons = 0; + int numberOfPeriods = 0; + int numberOfPercent = 0; + String word = ""; + char c = 0; + char prevChar = 0; + int offset = 0; // offset for [] IP addresses + + if (length < 2) { return false; } - for (int i = 0; i < length; i++) { - prevChar = c; - c = ipAddress.charAt(i); - switch (c) { + for (int i = 0; i < length; i++) { + prevChar = c; + c = ipAddress.charAt(i); + switch (c) { - // case for an open bracket [x:x:x:...x] - case '[': - if (i != 0) { + // case for an open bracket [x:x:x:...x] + case '[': + if (i != 0) { return false; // must be first character } - if (ipAddress.charAt(length - 1) != ']') { + if (ipAddress.charAt(length - 1) != ']') { return false; // must have a close ] } - offset = 1; - if (length < 4) { + offset = 1; + if (length < 4) { return false; } - break; + break; - // case for a closed bracket at end of IP [x:x:x:...x] - case ']': - if (i != length - 1) { + // case for a closed bracket at end of IP [x:x:x:...x] + case ']': + if (i != length - 1) { return false; // must be last character } - if (ipAddress.charAt(0) != '[') { + if (ipAddress.charAt(0) != '[') { return false; // must have a open [ } - break; + break; - // case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d - case '.': - numberOfPeriods++; - if (numberOfPeriods > 3) { + // case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d + case '.': + numberOfPeriods++; + if (numberOfPeriods > 3) { return false; } - if (!isValidIP4Word(word)) { + if (!isValidIP4Word(word)) { return false; } - if (numberOfColons != 6 && !doubleColon) { + if (numberOfColons != 6 && !doubleColon) { return false; } - // a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an - // IPv4 ending, otherwise 7 :'s is bad - if (numberOfColons == 7 && ipAddress.charAt(0 + offset) != ':' - && ipAddress.charAt(1 + offset) != ':') { + // a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an + // IPv4 ending, otherwise 7 :'s is bad + if (numberOfColons == 7 && ipAddress.charAt(0 + offset) != ':' + && ipAddress.charAt(1 + offset) != ':') { return false; } - word = ""; - break; + word = ""; + break; - case ':': - numberOfColons++; - if (numberOfColons > 7) { + case ':': + numberOfColons++; + if (numberOfColons > 7) { return false; } - if (numberOfPeriods > 0) { + if (numberOfPeriods > 0) { return false; } - if (prevChar == ':') { - if (doubleColon) { + if (prevChar == ':') { + if (doubleColon) { return false; } - doubleColon = true; - } - word = ""; - break; - case '%': - if (numberOfColons == 0) { - return false; - } - numberOfPercent++; - - // validate that the stuff after the % is valid - if ((i + 1) >= length) { - // in this case the percent is there but no number is - // available - return false; - } - try { - Integer.parseInt(ipAddress.substring(i + 1)); - } catch (NumberFormatException e) { - // right now we just support an integer after the % so if - // this is not - // what is there then return + doubleColon = true; + } + word = ""; + break; + case '%': + if (numberOfColons == 0) { return false; } - break; - - default: - if (numberOfPercent == 0) { - if (word.length() > 3) { + numberOfPercent++; + + // validate that the stuff after the % is valid + if ((i + 1) >= length) { + // in this case the percent is there but no number is + // available + return false; + } + try { + Integer.parseInt(ipAddress.substring(i + 1)); + } catch (NumberFormatException e) { + // right now we just support an integer after the % so if + // this is not + // what is there then return + return false; + } + break; + + default: + if (numberOfPercent == 0) { + if (word.length() > 3) { return false; } - if (!isValidHexChar(c)) { + if (!isValidHexChar(c)) { return false; } - } - word += c; - } - } - - // Check if we have an IPv4 ending - if (numberOfPeriods > 0) { - if (numberOfPeriods != 3 || !isValidIP4Word(word)) { - return false; - } - } else { - // If we're at then end and we haven't had 7 colons then there is a - // problem unless we encountered a doubleColon - if (numberOfColons != 7 && !doubleColon) { + } + word += c; + } + } + + // Check if we have an IPv4 ending + if (numberOfPeriods > 0) { + if (numberOfPeriods != 3 || !isValidIP4Word(word)) { return false; } - - // If we have an empty word at the end, it means we ended in either - // a : or a . - // If we did not end in :: then this is invalid - if (numberOfPercent == 0) { - if (word == "" && ipAddress.charAt(length - 1 - offset) == ':' - && ipAddress.charAt(length - 2 - offset) != ':') { - return false; - } - } - } - - return true; - } - - public static boolean isValidIP4Word(String word) { - char c; - if (word.length() < 1 || word.length() > 3) { + } else { + // If we're at then end and we haven't had 7 colons then there is a + // problem unless we encountered a doubleColon + if (numberOfColons != 7 && !doubleColon) { + return false; + } + + // If we have an empty word at the end, it means we ended in either + // a : or a . + // If we did not end in :: then this is invalid + if (numberOfPercent == 0) { + if (word == "" && ipAddress.charAt(length - 1 - offset) == ':' + && ipAddress.charAt(length - 2 - offset) != ':') { + return false; + } + } + } + + return true; + } + + public static boolean isValidIP4Word(String word) { + char c; + if (word.length() < 1 || word.length() > 3) { return false; } - for (int i = 0; i < word.length(); i++) { - c = word.charAt(i); - if (!(c >= '0' && c <= '9')) { + for (int i = 0; i < word.length(); i++) { + c = word.charAt(i); + if (!(c >= '0' && c <= '9')) { return false; } - } - if (Integer.parseInt(word) > 255) { - return false; - } - return true; - } - - static boolean isValidHexChar(char c) { - - return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') - || (c >= 'a' && c <= 'f'); - } - - /** - * Takes a string and parses it to see if it is a valid IPV4 address. - * - * @return true, if the string represents an IPV4 address in dotted - * notation, false otherwise - */ - public static boolean isValidIPV4Address(String value) { - // BEGIN android-changed - // general test - if (!value.matches("\\p{Digit}+(\\.\\p{Digit}+)*")) { + } + if (Integer.parseInt(word) > 255) { return false; } + return true; + } + + static boolean isValidHexChar(char c) { + + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') + || (c >= 'a' && c <= 'f'); + } + + /** + * Takes a string and parses it to see if it is a valid IPV4 address. + * + * @return true, if the string represents an IPV4 address in dotted + * notation, false otherwise + */ + public static boolean isValidIPV4Address(String value) { + // BEGIN android-changed + // general test + if (!value.matches("\\p{Digit}+(\\.\\p{Digit}+)*")) { + return false; + } - String[] parts = value.split("\\."); - int length = parts.length; - if (length < 1 || length > 4) { - return false; - } + String[] parts = value.split("\\."); + int length = parts.length; + if (length < 1 || length > 4) { + return false; + } - if (length == 1) { - // One part decimal numeric address - long longValue = Long.parseLong(parts[0]); - return longValue <= 0xFFFFFFFFL; - } else { - // Test each part for inclusion in the correct range - for (int i = 0; i < length; i++) { - // For two part addresses, the second part expresses - // a 24-bit quantity; for three part addresses, the third - // part expresses a 16-bit quantity. - int max = 0xff; - if ((length == 2) && (i == 1)) { - max = 0xffffff; - } else if ((length == 3) && (i == 2)) { - max = 0xffff; - } - if (Integer.parseInt(parts[i]) > max) { - return false; + if (length == 1) { + // One part decimal numeric address + long longValue = Long.parseLong(parts[0]); + return longValue <= 0xFFFFFFFFL; + } else { + // Test each part for inclusion in the correct range + for (int i = 0; i < length; i++) { + // For two part addresses, the second part expresses + // a 24-bit quantity; for three part addresses, the third + // part expresses a 16-bit quantity. + int max = 0xff; + if ((length == 2) && (i == 1)) { + max = 0xffffff; + } else if ((length == 3) && (i == 2)) { + max = 0xffff; + } + if (Integer.parseInt(parts[i]) > max) { + return false; + } } + return true; } - return true; - } - // END android-changed - } + // END android-changed + } } diff --git a/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java b/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java index d7c2ab8..51a2d28 100644 --- a/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java +++ b/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java @@ -106,6 +106,7 @@ public class InputStreamExposer { // if (is instanceof ExposedByteArrayInputStream) { // return ((ExposedByteArrayInputStream) is).expose(); // } + // END android-changed if (is.getClass().equals(ByteArrayInputStream.class)) { return expose((ByteArrayInputStream) is); diff --git a/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java b/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java deleted file mode 100644 index 1a994b2..0000000 --- a/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.util; - -import java.util.Arrays; - -/** - * Helper class with methods for sorting arrays. - * @deprecated Use {@link Comparator} and {@link Arrays.sort()} - */ -@Deprecated -public final class Sorter { - public interface Comparator<T> extends java.util.Comparator<T> { - } - - /** - * Sorts the array of objects using the default sorting algorithm. - * - * @param objs - * array of objects to be sorted - * @param comp - * A Comparator to be used to sort the elements - * - */ - public static <T> void sort(T[] objs, Comparator<T> comp) { - Arrays.sort(objs, comp); - } - -} diff --git a/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java b/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java index 26e8d01..655d156 100644 --- a/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java +++ b/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java @@ -29,7 +29,7 @@ import java.util.NoSuchElementException; import java.util.Set; /** - * + * * Reductive hash with two keys * */ @@ -37,13 +37,13 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { static final float DEFAULT_LOAD_FACTOR = 0.75f; static final int DEFAULT_INITIAL_SIZE = 16; - + private Set<Map.Entry<String, V>> entrySet; private Collection<V> values; private int size; private int arrSize; private int modCount; - + private Entry<E, K, V>[] arr; private float loadFactor; @@ -55,9 +55,10 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { public TwoKeyHashMap() { this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR); } - + /** * Constructs an empty HashMap + * * @param initialCapacity */ public TwoKeyHashMap(int initialCapacity) { @@ -65,16 +66,19 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { } /** - * Constructs an empty HashMap + * Constructs an empty HashMap + * * @param initialCapacity * @param initialLoadFactor */ + @SuppressWarnings("unchecked") public TwoKeyHashMap(int initialCapacity, float initialLoadFactor) { - if (initialCapacity < 0) { + if (initialCapacity < 0) { throw new IllegalArgumentException("initialCapacity should be >= 0"); } if (initialLoadFactor <= 0) { - throw new IllegalArgumentException("initialLoadFactor should be > 0"); + throw new IllegalArgumentException( + "initialLoadFactor should be > 0"); } loadFactor = initialLoadFactor; if (initialCapacity == Integer.MAX_VALUE) { @@ -84,9 +88,9 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { threshold = (int) (arrSize * loadFactor); arr = new Entry[arrSize + 1]; } - + /** - * Returns a collection view of the values + * Returns a collection view of the values */ public Collection<V> values() { if (values == null) { @@ -94,9 +98,9 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { } return values; } - + /** - * Returns a collection view of the mappings + * Returns a collection view of the mappings */ public Set<Map.Entry<String, V>> entrySet() { if (entrySet == null) { @@ -104,7 +108,7 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { } return entrySet; } - + /** * Clears the map */ @@ -116,6 +120,7 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { /** * Removes the mapping for the keys + * * @param key1 * @param key2 * @return @@ -124,9 +129,10 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { Entry<E, K, V> e = removeEntry(key1, key2); return null != e ? e.value : null; } - + /** * Associates the specified value with the specified keys in this map + * * @param key1 * @param key2 * @param value @@ -152,7 +158,8 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { Entry<E, K, V> e = arr[index]; while (e != null) { - if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) { + if (hash == e.hash && key1.equals(e.getKey1()) + && key2.equals(e.getKey2())) { V oldValue = e.value; e.value = value; return oldValue; @@ -172,8 +179,9 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { /** * Rehash the map - * + * */ + @SuppressWarnings("unchecked") void rehash() { int newArrSize = (arrSize + 1) * 2 + 1; if (newArrSize < 0) { @@ -206,10 +214,12 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { } /** - * Returns true if this map contains a mapping for the specified keys - * @param key1 - * @param key2 - * @return + * Answers whether this map contains a mapping for the specified keys. + * + * @param key1 first key + * @param key2 second key + * @return true if this map contains a mapping for the specified keys, and + * false otherwise. */ public boolean containsKey(Object key1, Object key2) { return findEntry(key1, key2) != null; @@ -217,6 +227,7 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { /** * Return the value by keys + * * @param key1 * @param key2 * @return @@ -237,14 +248,15 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { } /** - * Returns the number of mappings + * Returns the number of mappings */ public int size() { return size; } - + /** - * Creates new entry + * Creates new entry + * * @param hashCode * @param key1 * @param key2 @@ -252,13 +264,14 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { * @param next * @return */ - Entry<E, K, V> createEntry(int hashCode, E key1, K key2, - V value, Entry<E, K, V> next) { + Entry<E, K, V> createEntry(int hashCode, E key1, K key2, V value, + Entry<E, K, V> next) { return new Entry<E, K, V>(hashCode, key1, key2, value, next); } /** * Creates entries iterator + * * @return */ Iterator<Map.Entry<String, V>> createEntrySetIterator() { @@ -267,18 +280,18 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { /** * Creates values iterator + * * @return */ Iterator<V> createValueCollectionIterator() { return new ValueIteratorImpl(); } - /** * Entry implementation for the TwoKeyHashMap class * */ - public static class Entry<E, K, V> implements Map.Entry<String, V> { + public static class Entry<E, K, V> implements Map.Entry<String, V> { int hash; E key1; K key2; @@ -292,7 +305,7 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { this.value = value; this.next = next; } - + public String getKey() { return key1.toString() + key2.toString(); } @@ -300,7 +313,7 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { public E getKey1() { return key1; } - + public K getKey2() { return key2; } @@ -324,12 +337,11 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { Object getKey1 = e.getKey1(); Object getKey2 = e.getKey2(); Object getValue = e.getValue(); - if ((key1 == null && getKey1 != null) || - (key2 == null && getKey2 != null) || - (value == null && getValue != null) || - !key1.equals(e.getKey1()) || - !key2.equals(e.getKey2()) || - !value.equals(getValue)) { + if ((key1 == null && getKey1 != null) + || (key2 == null && getKey2 != null) + || (value == null && getValue != null) + || !key1.equals(e.getKey1()) || !key2.equals(e.getKey2()) + || !value.equals(getValue)) { return false; } return true; @@ -340,9 +352,9 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { int hash2 = (key2 == null ? 0 : key2.hashCode()); return (hash1 + hash2) ^ (value == null ? 0 : value.hashCode()); } - + } - + class EntrySetImpl extends AbstractSet<Map.Entry<String, V>> { public int size() { return size; @@ -375,7 +387,7 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { if (!(obj instanceof Entry)) { return false; } - return removeEntry(((Entry) obj).getKey1(), ((Entry)obj).getKey2()) != null; + return removeEntry(((Entry) obj).getKey1(), ((Entry) obj).getKey2()) != null; } public Iterator<Map.Entry<String, V>> iterator() { @@ -425,14 +437,14 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { found = false; returned_index = curr; returned_entry = curr_entry; - return (Map.Entry<String, V>)curr_entry; + return (Map.Entry<String, V>) curr_entry; } public void remove() { if (returned_index == -1) { throw new IllegalStateException(); } - + if (modCount != startModCount) { throw new ConcurrentModificationException(); } @@ -454,7 +466,7 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { returned_index = -1; } } - + private final Entry<E, K, V> findEntry(Object key1, Object key2) { if (key1 == null && key2 == null) { return arr[arrSize]; @@ -465,14 +477,15 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { Entry<E, K, V> e = arr[index]; while (e != null) { - if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) { + if (hash == e.hash && key1.equals(e.getKey1()) + && key2.equals(e.getKey2())) { return e; } e = e.next; } return null; } - + // Removes entry private final Entry<E, K, V> removeEntry(Object key1, Object key2) { if (key1 == null && key2 == null) { @@ -493,7 +506,8 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { Entry<E, K, V> e = arr[index]; Entry<E, K, V> prev = e; while (e != null) { - if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) { + if (hash == e.hash && key1.equals(e.getKey1()) + && key2.equals(e.getKey2())) { if (prev == e) { arr[index] = e.next; } else { @@ -529,12 +543,12 @@ public class TwoKeyHashMap<E, K, V> extends AbstractMap<String, V> { public Iterator<V> iterator() { return createValueCollectionIterator(); } - + public boolean contains(Object obj) { return containsValue(obj); } } - + class ValueIteratorImpl implements Iterator<V> { private EntryIteratorImpl itr; diff --git a/luni/src/main/java/org/apache/harmony/luni/util/Util.java b/luni/src/main/java/org/apache/harmony/luni/util/Util.java index bfb0149..0688e7d 100644 --- a/luni/src/main/java/org/apache/harmony/luni/util/Util.java +++ b/luni/src/main/java/org/apache/harmony/luni/util/Util.java @@ -41,13 +41,19 @@ public final class Util { if (encoding != null) { try { "".getBytes(encoding); - } catch (java.io.UnsupportedEncodingException e) { + } catch (Throwable t) { encoding = null; } } defaultEncoding = encoding; } + /** + * Get bytes from String using default encoding; default encoding can + * be changed via "os.encoding" property + * @param name input String + * @return byte array + */ public static byte[] getBytes(String name) { if (defaultEncoding != null) { try { @@ -58,6 +64,20 @@ public final class Util { return name.getBytes(); } + /** + * Get bytes from String with UTF8 encoding + * @param name + * input String + * @return byte array + */ + public static byte[] getUTF8Bytes(String name) { + try { + return name.getBytes("UTF-8"); + } catch (java.io.UnsupportedEncodingException e) { + return getBytes(name); + } + } + public static String toString(byte[] bytes) { if (defaultEncoding != null) { try { @@ -68,6 +88,10 @@ public final class Util { 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 { @@ -78,10 +102,18 @@ public final class Util { return new String(bytes, offset, length); } + public static String toUTF8String(byte[] bytes, int offset, int length) { + try { + return new String(bytes, offset, length, "UTF-8"); + } catch (java.io.UnsupportedEncodingException e) { + return toString(bytes, offset, length); + } + } + /** * 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 @@ -236,7 +268,7 @@ public final class Util { * '%' 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. @@ -273,7 +305,7 @@ public final class Util { } return result.toString(); } - + public static String toASCIILowerCase(String s) { int len = s.length(); StringBuilder buffer = new StringBuilder(len); @@ -287,7 +319,7 @@ public final class Util { } return buffer.toString(); } - + public static String toASCIIUpperCase(String s) { int len = s.length(); StringBuilder buffer = new StringBuilder(len); diff --git a/luni/src/main/native/cbigint.c b/luni/src/main/native/cbigint.c index 0f65ca0..77ee0f8 100644 --- a/luni/src/main/native/cbigint.c +++ b/luni/src/main/native/cbigint.c @@ -18,7 +18,7 @@ #include <string.h> #include "cbigint.h" -#if defined(LINUX) || defined(FREEBSD) +#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) #define USE_LL #endif @@ -691,7 +691,7 @@ timesTenToTheEHighPrecision (U_64 * result, IDATA length, jint e) */ /* Replace the current implementaion which performs a * "multiplication" by 10 e number of times with an actual - * mulitplication. 10e19 is the largest exponent to the power of ten + * multiplication. 10e19 is the largest exponent to the power of ten * that will fit in a 64-bit integer, and 10e9 is the largest exponent to * the power of ten that will fit in a 64-bit integer. Not sure where the * break-even point is between an actual multiplication and a diff --git a/luni/src/main/native/java_io_FileDescriptor.c b/luni/src/main/native/java_io_FileDescriptor.c index a5ec8b7..897e688 100644 --- a/luni/src/main/native/java_io_FileDescriptor.c +++ b/luni/src/main/native/java_io_FileDescriptor.c @@ -103,20 +103,6 @@ static void fd_sync(JNIEnv* env, jobject obj) { } } -/* - * public native boolean valid() - */ -static jboolean fd_valid(JNIEnv* env, jobject obj) { - int fd = getFd(env, obj); - struct stat sb; - - if(fstat(fd, &sb) == 0) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } -} - /* checks to see if class is inited and inits if needed, returning -1 * on fail and 0 on success */ @@ -205,8 +191,7 @@ void jniSetFileDescriptorOfFD (JNIEnv* env, jobject fileDescriptor, int value) { static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ { "oneTimeInitialization", "()V", nativeClassInit }, - { "syncImpl", "()V", fd_sync }, - { "valid", "()Z", fd_valid } + { "syncImpl", "()V", fd_sync } }; int register_java_io_FileDescriptor(JNIEnv* env) { return jniRegisterNativeMethods(env, "java/io/FileDescriptor", diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp index e105f5c..cce822a 100644 --- a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp +++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp @@ -1654,7 +1654,7 @@ static int createSocketFileDescriptor(JNIEnv* env, jobject fileDescriptor, } -static void osNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz, +static void osNetworkSystem_createStreamSocketImpl(JNIEnv* env, jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) { // LOGD("ENTER createSocketImpl"); createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM); @@ -2340,35 +2340,6 @@ static void osNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass clazz, } } -static jboolean osNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz, - jobject fileDescriptor, jint port, jboolean bindToDevice, - jobject inetAddress) { - // LOGD("ENTER socketBindImpl2"); - - struct sockaddr_storage sockaddress; - int ret; - int handle; - - ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress); - if (ret < 0) // Exception has already been thrown. - return 0; - - handle = jniGetFDFromFileDescriptor(env, fileDescriptor); - if (handle == 0 || handle == -1) { - throwSocketException(env, SOCKERR_BADDESC); - return 0; - } - - ret = doBind(handle, &sockaddress); - if (ret < 0) { - int err = convertError(errno); - jniThrowException(env, "java/net/BindException", netLookupErrorString(err)); - return 0; - } - - return 0; -} - static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz, jobject fd, jobject sender, jint receiveTimeout) { // LOGD("ENTER peekDatagramImpl"); @@ -2639,19 +2610,6 @@ static void osNetworkSystem_createServerStreamSocketImpl(JNIEnv* env, setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int)); } -static void osNetworkSystem_createMulticastSocketImpl(JNIEnv* env, - jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) { - // LOGD("ENTER createMulticastSocketImpl"); - - int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM); - if (handle < 0) - return; - - int value = 1; - // setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(jbyte)); - setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int)); -} - /* * @param timeout in milliseconds. If zero, block until data received */ @@ -3847,7 +3805,7 @@ clean: static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ { "oneTimeInitializationImpl", "(Z)V", (void*) osNetworkSystem_oneTimeInitializationImpl }, - { "createSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createSocketImpl }, + { "createStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createStreamSocketImpl }, { "createDatagramSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createDatagramSocketImpl }, { "readSocketImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_readSocketImpl }, { "readSocketDirectImpl", "(Ljava/io/FileDescriptor;IIII)I", (void*) osNetworkSystem_readSocketDirectImpl }, @@ -3865,7 +3823,6 @@ static JNINativeMethod gMethods[] = { { "sendUrgentDataImpl", "(Ljava/io/FileDescriptor;B)V", (void*) osNetworkSystem_sendUrgentDataImpl }, { "connectDatagramImpl2", "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V", (void*) osNetworkSystem_connectDatagramImpl2 }, { "disconnectDatagramImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_disconnectDatagramImpl }, - { "socketBindImpl2", "(Ljava/io/FileDescriptor;IZLjava/net/InetAddress;)Z", (void*) osNetworkSystem_socketBindImpl2 }, { "peekDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I", (void*) osNetworkSystem_peekDatagramImpl }, { "receiveDatagramImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I", (void*) osNetworkSystem_receiveDatagramImpl }, { "receiveDatagramDirectImpl", "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I", (void*) osNetworkSystem_receiveDatagramDirectImpl }, @@ -3876,7 +3833,6 @@ static JNINativeMethod gMethods[] = { { "sendConnectedDatagramImpl", "(Ljava/io/FileDescriptor;[BIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramImpl }, { "sendConnectedDatagramDirectImpl", "(Ljava/io/FileDescriptor;IIIZ)I", (void*) osNetworkSystem_sendConnectedDatagramDirectImpl }, { "createServerStreamSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createServerStreamSocketImpl }, - { "createMulticastSocketImpl", "(Ljava/io/FileDescriptor;Z)V", (void*) osNetworkSystem_createMulticastSocketImpl }, { "receiveStreamImpl", "(Ljava/io/FileDescriptor;[BIII)I", (void*) osNetworkSystem_receiveStreamImpl }, { "sendStreamImpl", "(Ljava/io/FileDescriptor;[BII)I", (void*) osNetworkSystem_sendStreamImpl }, { "shutdownInputImpl", "(Ljava/io/FileDescriptor;)V", (void*) osNetworkSystem_shutdownInputImpl }, diff --git a/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c b/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c index d8a1e68..e92b776 100644 --- a/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c +++ b/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c @@ -22,7 +22,7 @@ #include "commonDblParce.h" #include "cbigint.h" -#if defined(LINUX) +#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) #define USE_LL #endif diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java index ed81162..84cddf2 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java @@ -45,8 +45,9 @@ public class FileTest extends TestCase { File file = new File(root, "/dir/file"); assertEquals("Assert 1: wrong path result ", path.getPath(), file .getPath()); - assertTrue("Assert 1.1: path not absolute ", new File("\\\\\\a\b").isAbsolute()); - + assertFalse("Assert 1.1: path absolute ", new File("\\\\\\a\b").isAbsolute()); + assertTrue("Assert 1.1: path absolute ", new File("///a/b").isAbsolute()); + // Test data used in a few places below String dirName = System.getProperty("java.io.tmpdir"); String fileName = "input.tst"; diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java index 14ca1ad..3097fbe 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java @@ -838,6 +838,8 @@ public class ClassTest extends junit.framework.TestCase { args = {} ) public void test_getClassLoader() { + // this fails if ClassTest.class was loaded by the regular classloader, + // but passes if it was loaded by the boot class loader. assertEquals(ExtendTestClass.class.getClassLoader(), PublicTestClass.class.getClassLoader()); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java index 2b03e5a..b1ad88a 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java @@ -1091,8 +1091,6 @@ public class FloatTest extends TestCase { fail("Expected Float.valueOf(null) to throw NPE."); } catch (NullPointerException ex) { // expected - } catch (Exception ex) { - fail("Expected Float.valueOf(null) to throw NPE not " + ex.getClass().getName()); } try { diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java index 9151068..ea71009 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java @@ -169,6 +169,56 @@ public class IntegerTest extends TestCase { exception = true; } assertTrue("Failed to throw exception for 9999999999", exception); + + try { + Integer.decode("-"); + fail("Expected exception for -"); + } catch (NumberFormatException e) { + // Expected + } + + try { + Integer.decode("0x"); + fail("Expected exception for 0x"); + } catch (NumberFormatException e) { + // Expected + } + + try { + Integer.decode("#"); + fail("Expected exception for #"); + } catch (NumberFormatException e) { + // Expected + } + + try { + Integer.decode("x123"); + fail("Expected exception for x123"); + } catch (NumberFormatException e) { + // Expected + } + + try { + Integer.decode(null); + fail("Expected exception for null"); + } catch (NullPointerException e) { + // Expected + } + + try { + Integer.decode(""); + fail("Expected exception for empty string"); + } catch (NumberFormatException ex) { + // Expected + } + + try { + Integer.decode(" "); + fail("Expected exception for single space"); + } catch (NumberFormatException ex) { + // Expected + } + } /** @@ -591,6 +641,15 @@ public class IntegerTest extends TestCase { -Integer.MAX_VALUE)); assertEquals("Returned incorrect octal string", "-2147483648", Integer.toString( Integer.MIN_VALUE)); + + // Test for HARMONY-6068 + assertEquals("Returned incorrect octal String", "-1000", Integer.toString(-1000)); + assertEquals("Returned incorrect octal String", "1000", Integer.toString(1000)); + assertEquals("Returned incorrect octal String", "0", Integer.toString(0)); + assertEquals("Returned incorrect octal String", "708", Integer.toString(708)); + assertEquals("Returned incorrect octal String", "-100", Integer.toString(-100)); + assertEquals("Returned incorrect octal String", "-1000000008", Integer.toString(-1000000008)); + assertEquals("Returned incorrect octal String", "2000000008", Integer.toString(2000000008)); } /** diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java index e2b72be..758428e 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java @@ -23,6 +23,7 @@ import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargetClass; import dalvik.annotation.BrokenTest; +import dalvik.annotation.SideEffect; @TestTargetClass(Object.class) public class ObjectTest extends junit.framework.TestCase { @@ -79,6 +80,7 @@ public class ObjectTest extends junit.framework.TestCase { method = "finalize", args = {} ) + @SideEffect("Causes OutOfMemoryError to test finalization") public void test_finalize() { isCalled = false; class TestObject extends Object { diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java index 93561bf..d35f50b 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java @@ -228,6 +228,16 @@ public class ProcessBuilderTest extends TestCase { Process process = pb.start(); InputStream in = process.getInputStream(); InputStream err = process.getErrorStream(); + + while (true) { + try { + process.waitFor(); + break; + } catch (InterruptedException e) { + // Ignored + } + } + byte[] buf = new byte[1024]; if (in.available() > 0) { assertTrue(in.read(buf) > 0); diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java index bcb94c7..48fddfe 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java @@ -37,11 +37,7 @@ public class ThreadLocalTest extends TestCase { args = {} ) public void test_Constructor() { - try { - new ThreadLocal<Object>(); - } catch (Exception e) { - fail("unexpected exception: " + e.toString()); - } + new ThreadLocal<Object>(); } /** diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java index d00968f..bdbfbd4 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java @@ -67,8 +67,7 @@ public class ContentHandlerFactoryTest extends TestCase { assertTrue(isCreateContentHandlerCalled); assertTrue(isGetContentCalled); } catch (Exception e) { - fail("Exception during test : " + e.getMessage()); - + throw new RuntimeException(e); } isGetContentCalled = false; @@ -77,8 +76,7 @@ public class ContentHandlerFactoryTest extends TestCase { con.getContent(new Class[] {}); assertTrue(isGetContentCalled); } catch (Exception e) { - fail("Exception during test : " + e.getMessage()); - + throw new RuntimeException(e); } try { diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java index c803d3b..bcd73d8 100644 --- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java @@ -1069,8 +1069,6 @@ public class URLConnectionTest extends TestCase { method = "getHeaderFieldDate", args = {java.lang.String.class, long.class} ) - @KnownFailure("getHeaderFieldDate on Content-Length throws an exception." - + " The RI just returns the default value") public void test_getHeaderFieldDateLjava_lang_StringJ() { Support_TestWebData params = Support_TestWebData.testParams[0]; @@ -1612,7 +1610,6 @@ public class URLConnectionTest extends TestCase { method = "guessContentTypeFromStream", args = {java.io.InputStream.class} ) - @KnownFailure("'<?xml' recognised as text/html instead of application/xml") public void test_guessContentTypeFromStreamLjava_io_InputStream() throws IOException { assertContentTypeEquals("ASCII", "text/html", "<html>"); diff --git a/luni/src/test/java/tests/api/java/io/FileTest.java b/luni/src/test/java/tests/api/java/io/FileTest.java index b35e85f..9f32fef 100644 --- a/luni/src/test/java/tests/api/java/io/FileTest.java +++ b/luni/src/test/java/tests/api/java/io/FileTest.java @@ -217,8 +217,6 @@ public class FileTest extends junit.framework.TestCase { method = "File", args = {java.lang.String.class, java.lang.String.class} ) - @AndroidOnly("Test 3 incorrectly fails on the RI; Android is more " + - "better at resolving path names.") public void test_ConstructorLjava_lang_StringLjava_lang_String_112270() { File ref1 = new File("/dir1/file1"); @@ -230,10 +228,10 @@ public class FileTest extends junit.framework.TestCase { ref1.getPath())); File file3 = new File("\\", "\\dir1\\file1"); assertTrue("wrong result 3: " + file3, file3.getPath().equals( - ref1.getPath())); + "\\/\\dir1\\file1")); File file4 = new File("\\", "\\\\dir1\\file1"); assertTrue("wrong result 4: " + file4, file4.getPath().equals( - ref1.getPath())); + "\\/\\\\dir1\\file1")); File ref2 = new File("/lib/content-types.properties"); File file5 = new File("/", "lib/content-types.properties"); @@ -250,8 +248,6 @@ public class FileTest extends junit.framework.TestCase { method = "File", args = {java.io.File.class, java.lang.String.class} ) - @AndroidOnly("Test 3 incorrectly fails on the RI; Android is more " + - "better at resolving path names.") public void test_ConstructorLjava_io_FileLjava_lang_String_112270() { File ref1 = new File("/dir1/file1"); @@ -264,10 +260,10 @@ public class FileTest extends junit.framework.TestCase { ref1.getPath())); File file3 = new File(root, "\\dir1\\file1"); assertTrue("wrong result 3: " + file3, file3.getPath().equals( - ref1.getPath())); + "/\\dir1\\file1")); File file4 = new File(root, "\\\\dir1\\file1"); assertTrue("wrong result 4: " + file4, file4.getPath().equals( - ref1.getPath())); + "/\\\\dir1\\file1")); File ref2 = new File("/lib/content-types.properties"); File file5 = new File(root, "lib/content-types.properties"); @@ -693,6 +689,8 @@ public class FileTest extends junit.framework.TestCase { args = {} ) public void test_delete() { + // this test passes in the emulator, but it fails on the device + // Test for method boolean java.io.File.delete() try { File dir = new File(System.getProperty("java.io.tmpdir"), platformId diff --git a/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java b/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java index 3f5fc68..783478a 100644 --- a/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java +++ b/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java @@ -30,6 +30,7 @@ import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; +import java.util.Arrays; import tests.support.Support_OutputStream; @@ -483,6 +484,99 @@ public class OutputStreamWriterTest extends TestCase { } } + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "write", + args = {char[].class} + ) + public void test_write_US_ASCII() throws Exception { + testEncodeCharset("US-ASCII", 128); + } + + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "write", + args = {char[].class} + ) + public void test_write_ISO_8859_1() throws Exception { + testEncodeCharset("ISO-8859-1", 256); + } + + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "write", + args = {char[].class} + ) + public void test_write_UTF_16BE() throws Exception { + testEncodeCharset("UTF-16BE", 0xd800); + } + + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "write", + args = {char[].class} + ) + public void test_write_UTF_16LE() throws Exception { + testEncodeCharset("UTF-16LE", 0xd800); + } + + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "write", + args = {char[].class} + ) + public void test_write_UTF_16() throws Exception { + testEncodeCharset("UTF-16", 0xd800); + } + + @TestTargetNew( + level = TestLevel.PARTIAL_COMPLETE, + notes = "", + method = "write", + args = {char[].class} + ) + public void test_write_UTF_8() throws Exception { + testEncodeCharset("UTF-8", 0xd800); + } + + private void testEncodeCharset(String charset, int maxChar) throws Exception { + char[] chars = new char[maxChar]; + for (int i = 0; i < maxChar; i++) { + chars[i] = (char) i; + } + + // to byte array + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + OutputStreamWriter charsOut = new OutputStreamWriter(bytesOut, charset); + charsOut.write(chars); + charsOut.flush(); + + // decode from byte array, one character at a time + ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytesOut.toByteArray()); + InputStreamReader charsIn = new InputStreamReader(bytesIn, charset); + for (int i = 0; i < maxChar; i++) { + assertEquals(i, charsIn.read()); + } + assertEquals(-1, charsIn.read()); + + // decode from byte array, using byte buffers + bytesIn = new ByteArrayInputStream(bytesOut.toByteArray()); + charsIn = new InputStreamReader(bytesIn, charset); + char[] decoded = new char[maxChar]; + for (int r = 0; r < maxChar; ) { + r += charsIn.read(decoded, r, maxChar - r); + } + assertEquals(-1, charsIn.read()); + for (int i = 0; i < maxChar; i++) { + assertEquals(i, decoded[i]); + } + } + /** * @tests java.io.OutputStreamWriter#getEncoding() */ diff --git a/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java b/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java index 4c67241..d890f38 100644 --- a/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java +++ b/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java @@ -21,6 +21,7 @@ import dalvik.annotation.TestLevel; import dalvik.annotation.TestTargetNew; import dalvik.annotation.TestTargetClass; import dalvik.annotation.BrokenTest; +import dalvik.annotation.SideEffect; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; @@ -107,6 +108,7 @@ public class SoftReferenceTest extends junit.framework.TestCase { method = "get", args = {} ) + @SideEffect("Causes OutOfMemoryError to test finalization") public void test_get_SoftReference() { class TestObject { diff --git a/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java b/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java index 31dfaa5..8919652 100644 --- a/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java +++ b/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java @@ -169,8 +169,6 @@ public class GenericReflectionCornerCases extends GenericReflectionTestsBase { ) }) @SuppressWarnings("unchecked") - @KnownFailure("Class MultipleBoundedWildcardUnEquality can not be found, " - + "maybe the wrong class loader is used to get the raw type?") public void testMultipleBoundedWildcardUnEquality() throws Exception { Class<? extends MultipleBoundedWildcardUnEquality> clazz = MultipleBoundedWildcardUnEquality.class; @@ -240,8 +238,6 @@ public class GenericReflectionCornerCases extends GenericReflectionTestsBase { ) }) @SuppressWarnings("unchecked") - @KnownFailure("Class MultipleBoundedWildcardEquality can not be found, " - + "maybe the wrong class loader is used to get the raw type?") public void testMultipleBoundedWildcard() throws Exception { Class<? extends MultipleBoundedWildcardEquality> clazz = MultipleBoundedWildcardEquality.class; diff --git a/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java b/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java index c9255b2..7db5dbe 100644 --- a/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java +++ b/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java @@ -201,8 +201,6 @@ public class GenericTypesTest extends GenericReflectionTestsBase { args = {} ) @SuppressWarnings("unchecked") - @KnownFailure("Class GenericType can not be found, " - + "maybe the wrong class loader is used to get the raw type?") public void testSimpleInheritance() throws Exception { Class<? extends SimpleInheritance> clazz = SimpleInheritance.class; TypeVariable<Class> subTypeVariable = getTypeParameter(clazz); diff --git a/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java b/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java index eaff7c8..bf3698e 100644 --- a/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java +++ b/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java @@ -55,8 +55,6 @@ public class ParameterizedTypeTest extends GenericReflectionTestsBase { args = {} ) }) - @KnownFailure("Class A can not be found, " - + "maybe the wrong class loader is used to get the raw type?") public void testStringParameterizedSuperClass() { Class<? extends B> clazz = B.class; Type genericSuperclass = clazz.getGenericSuperclass(); @@ -93,8 +91,6 @@ public class ParameterizedTypeTest extends GenericReflectionTestsBase { args = {} ) }) - @KnownFailure("Class C can not be found, " - + "maybe the wrong class loader is used to get the raw type?") public void testTypeParameterizedSuperClass() { Class<? extends D> clazz = D.class; Type genericSuperclass = clazz.getGenericSuperclass(); diff --git a/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java b/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java index f6957e2..13141f8 100644 --- a/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java +++ b/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java @@ -36,6 +36,9 @@ import java.net.SocketException; import java.net.UnknownHostException; import java.security.Permission; import java.util.Enumeration; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; import tests.support.Support_NetworkInterface; import tests.support.Support_PortManager; @@ -64,23 +67,24 @@ public class MulticastSocketTest extends SocketTestCase { public MulticastSocket ms; - boolean running = true; + volatile boolean running = true; - volatile public byte[] rbuf = new byte[512]; - - volatile DatagramPacket rdp = null; + private final BlockingQueue<DatagramPacket> queue + = new ArrayBlockingQueue<DatagramPacket>(1); public void run() { try { while (running) { try { + byte[] rbuf = new byte[512]; + rbuf[0] = -1; + DatagramPacket rdp = new DatagramPacket(rbuf, rbuf.length); ms.receive(rdp); + queue.put(rdp); } catch (java.io.InterruptedIOException e) { - Thread.yield(); + } catch (InterruptedException e) { } - ; } - ; } catch (java.io.IOException e) { System.out.println("Multicast server failed: " + e); } finally { @@ -93,15 +97,8 @@ public class MulticastSocketTest extends SocketTestCase { ms.leaveGroup(aGroup); } - public void stopServer() { - running = false; - } - public MulticastServer(InetAddress anAddress, int aPort) throws java.io.IOException { - rbuf = new byte[512]; - rbuf[0] = -1; - rdp = new DatagramPacket(rbuf, rbuf.length); ms = new MulticastSocket(aPort); ms.setSoTimeout(2000); ms.joinGroup(anAddress); @@ -109,13 +106,20 @@ public class MulticastSocketTest extends SocketTestCase { public MulticastServer(SocketAddress anAddress, int aPort, NetworkInterface netInterface) throws java.io.IOException { - rbuf = new byte[512]; - rbuf[0] = -1; - rdp = new DatagramPacket(rbuf, rbuf.length); ms = new MulticastSocket(aPort); ms.setSoTimeout(2000); ms.joinGroup(anAddress, netInterface); } + + public DatagramPacket receive() throws InterruptedException { + return queue.poll(1000, TimeUnit.MILLISECONDS); + } + + public void stopServer() throws InterruptedException { + running = false; + interrupt(); + join(); + } } /** @@ -458,7 +462,7 @@ public class MulticastSocketTest extends SocketTestCase { method = "joinGroup", args = {java.net.InetAddress.class} ) - public void test_joinGroupLjava_net_InetAddress() { + public void test_joinGroupLjava_net_InetAddress() throws InterruptedException { // Test for method void // java.net.MulticastSocket.joinGroup(java.net.InetAddress) String msg = null; @@ -476,8 +480,7 @@ public class MulticastSocketTest extends SocketTestCase { .length(), group, groupPort); mss.joinGroup(group); mss.send(sdp, (byte) 10); - Thread.sleep(1000); - + SecurityManager sm = new SecurityManager() { public void checkPermission(Permission perm) { @@ -514,8 +517,10 @@ public class MulticastSocketTest extends SocketTestCase { } catch (Exception e) { fail("Exception during joinGroup test: " + e.toString()); } - assertTrue("Group member did not recv data: ", new String(server.rdp - .getData(), 0, server.rdp.getLength()).equals(msg)); + DatagramPacket rdb = server.receive(); + + assertEquals("Group member did not recv data: ", msg, + new String(rdb.getData(), 0, rdb.getLength())); } @@ -609,11 +614,11 @@ public class MulticastSocketTest extends SocketTestCase { .length(), group, serverPort); mss.setTimeToLive(2); mss.send(sdp); - Thread.sleep(1000); + DatagramPacket rdp = server.receive(); + // now vaildate that we received the data as expected - assertTrue("Group member did not recv data: ", new String( - server.rdp.getData(), 0, server.rdp.getLength()) - .equals(msg)); + assertEquals("Group member did not recv data: ", msg, + new String(rdp.getData(), 0, rdp.getLength())); server.stopServer(); // now validate that we handled the case were we join a @@ -634,11 +639,9 @@ public class MulticastSocketTest extends SocketTestCase { sdp = new DatagramPacket(msg.getBytes(), msg.length(), group2, serverPort); mss.send(sdp); - Thread.sleep(1000); - assertFalse( - "Group member received data when sent on different group: ", - new String(server.rdp.getData(), 0, server.rdp.getLength()) - .equals(msg)); + rdp = server.receive(); + assertNull("Group member received data when sent on different group", + rdp); server.stopServer(); // if there is more than one network interface then check that @@ -718,20 +721,20 @@ public class MulticastSocketTest extends SocketTestCase { sdp = new DatagramPacket(msg.getBytes(), msg.length(), group, serverPort); mss.send(sdp); - Thread.sleep(1000); + rdp = server.receive(); + if (thisInterface.equals(sendingInterface)) { - assertTrue( + assertEquals( "Group member did not recv data when " + - "bound on specific interface: ", - new String(server.rdp.getData(), 0, - server.rdp.getLength()).equals(msg)); + "bound on specific interface: ", msg, + new String(rdp.getData(), 0, rdp.getLength())); } else { assertFalse( "Group member received data on other " + "interface when only asked for it on one " + "interface: ", - new String(server.rdp.getData(), 0, - server.rdp.getLength()).equals(msg)); + new String(rdp.getData(), 0, + rdp.getLength()).equals(msg)); } server.stopServer(); @@ -943,7 +946,7 @@ public class MulticastSocketTest extends SocketTestCase { method = "send", args = {java.net.DatagramPacket.class, byte.class} ) - public void test_sendLjava_net_DatagramPacketB() { + public void test_sendLjava_net_DatagramPacketB() throws InterruptedException { // Test for method void // java.net.MulticastSocket.send(java.net.DatagramPacket, byte) @@ -1016,11 +1019,10 @@ public class MulticastSocketTest extends SocketTestCase { } catch(IOException ioe) { //expected } - - byte[] data = server.rdp.getData(); - int length = server.rdp.getLength(); - assertTrue("Failed to send data. Received " + length, new String(data, - 0, length).equals(msg)); + + DatagramPacket rdp = server.receive(); + assertEquals("Failed to send data. Received " + rdp.getLength(), msg, + new String(rdp.getData(), 0, rdp.getLength())); } /** @@ -1163,24 +1165,13 @@ public class MulticastSocketTest extends SocketTestCase { DatagramPacket sdp = new DatagramPacket(theBytes, theBytes.length, group, serverPort); mss.send(sdp); - Thread.sleep(1000); - String receivedMessage = new String(server.rdp - .getData(), 0, server.rdp.getLength()); - assertTrue( - "Group member did not recv data when send on " + - "a specific interface: ", - receivedMessage.equals(msg)); - assertTrue( - "Datagram was not received from expected " + - "interface expected[" - + thisInterface - + "] got [" - + NetworkInterface - .getByInetAddress(server.rdp - .getAddress()) + "]", - NetworkInterface.getByInetAddress( - server.rdp.getAddress()).equals( - thisInterface)); + DatagramPacket rdp = server.receive(); + + String receivedMessage = new String(rdp.getData(), 0, rdp.getLength()); + assertEquals("Group member did not recv data when send on " + + "a specific interface: ", msg, receivedMessage); + assertEquals("Datagram was not received as expected.", + thisInterface, NetworkInterface.getByInetAddress(rdp.getAddress())); // stop the server server.stopServer(); @@ -1598,7 +1589,7 @@ public class MulticastSocketTest extends SocketTestCase { * Tears down the fixture, for example, close a network connection. This * method is called after a test is executed. */ - protected void tearDown() { + protected void tearDown() throws InterruptedException { if (t != null) t.interrupt(); diff --git a/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java b/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java index 9fc287c..463532f 100644 --- a/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java +++ b/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java @@ -40,7 +40,7 @@ public class UnknownServiceExceptionTest extends junit.framework.TestCase { public void test_Constructor() { // Test for method java.net.UnknownServiceException() try { - new URL("file://moo.txt").openConnection().getOutputStream(); + new URL("file:///moo.txt").openConnection().getOutputStream(); } catch (UnknownServiceException e) { // correct return; diff --git a/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java b/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java index 169afe3..e2c47b8 100644 --- a/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java +++ b/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java @@ -85,7 +85,7 @@ public class AbstractSequentialListTest extends TestCase { } public boolean hasNext() { - return false; + return true; } public boolean hasPrevious() { diff --git a/luni/src/test/java/tests/api/java/util/BitSetTest.java b/luni/src/test/java/tests/api/java/util/BitSetTest.java index c0e6f2a..34ec49a 100644 --- a/luni/src/test/java/tests/api/java/util/BitSetTest.java +++ b/luni/src/test/java/tests/api/java/util/BitSetTest.java @@ -252,7 +252,7 @@ public class BitSetTest extends junit.framework.TestCase { initialSize = bs.size(); bs.set(0, initialSize); bs.clear(7, 64); - assertEquals("Failed to grow BitSet", 128, bs.size()); + assertEquals("Failed to grow BitSet", 64, bs.size()); for (int i = 0; i < 7; i++) assertTrue("Shouldn't have cleared bit " + i, bs.get(i)); for (int i = 7; i < 64; i++) @@ -624,7 +624,7 @@ public class BitSetTest extends junit.framework.TestCase { // pos1 and pos2 is in the same bitset element, boundary testing bs = new BitSet(16); bs.set(7, 64); - assertEquals("Failed to grow BitSet", 128, bs.size()); + assertEquals("Failed to grow BitSet", 64, bs.size()); for (int i = 0; i < 7; i++) assertTrue("Shouldn't have set bit " + i, !bs.get(i)); for (int i = 7; i < 64; i++) @@ -858,7 +858,7 @@ public class BitSetTest extends junit.framework.TestCase { bs.set(7); bs.set(10); bs.flip(7, 64); - assertEquals("Failed to grow BitSet", 128, bs.size()); + assertEquals("Failed to grow BitSet", 64, bs.size()); for (int i = 0; i < 7; i++) assertTrue("Shouldn't have flipped bit " + i, !bs.get(i)); assertTrue("Failed to flip bit 7", !bs.get(7)); diff --git a/luni/src/test/java/tests/api/java/util/FormatterTest.java b/luni/src/test/java/tests/api/java/util/FormatterTest.java index 636f1bd..b2030c9 100644 --- a/luni/src/test/java/tests/api/java/util/FormatterTest.java +++ b/luni/src/test/java/tests/api/java/util/FormatterTest.java @@ -4705,7 +4705,7 @@ public class FormatterTest extends TestCase { bw.close(); readOnly = File.createTempFile("readonly", null); - readOnly.setReadOnly(); + assertTrue(readOnly.setReadOnly()); secret = File.createTempFile("secret", null); diff --git a/luni/src/test/java/tests/api/java/util/TreeMapTest.java b/luni/src/test/java/tests/api/java/util/TreeMapTest.java index 7ea4c9e..0e7f6a1 100644 --- a/luni/src/test/java/tests/api/java/util/TreeMapTest.java +++ b/luni/src/test/java/tests/api/java/util/TreeMapTest.java @@ -83,6 +83,9 @@ public class TreeMapTest extends junit.framework.TestCase { if (null == o1) { return -1; } + if (null == o2) { + return 1; + } return o1.compareTo(o2); } } @@ -844,8 +847,6 @@ public class TreeMapTest extends junit.framework.TestCase { method = "equals", args = {java.lang.Object.class} ) - @KnownFailure("equals(Onject o) method throws java.lang.ClassCastException " + - "for TreeMap objects with different key objects.") public void test_equals() throws Exception { // comparing TreeMaps with different object types Map m1 = new TreeMap(); diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java index ddd56e5..ac8f77b 100644 --- a/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java +++ b/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java @@ -15,14 +15,13 @@ * limitations under the License. */ -/* - * Android Notice - * In this class the address length was changed from long to int. - * This is due to performance optimizations for the device. - */ - package org.apache.harmony.nio.internal; +// BEGIN android-note +// Copied from a newer version of Harmony. +// In this class the address length was changed from long to int. +// END android-note + import java.io.FileDescriptor; import java.io.IOException; import java.io.InterruptedIOException; @@ -43,7 +42,7 @@ import java.nio.channels.NotYetConnectedException; import java.nio.channels.spi.SelectorProvider; import org.apache.harmony.luni.net.NetUtil; -import org.apache.harmony.luni.net.SocketImplProvider; +import org.apache.harmony.luni.net.PlainDatagramSocketImpl; import org.apache.harmony.luni.platform.FileDescriptorHandler; import org.apache.harmony.luni.platform.INetworkSystem; import org.apache.harmony.luni.platform.Platform; @@ -52,15 +51,10 @@ import org.apache.harmony.nio.AddressUtil; /* * The default implementation class of java.nio.channels.DatagramChannel. - * */ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorHandler { - // ------------------------------------------------------------------- - // Class variables - // ------------------------------------------------------------------- - // The singleton to do the native network operation. private static final INetworkSystem networkSystem = Platform .getNetworkSystem(); @@ -72,10 +66,6 @@ class DatagramChannelImpl extends DatagramChannel implements private static final byte[] stubArray = new byte[0]; - // ------------------------------------------------------------------- - // Instance variables - // ------------------------------------------------------------------- - // The fd to interact with native code private FileDescriptor fd; @@ -94,19 +84,17 @@ class DatagramChannelImpl extends DatagramChannel implements // whether the socket is bound boolean isBound = false; - private final Object readLock = new Object(); + private static class ReadLock {} + private final Object readLock = new ReadLock(); - private final Object writeLock = new Object(); + private static class WriteLock {} + private final Object writeLock = new WriteLock(); // used to store the trafficClass value which is simply returned // as the value that was set. We also need it to pass it to methods // that specify an address packets are going to be sent to private int trafficClass = 0; - // ------------------------------------------------------------------- - // Constructor - // ------------------------------------------------------------------- - /* * Constructor */ @@ -120,16 +108,13 @@ class DatagramChannelImpl extends DatagramChannel implements /* * for native call */ - private DatagramChannelImpl(){ + @SuppressWarnings("unused") + private DatagramChannelImpl() { super(SelectorProvider.provider()); fd = new FileDescriptor(); connectAddress = new InetSocketAddress(0); } - // ------------------------------------------------------------------- - // Methods for getting internal DatagramSocket. - // ------------------------------------------------------------------- - /* * Getting the internal DatagramSocket If we have not the socket, we create * a new one. @@ -137,8 +122,8 @@ class DatagramChannelImpl extends DatagramChannel implements @Override synchronized public DatagramSocket socket() { if (null == socket) { - socket = new DatagramSocketAdapter(SocketImplProvider - .getDatagramSocketImpl(fd, localPort), this); + socket = new DatagramSocketAdapter( + new PlainDatagramSocketImpl(fd, localPort), this); } return socket; } @@ -155,12 +140,7 @@ class DatagramChannelImpl extends DatagramChannel implements .preferIPv6Addresses()); } - // ------------------------------------------------------------------- - // Methods for connect and disconnect - // ------------------------------------------------------------------- - - /* - * + /** * @see java.nio.channels.DatagramChannel#isConnected() */ @Override @@ -168,8 +148,7 @@ class DatagramChannelImpl extends DatagramChannel implements return connected; } - /* - * + /** * @see java.nio.channels.DatagramChannel#connect(java.net.SocketAddress) */ @Override @@ -214,8 +193,7 @@ class DatagramChannelImpl extends DatagramChannel implements return this; } - /* - * + /** * @see java.nio.channels.DatagramChannel#disconnect() */ @Override @@ -232,12 +210,7 @@ class DatagramChannelImpl extends DatagramChannel implements return this; } - // ------------------------------------------------------------------- - // Methods for send and receive - // ------------------------------------------------------------------- - - /* - * + /** * @see java.nio.channels.DatagramChannel#receive(java.nio.ByteBuffer) */ @Override @@ -284,14 +257,15 @@ class DatagramChannelImpl extends DatagramChannel implements .position() + target.arrayOffset(), target.remaining()); } else { - receivePacket = new DatagramPacket(new byte[target.remaining()], target.remaining()); + receivePacket = new DatagramPacket(new byte[target.remaining()], + target.remaining()); } do { if (isConnected()) { - received = networkSystem.recvConnectedDatagram(fd, receivePacket, - receivePacket.getData(), receivePacket.getOffset(), - receivePacket.getLength(), isBlocking() ? 0 - : DEFAULT_TIMEOUT, false); + received = networkSystem.recvConnectedDatagram(fd, + receivePacket, receivePacket.getData(), receivePacket + .getOffset(), receivePacket.getLength(), + isBlocking() ? 0 : DEFAULT_TIMEOUT, false); } else { received = networkSystem.receiveDatagram(fd, receivePacket, receivePacket.getData(), receivePacket.getOffset(), @@ -327,24 +301,23 @@ class DatagramChannelImpl extends DatagramChannel implements return retAddr; } - private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop) throws IOException - { - SocketAddress retAddr = null; - DatagramPacket receivePacket = new DatagramPacket( - stubArray, 0); + private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop) + throws IOException { + SocketAddress retAddr = null; + DatagramPacket receivePacket = new DatagramPacket(stubArray, 0); int oldposition = target.position(); int received = 0; do { int address = AddressUtil.getDirectBufferAddress(target); if (isConnected()) { - received = networkSystem.recvConnectedDatagramDirect(fd, receivePacket, - address, target.position(), - target.remaining(), isBlocking() ? 0 + received = networkSystem.recvConnectedDatagramDirect(fd, + receivePacket, address, target.position(), target + .remaining(), isBlocking() ? 0 : DEFAULT_TIMEOUT, false); } else { - received = networkSystem.receiveDatagramDirect(fd, receivePacket, - address, target.position(), - target.remaining(), isBlocking() ? 0 + received = networkSystem.receiveDatagramDirect(fd, + receivePacket, address, target.position(), target + .remaining(), isBlocking() ? 0 : DEFAULT_TIMEOUT, false); } @@ -352,15 +325,14 @@ class DatagramChannelImpl extends DatagramChannel implements SecurityManager sm = System.getSecurityManager(); if (!isConnected() && null != sm) { try { - sm.checkAccept(receivePacket.getAddress() - .getHostAddress(), receivePacket.getPort()); + sm.checkAccept(receivePacket.getAddress().getHostAddress(), + receivePacket.getPort()); } catch (SecurityException e) { // do discard the datagram packet receivePacket = null; } } - if (null != receivePacket - && null != receivePacket.getAddress()) { + if (null != receivePacket && null != receivePacket.getAddress()) { // copy the data of received packet if (received > 0) { target.position(oldposition + received); @@ -372,7 +344,7 @@ class DatagramChannelImpl extends DatagramChannel implements return retAddr; } - /* + /** * @see java.nio.channels.DatagramChannel#send(java.nio.ByteBuffer, * java.net.SocketAddress) */ @@ -445,12 +417,7 @@ class DatagramChannelImpl extends DatagramChannel implements } } - // ------------------------------------------------------------------- - // Methods for read and write. - // ------------------------------------------------------------------- - - /* - * + /** * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer) */ @Override @@ -467,10 +434,10 @@ class DatagramChannelImpl extends DatagramChannel implements return 0; } - int readCount = 0; + int readCount = 0; if (target.isDirect() || target.hasArray()) { readCount = readImpl(target); - if(readCount > 0){ + if (readCount > 0) { target.position(target.position() + readCount); } @@ -478,15 +445,14 @@ class DatagramChannelImpl extends DatagramChannel implements byte[] readArray = new byte[target.remaining()]; ByteBuffer readBuffer = ByteBuffer.wrap(readArray); readCount = readImpl(readBuffer); - if(readCount > 0){ + if (readCount > 0) { target.put(readArray, 0, readCount); } } return readCount; } - /* - * + /** * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer[], int, * int) */ @@ -530,7 +496,7 @@ class DatagramChannelImpl extends DatagramChannel implements * read from channel, and store the result in the target. */ private int readImpl(ByteBuffer readBuffer) throws IOException { - synchronized(readLock){ + synchronized (readLock) { int readCount = 0; try { begin(); @@ -542,8 +508,9 @@ class DatagramChannelImpl extends DatagramChannel implements if (readBuffer.isDirect()) { int address = AddressUtil.getDirectBufferAddress(readBuffer); if (isConnected()) { - readCount = networkSystem.recvConnectedDatagramDirect(fd, - null, address, start, length, timeout, false); + readCount = networkSystem.recvConnectedDatagramDirect( + fd, null, address, start, length, timeout, + false); } else { readCount = networkSystem.receiveDatagramDirect(fd, null, address, start, length, timeout, false); @@ -553,11 +520,11 @@ class DatagramChannelImpl extends DatagramChannel implements byte[] target = readBuffer.array(); start += readBuffer.arrayOffset(); if (isConnected()) { - readCount = networkSystem.recvConnectedDatagram(fd, null, - target, start, length, timeout, false); + readCount = networkSystem.recvConnectedDatagram(fd, + null, target, start, length, timeout, false); } else { - readCount = networkSystem.receiveDatagram(fd, null, target, - start, length, timeout, false); + readCount = networkSystem.receiveDatagram(fd, null, + target, start, length, timeout, false); } } return readCount; @@ -570,7 +537,7 @@ class DatagramChannelImpl extends DatagramChannel implements } } - /* + /** * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer) */ @Override @@ -602,7 +569,7 @@ class DatagramChannelImpl extends DatagramChannel implements return result; } - /* + /** * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int, * int) */ @@ -621,7 +588,7 @@ class DatagramChannelImpl extends DatagramChannel implements return 0; } ByteBuffer writeBuf = ByteBuffer.allocate(count); - for (int val = offset; val < length+offset; val++) { + for (int val = offset; val < length + offset; val++) { ByteBuffer source = sources[val]; int oldPosition = source.position(); writeBuf.put(source); @@ -642,10 +609,10 @@ class DatagramChannelImpl extends DatagramChannel implements } /* - * write the source. return the count of bytes written. + * Write the source. Return the count of bytes written. */ private int writeImpl(ByteBuffer buf) throws IOException { - synchronized(writeLock){ + synchronized (writeLock) { int result = 0; try { begin(); @@ -654,13 +621,13 @@ class DatagramChannelImpl extends DatagramChannel implements if (buf.isDirect()) { int address = AddressUtil.getDirectBufferAddress(buf); - result = networkSystem.sendConnectedDatagramDirect(fd, address, - start, length, isBound); + result = networkSystem.sendConnectedDatagramDirect(fd, + address, start, length, isBound); } else { // buf is assured to have array. start += buf.arrayOffset(); - result = networkSystem.sendConnectedDatagram(fd, buf.array(), - start, length, isBound); + result = networkSystem.sendConnectedDatagram(fd, buf + .array(), start, length, isBound); } return result; } catch (SocketException e) { @@ -677,12 +644,8 @@ class DatagramChannelImpl extends DatagramChannel implements } } - // ------------------------------------------------------------------- - // Protected Inherited methods - // ------------------------------------------------------------------- - /* - * do really closing action here + * Do really closing action here. */ @Override synchronized protected void implCloseSelectableChannel() throws IOException { @@ -694,8 +657,7 @@ class DatagramChannelImpl extends DatagramChannel implements } } - /* - * + /** * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean) */ @Override @@ -707,12 +669,8 @@ class DatagramChannelImpl extends DatagramChannel implements // decided by isBlocking() method. } - // ------------------------------------------------------------------- - // Share methods for checking. - // ------------------------------------------------------------------- - /* - * status check, must be open. + * Status check, must be open. */ private void checkOpen() throws IOException { if (!isOpen()) { @@ -721,7 +679,7 @@ class DatagramChannelImpl extends DatagramChannel implements } /* - * status check, must be open and connected, for read and write. + * Status check, must be open and connected, for read and write. */ private void checkOpenConnected() throws IOException { checkOpen(); @@ -731,7 +689,7 @@ class DatagramChannelImpl extends DatagramChannel implements } /* - * buffer check, must not null + * Buffer check, must not null */ private void checkNotNull(ByteBuffer source) { if (null == source) { @@ -740,7 +698,7 @@ class DatagramChannelImpl extends DatagramChannel implements } /* - * buffer check, must not null and not read only buffer, for read and + * Buffer check, must not null and not read only buffer, for read and * receive. */ private void checkWritable(ByteBuffer target) { @@ -750,12 +708,8 @@ class DatagramChannelImpl extends DatagramChannel implements } } - // ------------------------------------------------------------------- - // Adapter classes for internal socket. - // ------------------------------------------------------------------- - /* - * get the fd for internal use. + * Get the fd for internal use. */ public FileDescriptor getFD() { return fd; @@ -781,7 +735,7 @@ class DatagramChannelImpl extends DatagramChannel implements private DatagramChannelImpl channelImpl; /* - * init the datagramSocketImpl and datagramChannelImpl + * Constructor initialize the datagramSocketImpl and datagramChannelImpl */ DatagramSocketAdapter(DatagramSocketImpl socketimpl, DatagramChannelImpl channelImpl) { @@ -790,14 +744,14 @@ class DatagramChannelImpl extends DatagramChannel implements } /* - * get the internal datagramChannelImpl + * Get the internal datagramChannelImpl */ @Override public DatagramChannel getChannel() { return channelImpl; } - /* + /** * @see java.net.DatagramSocket#isBound() */ @Override @@ -805,7 +759,7 @@ class DatagramChannelImpl extends DatagramChannel implements return channelImpl.isBound; } - /* + /** * @see java.net.DatagramSocket#isConnected() */ @Override @@ -813,7 +767,7 @@ class DatagramChannelImpl extends DatagramChannel implements return channelImpl.isConnected(); } - /* + /** * @see java.net.DatagramSocket#getInetAddress() */ @Override @@ -824,7 +778,7 @@ class DatagramChannelImpl extends DatagramChannel implements return channelImpl.connectAddress.getAddress(); } - /* + /** * @see java.net.DatagramSocket#getLocalAddress() */ @Override @@ -832,7 +786,7 @@ class DatagramChannelImpl extends DatagramChannel implements return channelImpl.getLocalAddress(); } - /* + /** * @see java.net.DatagramSocket#getPort() */ @Override @@ -843,7 +797,7 @@ class DatagramChannelImpl extends DatagramChannel implements return channelImpl.connectAddress.getPort(); } - /* + /** * @see java.net.DatagramSocket#bind(java.net.SocketAddress) */ @Override @@ -855,7 +809,7 @@ class DatagramChannelImpl extends DatagramChannel implements channelImpl.isBound = true; } - /* + /** * @see java.net.DatagramSocket#receive(java.net.DatagramPacket) */ @Override @@ -866,7 +820,7 @@ class DatagramChannelImpl extends DatagramChannel implements super.receive(packet); } - /* + /** * @see java.net.DatagramSocket#send(java.net.DatagramPacket) */ @Override @@ -877,7 +831,7 @@ class DatagramChannelImpl extends DatagramChannel implements super.send(packet); } - /* + /** * @see java.net.DatagramSocket#close() */ @Override @@ -894,7 +848,7 @@ class DatagramChannelImpl extends DatagramChannel implements } } - /* + /** * @see java.net.DatagramSocket#disconnect() */ @Override diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java index 3bc368f..dbef656 100644 --- a/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java +++ b/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java @@ -17,6 +17,10 @@ package org.apache.harmony.nio.internal; +// BEGIN android-note +// Copied from a newer version of Harmony. +// END android-note + import java.io.FileDescriptor; import java.io.IOException; import java.net.ServerSocket; @@ -27,13 +31,12 @@ import java.net.SocketTimeoutException; import java.nio.channels.ClosedChannelException; import java.nio.channels.IllegalBlockingModeException; import java.nio.channels.NotYetBoundException; -import java.nio.channels.SelectableChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; import org.apache.harmony.luni.net.NetUtil; -import org.apache.harmony.luni.net.SocketImplProvider; +import org.apache.harmony.luni.net.PlainServerSocketImpl; import org.apache.harmony.luni.platform.FileDescriptorHandler; import org.apache.harmony.luni.platform.Platform; @@ -43,10 +46,6 @@ import org.apache.harmony.luni.platform.Platform; public class ServerSocketChannelImpl extends ServerSocketChannel implements FileDescriptorHandler { - // ---------------------------------------------------- - // Class variables - // ---------------------------------------------------- - // status un-init, not initialized. private static final int SERVER_STATUS_UNINIT = -1; @@ -56,10 +55,6 @@ public class ServerSocketChannelImpl extends ServerSocketChannel implements // status closed. private static final int SERVER_STATUS_CLOSED = 1; - // ------------------------------------------------------------------- - // Instance variables - // ------------------------------------------------------------------- - // The fd to interact with native code private final FileDescriptor fd; @@ -74,13 +69,9 @@ public class ServerSocketChannelImpl extends ServerSocketChannel implements boolean isBound = false; // lock for accept - private class AcceptLock {} + private static class AcceptLock {} private final Object acceptLock = new AcceptLock(); - // ---------------------------------------------------- - // Constructor - // ---------------------------------------------------- - /* * Constructor */ @@ -88,26 +79,23 @@ public class ServerSocketChannelImpl extends ServerSocketChannel implements super(sp); status = SERVER_STATUS_OPEN; fd = new FileDescriptor(); - Platform.getNetworkSystem().createServerStreamSocket(fd, + Platform.getNetworkSystem().createStreamSocket(fd, NetUtil.preferIPv4Stack()); - impl = SocketImplProvider.getServerSocketImpl(fd); + impl = new PlainServerSocketImpl(fd); socket = new ServerSocketAdapter(impl, this); } // for native call + @SuppressWarnings("unused") private ServerSocketChannelImpl() throws IOException { super(SelectorProvider.provider()); status = SERVER_STATUS_OPEN; fd = new FileDescriptor(); - impl = SocketImplProvider.getServerSocketImpl(fd); + impl = new PlainServerSocketImpl(fd); socket = new ServerSocketAdapter(impl, this); isBound = false; } - // ---------------------------------------------------- - // Methods - // ---------------------------------------------------- - /* * Getting the internal Socket If we have not the socket, we create a new * one. @@ -128,7 +116,7 @@ public class ServerSocketChannelImpl extends ServerSocketChannel implements throw new NotYetBoundException(); } - SocketChannel sockChannel = SocketChannel.open(); + SocketChannel sockChannel = new SocketChannelImpl(SelectorProvider.provider(), false); Socket socketGot = sockChannel.socket(); try { @@ -168,10 +156,6 @@ public class ServerSocketChannelImpl extends ServerSocketChannel implements return sockChannel; } - // ------------------------------------------------------------------- - // Protected inherited methods - // ------------------------------------------------------------------- - /* * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking * @@ -202,10 +186,6 @@ public class ServerSocketChannelImpl extends ServerSocketChannel implements return fd; } - // ---------------------------------------------------- - // Adapter classes. - // ---------------------------------------------------- - /* * The adapter class of ServerSocket. */ @@ -264,10 +244,7 @@ public class ServerSocketChannelImpl extends ServerSocketChannel implements synchronized (this) { super.implAccept(aSocket); sockChannel.setConnected(); - // BEGIN android-added - // copied from a newer version of harmony sockChannel.setBound(true); - // END android-added } SecurityManager sm = System.getSecurityManager(); if (sm != null) { diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java index 8e6c52f..1affb21 100644 --- a/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java +++ b/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java @@ -17,6 +17,11 @@ package org.apache.harmony.nio.internal; +// BEGIN android-note +// Copied from a newer version of Harmony. +// In this class the address length was changed from long to int. +// END android-note + import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; @@ -42,25 +47,20 @@ import java.nio.channels.UnresolvedAddressException; import java.nio.channels.UnsupportedAddressTypeException; import java.nio.channels.spi.SelectorProvider; -import org.apache.harmony.luni.net.SocketImplProvider; +import org.apache.harmony.luni.net.PlainSocketImpl; import org.apache.harmony.luni.platform.FileDescriptorHandler; import org.apache.harmony.luni.platform.INetworkSystem; import org.apache.harmony.luni.platform.Platform; import org.apache.harmony.luni.util.ErrorCodeException; +import org.apache.harmony.luni.util.Msg; import org.apache.harmony.nio.AddressUtil; import org.apache.harmony.nio.internal.nls.Messages; /* - * * The default implementation class of java.nio.channels.SocketChannel. - * */ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { - // ------------------------------------------------------------------- - // Class variables - // ------------------------------------------------------------------- - private static final int EOF = -1; private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211; @@ -68,41 +68,37 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { // The singleton to do the native network operation. static final INetworkSystem networkSystem = Platform.getNetworkSystem(); - // status un-init, not initialized. + // Status un-init, not initialized. static final int SOCKET_STATUS_UNINIT = EOF; - // status before connect. + // Status before connect. static final int SOCKET_STATUS_UNCONNECTED = 0; - // status connection pending + // Status connection pending. static final int SOCKET_STATUS_PENDING = 1; - // status after connection success + // Status after connection success. static final int SOCKET_STATUS_CONNECTED = 2; - // status closed. + // Status closed. static final int SOCKET_STATUS_CLOSED = 3; - // timeout used for non-block mode. + // Timeout used for non-block mode. private static final int TIMEOUT_NONBLOCK = 0; - // timeout used for block mode. + // Timeout used for block mode. private static final int TIMEOUT_BLOCK = EOF; - // step used for connect + // Step used for connect. private static final int HY_SOCK_STEP_START = 0; - // step used for finishConnect + // Step used for finishConnect. private static final int HY_PORT_SOCKET_STEP_CHECK = 1; - // connect success + // Connect success. private static final int CONNECT_SUCCESS = 0; - // ------------------------------------------------------------------- - // Instance Variables - // ------------------------------------------------------------------- - - // The fd to interact with native code + // The descriptor to interact with native code. FileDescriptor fd; // Our internal Socket. @@ -111,24 +107,23 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { // The address to be connected. InetSocketAddress connectAddress = null; - // Local address of the this socket (package private for adapter) + // Local address of the this socket (package private for adapter). InetAddress localAddress = null; - // local port + // Local port number. int localPort; // At first, uninitialized. int status = SOCKET_STATUS_UNINIT; - // BEGIN android-changed - // copied from a newer version of harmony - // whether the socket is bound + // Whether the socket is bound. volatile boolean isBound = false; - // END adroid-changed - private final Object readLock = new Object(); + private static class ReadLock {} + private final Object readLock = new ReadLock(); - private final Object writeLock = new Object(); + private static class WriteLock {} + private final Object writeLock = new WriteLock(); // BEGIN android-changed // this content is a struct used in connect_withtimeout(). @@ -136,30 +131,37 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { private byte[] connectContext = new byte[392]; // END android-changed - // used to store the trafficClass value which is simply returned + // Used to store the trafficClass value which is simply returned // as the value that was set. We also need it to pass it to methods - // that specify an address packets are going to be sent to + // that specify an address packets are going to be sent to. private int trafficClass = 0; - // ------------------------------------------------------------------- - // Constructor - // ------------------------------------------------------------------- - /* - * Constructor + * Constructor for creating a connected socket channel. */ public SocketChannelImpl(SelectorProvider selectorProvider) throws IOException { + this(selectorProvider, true); + } + + /* + * Constructor for creating an optionally connected socket channel. + */ + public SocketChannelImpl(SelectorProvider selectorProvider, boolean connect) + throws IOException { super(selectorProvider); fd = new FileDescriptor(); status = SOCKET_STATUS_UNCONNECTED; - networkSystem.createSocket(fd, true); + if (connect) { + networkSystem.createStreamSocket(fd, true); + } } /* - * for native call + * For native call. */ - private SocketChannelImpl(){ + @SuppressWarnings("unused") + private SocketChannelImpl() { super(SelectorProvider.provider()); fd = new FileDescriptor(); connectAddress = new InetSocketAddress(0); @@ -186,10 +188,6 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { status = SOCKET_STATUS_UNCONNECTED; } - // ------------------------------------------------------------------- - // Methods for getting internal Socket. - // ------------------------------------------------------------------- - /* * Getting the internal Socket If we have not the socket, we create a new * one. @@ -204,8 +202,8 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { addr = connectAddress.getAddress(); port = connectAddress.getPort(); } - socket = new SocketAdapter(SocketImplProvider.getSocketImpl(fd, - localPort, addr, port), this); + socket = new SocketAdapter( + new PlainSocketImpl(fd, localPort, addr, port), this); } catch (SocketException e) { return null; } @@ -213,11 +211,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return socket; } - // ------------------------------------------------------------------- - // Methods for connect and finishConnect - // ------------------------------------------------------------------- - - /* + /** * @see java.nio.channels.SocketChannel#isConnected() */ @Override @@ -226,20 +220,17 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * status setting used by other class. + * Status setting used by other class. */ synchronized void setConnected() { status = SOCKET_STATUS_CONNECTED; } - // BEGIN android-added - // copied from a newer version of harmony void setBound(boolean flag) { isBound = flag; } - // END android-added - /* + /** * @see java.nio.channels.SocketChannel#isConnectionPending() */ @Override @@ -247,7 +238,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return status == SOCKET_STATUS_PENDING; } - /* + /** * @see java.nio.channels.SocketChannel#connect(java.net.SocketAddress) */ @Override @@ -257,9 +248,15 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { // check the address InetSocketAddress inetSocketAddress = validateAddress(socketAddress); + InetAddress normalAddr = inetSocketAddress.getAddress(); + + // When connecting, map ANY address to Localhost + if (normalAddr.isAnyLocalAddress()) { + normalAddr = InetAddress.getLocalHost(); + } int port = inetSocketAddress.getPort(); - String hostName = inetSocketAddress.getAddress().getHostName(); + String hostName = normalAddr.getHostName(); // security check SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -271,23 +268,12 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { boolean finished = false; try { - if (!isBound) { - // bind - networkSystem.bind2(fd, 0, true, InetAddress - .getByAddress(new byte[] { 0, 0, 0, 0 })); - isBound = true; - } - if (isBlocking()) { begin(); - result = networkSystem.connect(fd, trafficClass, - inetSocketAddress.getAddress(), inetSocketAddress - .getPort()); - + result = networkSystem.connect(fd, trafficClass, normalAddr, port); } else { result = networkSystem.connectWithTimeout(fd, 0, trafficClass, - inetSocketAddress.getAddress(), inetSocketAddress - .getPort(), HY_SOCK_STEP_START, connectContext); + normalAddr, port, HY_SOCK_STEP_START, connectContext); // set back to nonblocking to work around with a bug in portlib if (!this.isBlocking()) { networkSystem.setNonBlocking(fd, true); @@ -328,7 +314,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return finished; } - /* + /** * @see java.nio.channels.SocketChannel#finishConnect() */ @Override @@ -372,14 +358,13 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { synchronized (this) { status = (finished ? SOCKET_STATUS_CONNECTED : status); isBound = finished; + // TPE: Workaround for bug that turns socket back to blocking + if (!isBlocking()) implConfigureBlocking(false); } return finished; } - // ------------------------------------------------------------------- - // Methods for read and write - // ------------------------------------------------------------------- - /* + /** * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer) */ @Override @@ -411,7 +396,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return readCount; } - /* + /** * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer[], int, * int) */ @@ -449,16 +434,17 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { private boolean isIndexValid(ByteBuffer[] targets, int offset, int length) { return (length >= 0) && (offset >= 0) - && ((long)length + (long)offset <= targets.length); + && ((long) length + (long) offset <= targets.length); } - /* - * read from channel, and store the result in the target. + /** + * Read from channel, and store the result in the target. * - * @param target output parameter + * @param target + * output parameter */ private int readImpl(ByteBuffer target) throws IOException { - synchronized(readLock){ + synchronized (readLock) { int readCount = 0; try { if (isBlocking()) { @@ -467,10 +453,13 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { int offset = target.position(); int length = target.remaining(); if (target.isDirect()) { + // BEGIN android-changed + // changed address from long to int; split address and offset paramters int address = AddressUtil.getDirectBufferAddress(target); readCount = networkSystem.readDirect(fd, address, offset, length, (isBlocking() ? TIMEOUT_BLOCK : TIMEOUT_NONBLOCK)); + // END android-changed } else { // target is assured to have array. byte[] array = target.array(); @@ -487,8 +476,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } } - /* - * + /** * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer) */ @Override @@ -503,7 +491,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return writeImpl(source); } - /* + /** * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer[], int, * int) */ @@ -520,7 +508,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return 0; } ByteBuffer writeBuf = ByteBuffer.allocate(count); - for (int val = offset; val < length+offset; val++) { + for (int val = offset; val < length + offset; val++) { ByteBuffer source = sources[val]; int oldPosition = source.position(); writeBuf.put(source); @@ -550,10 +538,10 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * write the source. return the count of bytes written. + * Write the source. return the count of bytes written. */ private int writeImpl(ByteBuffer source) throws IOException { - synchronized(writeLock){ + synchronized (writeLock) { if (!source.hasRemaining()) { return 0; } @@ -565,9 +553,12 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { begin(); } if (source.isDirect()) { + // BEGIN android-changed + // changed address from long to int; split address and pos parameters int address = AddressUtil.getDirectBufferAddress(source); - writeCount = networkSystem - .writeDirect(fd, address, pos, length); + writeCount = networkSystem.writeDirect(fd, address, pos, + length); + // END android-changed } else if (source.hasArray()) { pos += source.arrayOffset(); writeCount = networkSystem.write(fd, source.array(), pos, @@ -595,12 +586,8 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } } - // ------------------------------------------------------------------- - // Shared methods - // ------------------------------------------------------------------- - /* - * status check, open and "connected", when read and write. + * Status check, open and "connected", when read and write. */ synchronized private void checkOpenConnected() throws ClosedChannelException { @@ -613,7 +600,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * status check, open and "unconnected", before connection. + * Status check, open and "unconnected", before connection. */ synchronized private void checkUnconnected() throws IOException { if (!isOpen()) { @@ -628,7 +615,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * shared by this class and DatagramChannelImpl, to do the address transfer + * Shared by this class and DatagramChannelImpl, to do the address transfer * and check. */ static InetSocketAddress validateAddress(SocketAddress socketAddress) { @@ -646,7 +633,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * get local address + * Get local address. */ public InetAddress getLocalAddress() throws UnknownHostException { byte[] any_bytes = { 0, 0, 0, 0 }; @@ -656,11 +643,8 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return localAddress; } - // ------------------------------------------------------------------- - // Protected inherited methods - // ------------------------------------------------------------------- /* - * do really closing action here + * Do really closing action here. */ @Override synchronized protected void implCloseSelectableChannel() throws IOException { @@ -674,7 +658,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } } - /* + /** * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean) */ @Override @@ -685,30 +669,21 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * get the fd + * Get the fd. */ public FileDescriptor getFD() { return fd; } - // ------------------------------------------------------------------- - // Adapter classes for internal socket. - // ------------------------------------------------------------------- - + /* + * Adapter classes for internal socket. + */ private static class SocketAdapter extends Socket { - // ---------------------------------------------------- - // Class Variables - // ---------------------------------------------------- - SocketChannelImpl channel; SocketImpl socketImpl; - // ---------------------------------------------------- - // Methods - // ---------------------------------------------------- - SocketAdapter(SocketImpl socketimpl, SocketChannelImpl channel) throws SocketException { super(socketimpl); @@ -716,8 +691,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { this.channel = channel; } - /* - * + /** * @see java.net.Socket#getChannel() */ @Override @@ -725,8 +699,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return channel; } - /* - * + /** * @see java.net.Socket#isBound() */ @Override @@ -734,8 +707,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return channel.isBound; } - /* - * + /** * @see java.net.Socket#isConnected() */ @Override @@ -743,8 +715,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return channel.isConnected(); } - /* - * + /** * @see java.net.Socket#getLocalAddress() */ @Override @@ -756,8 +727,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } } - /* - * + /** * @see java.net.Socket#connect(java.net.SocketAddress, int) */ @Override @@ -778,8 +748,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } } - /* - * + /** * @see java.net.Socket#bind(java.net.SocketAddress) */ @Override @@ -798,8 +767,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } - /* - * + /** * @see java.net.Socket#close() */ @Override @@ -849,8 +817,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { .intValue(); } - /* - * + /** * @see java.net.Socket#getKeepAlive() */ @Override @@ -860,8 +827,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { .booleanValue(); } - /* - * + /** * @see java.net.Socket#getOOBInline() */ @Override @@ -871,8 +837,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { .booleanValue(); } - /* - * + /** * @see java.net.Socket#getSoLinger() */ @Override @@ -882,7 +847,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { .intValue(); } - /* + /** * @see java.net.Socket#getTcpNoDelay() */ @Override @@ -892,7 +857,82 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { .booleanValue(); } - /* + @Override + public void setKeepAlive(boolean value) throws SocketException { + checkOpen(); + socketImpl.setOption(SocketOptions.SO_KEEPALIVE, value ? Boolean.TRUE + : Boolean.FALSE); + } + + @Override + public void setOOBInline(boolean oobinline) throws SocketException { + checkOpen(); + socketImpl.setOption(SocketOptions.SO_OOBINLINE, oobinline ? Boolean.TRUE + : Boolean.FALSE); + } + + @Override + public synchronized void setReceiveBufferSize(int size) + throws SocketException { + checkOpen(); + if (size < 1) { + throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$ + } + socketImpl + .setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); + } + + @Override + public void setReuseAddress(boolean reuse) throws SocketException { + checkOpen(); + socketImpl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE + : Boolean.FALSE); + } + + @Override + public synchronized void setSendBufferSize(int size) throws SocketException { + checkOpen(); + if (size < 1) { + throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$ + } + socketImpl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); + } + + @Override + public void setSoLinger(boolean on, int timeout) throws SocketException { + checkOpen(); + if (on && timeout < 0) { + throw new IllegalArgumentException(Msg.getString("K0045")); //$NON-NLS-1$ + } + int val = on ? (65535 < timeout ? 65535 : timeout) : -1; + socketImpl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(val)); + } + + @Override + public synchronized void setSoTimeout(int timeout) throws SocketException { + checkOpen(); + if (timeout < 0) { + throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$ + } + socketImpl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); + } + + @Override + public void setTcpNoDelay(boolean on) throws SocketException { + checkOpen(); + socketImpl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on)); + } + + @Override + public void setTrafficClass(int value) throws SocketException { + checkOpen(); + if (value < 0 || value > 255) { + throw new IllegalArgumentException(); + } + socketImpl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value)); + } + + /** * @see java.net.Socket#getOutputStream() */ @Override @@ -912,8 +952,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { return new SocketChannelOutputStream(channel); } - /* - * + /** * @see java.net.Socket#getInputStream() */ @Override @@ -934,7 +973,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * Checks whether the channel is open + * Checks whether the channel is open. */ private void checkOpen() throws SocketException { if (isClosed()) { @@ -944,7 +983,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * used for net and nio exchange + * Used for net and nio exchange. */ public SocketImpl getImpl() { return socketImpl; @@ -964,7 +1003,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { } /* - * Closes this stream and channel + * Closes this stream and channel. * * @exception IOException thrown if an error occurs during the close */ @@ -973,7 +1012,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { channel.close(); } - /* + /** * @see java.io.OutputStream#write(byte[], int, int) */ @Override @@ -989,7 +1028,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { channel.write(buf); } - /* + /** * @see java.io.OutputStream#write(int) */ @Override @@ -1023,7 +1062,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { channel.close(); } - /* + /** * @see java.io.InputStream#read() */ @Override @@ -1038,7 +1077,7 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler { // END android-changed } - /* + /** * @see java.io.InputStream#read(byte[], int, int) */ @Override diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java index 6bcdaef..903c689 100644 --- a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java +++ b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java @@ -266,8 +266,6 @@ public class CharsetProviderTest extends TestCase { method = "charsetForName", args = {String.class} ) - @KnownFailure("Android throws Error in case of insufficient privileges, " + - "RI throws SecurityException") public void testIsSupported_InsufficientPrivilege() throws Exception { SecurityManager oldMan = System.getSecurityManager(); System.setSecurityManager(new MockSecurityManager()); @@ -301,8 +299,6 @@ public class CharsetProviderTest extends TestCase { method = "charsetForName", args = {String.class} ) - @KnownFailure("Android throws Error in case of insufficient privileges, " + - "RI throws SecurityException") public void testForName_InsufficientPrivilege() throws Exception { SecurityManager oldMan = System.getSecurityManager(); System.setSecurityManager(new MockSecurityManager()); diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java index dc2ec2e..0c61e75 100644 --- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java +++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java @@ -32,15 +32,25 @@ import junit.framework.TestCase; @TestTargetClass(java.util.prefs.Preferences.class) public class FilePreferencesImplTest extends TestCase { - public FilePreferencesImplTest() { - super(); - } - - @Override - protected void setUp(){ + String oldUserHome = System.getProperty("user.home"); + String oldJavaHome = System.getProperty("java.home"); + + protected void setUp() throws Exception { + super.setUp(); + + System.setProperty("user.home", System.getProperty("java.io.tmpdir")); + System.setProperty("java.home", System.getProperty("java.io.tmpdir")); + Preferences.systemRoot().clear(); + Preferences.userRoot().clear(); } - @Override - protected void tearDown(){ + + protected void tearDown() throws Exception { + Preferences.systemRoot().clear(); + Preferences.userRoot().clear(); + System.setProperty("user.home", oldUserHome); + System.setProperty("java.home", oldJavaHome); + + super.tearDown(); } @TestTargets({ diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java index 3260a04..eab3b14 100644 --- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java +++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java @@ -39,6 +39,27 @@ public class NodeChangeEventTest extends TestCase { NodeChangeEvent event; + String oldUserHome = System.getProperty("user.home"); + String oldJavaHome = System.getProperty("java.home"); + + protected void setUp() throws Exception { + super.setUp(); + + System.setProperty("user.home", System.getProperty("java.io.tmpdir")); + System.setProperty("java.home", System.getProperty("java.io.tmpdir")); + Preferences.systemRoot().clear(); + Preferences.userRoot().clear(); + } + + protected void tearDown() throws Exception { + Preferences.systemRoot().clear(); + Preferences.userRoot().clear(); + System.setProperty("user.home", oldUserHome); + System.setProperty("java.home", oldJavaHome); + + super.tearDown(); + } + @TestTargetNew( level = TestLevel.COMPLETE, notes = "", diff --git a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java index 9d526d6..0ebf6bb 100644 --- a/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java +++ b/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java @@ -45,8 +45,8 @@ import java.util.prefs.Preferences; @TestTargetClass(Preferences.class) public class PreferencesTest extends TestCase { - private String oldJavaHome; - private String oldUserHome; + String oldUserHome = System.getProperty("user.home"); + String oldJavaHome = System.getProperty("java.home"); MockSecurityManager manager = new MockSecurityManager(); @@ -81,6 +81,8 @@ public class PreferencesTest extends TestCase { .getBytes("UTF-8")); stream = new MockInputStream(in); + System.setProperty("user.home", System.getProperty("java.io.tmpdir")); + System.setProperty("java.home", System.getProperty("java.io.tmpdir")); Preferences.systemRoot().clear(); Preferences.userRoot().clear(); @@ -107,6 +109,8 @@ public class PreferencesTest extends TestCase { Preferences.systemRoot().clear(); Preferences.userRoot().clear(); + System.setProperty("user.home", oldUserHome); + System.setProperty("java.home", oldJavaHome); } @TestTargetNew( diff --git a/run-core-tests b/run-core-tests index 62b3c51..70ab320 100755 --- a/run-core-tests +++ b/run-core-tests @@ -26,5 +26,5 @@ mkdir $tmp chmod 777 $tmp exec dalvikvm -Duser.language=en -Duser.region=US -Djava.io.tmpdir=$tmp \ - -Xbootclasspath:$BOOTCLASSPATH:/system/framework/core-tests.jar \ + -classpath /system/framework/core-tests.jar \ -Xmx64M com.google.coretests.Main "$@" |
