[llvm-commits] [llvm-gcc-4.2] r43913 [43/80] - in /llvm-gcc-4.2/trunk: boehm-gc/ boehm-gc/Mac_files/ boehm-gc/cord/ boehm-gc/doc/ boehm-gc/include/ boehm-gc/include/private/ boehm-gc/tests/ libffi/ libffi/include/ libffi/src/ libffi/src/alpha/ libffi/src/arm/ libffi/src/cris/ libffi/src/frv/ libffi/src/ia64/ libffi/src/m32r/ libffi/src/m68k/ libffi/src/mips/ libffi/src/pa/ libffi/src/powerpc/ libffi/src/s390/ libffi/src/sh/ libffi/src/sh64/ libffi/src/sparc/ libffi/src/x86/ libffi/testsuite/ libffi/testsuite/config/ li...

Bill Wendling isanbard at gmail.com
Thu Nov 8 14:57:11 PST 2007


Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Collection.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Collection.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Collection.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Collection.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,288 @@
+/* Collection.java -- Interface that represents a collection of objects
+   Copyright (C) 1998, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Interface that represents a collection of objects. This interface is the
+ * root of the collection hierarchy, and does not provide any guarantees about
+ * the order of its elements or whether or not duplicate elements are
+ * permitted.
+ * <p>
+ * All methods of this interface that are defined to modify the collection are
+ * defined as <dfn>optional</dfn>. An optional operation may throw an
+ * UnsupportedOperationException if the data backing this collection does not
+ * support such a modification. This may mean that the data structure is
+ * immutable, or that it is read-only but may change ("unmodifiable"), or
+ * that it is modifiable but of fixed size (such as an array), or any number
+ * of other combinations.
+ * <p>
+ * A class that wishes to implement this interface should consider subclassing
+ * AbstractCollection, which provides basic implementations of most of the
+ * methods of this interface. Classes that are prepared to make guarantees
+ * about ordering or about absence of duplicate elements should consider
+ * implementing List or Set respectively, both of which are subinterfaces of
+ * Collection.
+ * <p>
+ * A general-purpose implementation of the Collection interface should in most
+ * cases provide at least two constructors: One which takes no arguments and
+ * creates an empty collection, and one which takes a Collection as an argument
+ * and returns a collection containing the same elements (that is, creates a
+ * copy of the argument using its own implementation).
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see List
+ * @see Set
+ * @see Map
+ * @see SortedSet
+ * @see SortedMap
+ * @see HashSet
+ * @see TreeSet
+ * @see ArrayList
+ * @see LinkedList
+ * @see Vector
+ * @see Collections
+ * @see Arrays
+ * @see AbstractCollection
+ * @since 1.2
+ * @status updated to 1.5 (minus generics)
+ */
+public interface Collection extends Iterable
+{
+  /**
+   * Add an element to this collection.
+   *
+   * @param o the object to add.
+   * @return true if the collection was modified as a result of this action.
+   * @throws UnsupportedOperationException if this collection does not
+   *   support the add operation.
+   * @throws ClassCastException if o cannot be added to this collection due
+   *   to its type.
+   * @throws NullPointerException if o is null and this collection doesn't
+   *   support the addition of null values.
+   * @throws IllegalArgumentException if o cannot be added to this
+   *   collection for some other reason.
+   */
+  boolean add(Object o);
+
+  /**
+   * Add the contents of a given collection to this collection.
+   *
+   * @param c the collection to add.
+   * @return true if the collection was modified as a result of this action.
+   * @throws UnsupportedOperationException if this collection does not
+   *   support the addAll operation.
+   * @throws ClassCastException if some element of c cannot be added to this
+   *   collection due to its type.
+   * @throws NullPointerException if some element of c is null and this
+   *   collection does not support the addition of null values.
+   * @throws NullPointerException if c itself is null.
+   * @throws IllegalArgumentException if some element of c cannot be added
+   *   to this collection for some other reason.
+   */
+  boolean addAll(Collection c);
+
+  /**
+   * Clear the collection, such that a subsequent call to isEmpty() would
+   * return true.
+   *
+   * @throws UnsupportedOperationException if this collection does not
+   *   support the clear operation.
+   */
+  void clear();
+
+  /**
+   * Test whether this collection contains a given object as one of its
+   * elements.
+   *
+   * @param o the element to look for.
+   * @return true if this collection contains at least one element e such that
+   *   <code>o == null ? e == null : o.equals(e)</code>.
+   * @throws ClassCastException if the type of o is not a valid type for this
+   *   collection.
+   * @throws NullPointerException if o is null and this collection doesn't
+   *   support null values.
+   */
+  boolean contains(Object o);
+
+  /**
+   * Test whether this collection contains every element in a given collection.
+   *
+   * @param c the collection to test for.
+   * @return true if for every element o in c, contains(o) would return true.
+   * @throws ClassCastException if the type of any element in c is not a valid
+   *   type for this collection.
+   * @throws NullPointerException if some element of c is null and this
+   *   collection does not support null values.
+   * @throws NullPointerException if c itself is null.
+   */
+  boolean containsAll(Collection c);
+
+  /**
+   * Test whether this collection is equal to some object. The Collection
+   * interface does not explicitly require any behaviour from this method, and
+   * it may be left to the default implementation provided by Object. The Set
+   * and List interfaces do, however, require specific behaviour from this
+   * method.
+   * <p>
+   * If an implementation of Collection, which is not also an implementation of
+   * Set or List, should choose to implement this method, it should take care
+   * to obey the contract of the equals method of Object. In particular, care
+   * should be taken to return false when o is a Set or a List, in order to
+   * preserve the symmetry of the relation.
+   *
+   * @param o the object to compare to this collection.
+   * @return true if the o is equal to this collection.
+   */
+  boolean equals(Object o);
+
+  /**
+   * Obtain a hash code for this collection. The Collection interface does not
+   * explicitly require any behaviour from this method, and it may be left to
+   * the default implementation provided by Object. The Set and List interfaces
+   * do, however, require specific behaviour from this method.
+   * <p>
+   * If an implementation of Collection, which is not also an implementation of
+   * Set or List, should choose to implement this method, it should take care
+   * to obey the contract of the hashCode method of Object. Note that this
+   * method renders it impossible to correctly implement both Set and List, as
+   * the required implementations are mutually exclusive.
+   *
+   * @return a hash code for this collection.
+   */
+  int hashCode();
+
+  /**
+   * Test whether this collection is empty, that is, if size() == 0.
+   *
+   * @return true if this collection contains no elements.
+   */
+  boolean isEmpty();
+
+  /**
+   * Obtain an Iterator over this collection.
+   *
+   * @return an Iterator over the elements of this collection, in any order.
+   */
+  Iterator iterator();
+
+  /**
+   * Remove a single occurrence of an object from this collection. That is,
+   * remove an element e, if one exists, such that <code>o == null ? e == null
+   *   : o.equals(e)</code>.
+   *
+   * @param o the object to remove.
+   * @return true if the collection changed as a result of this call, that is,
+   *   if the collection contained at least one occurrence of o.
+   * @throws UnsupportedOperationException if this collection does not
+   *   support the remove operation.
+   * @throws ClassCastException if the type of o is not a valid type
+   *   for this collection.
+   * @throws NullPointerException if o is null and the collection doesn't
+   *   support null values.
+   */
+  boolean remove(Object o);
+
+  /**
+   * Remove all elements of a given collection from this collection. That is,
+   * remove every element e such that c.contains(e).
+   *
+   * @param c The collection of objects to be removed.
+   * @return true if this collection was modified as a result of this call.
+   * @throws UnsupportedOperationException if this collection does not
+   *   support the removeAll operation.
+   * @throws ClassCastException if the type of any element in c is not a valid
+   *   type for this collection.
+   * @throws NullPointerException if some element of c is null and this
+   *   collection does not support removing null values.
+   * @throws NullPointerException if c itself is null.
+   */
+  boolean removeAll(Collection c);
+
+  /**
+   * Remove all elements of this collection that are not contained in a given
+   * collection. That is, remove every element e such that !c.contains(e).
+   *
+   * @param c The collection of objects to be retained.
+   * @return true if this collection was modified as a result of this call.
+   * @throws UnsupportedOperationException if this collection does not
+   *   support the retainAll operation.
+   * @throws ClassCastException if the type of any element in c is not a valid
+   *   type for this collection.
+   * @throws NullPointerException if some element of c is null and this
+   *   collection does not support retaining null values.
+   * @throws NullPointerException if c itself is null.
+   */
+  boolean retainAll(Collection c);
+
+  /**
+   * Get the number of elements in this collection.
+   *
+   * @return the number of elements in the collection.
+   */
+  int size();
+
+  /**
+   * Copy the current contents of this collection into an array.
+   *
+   * @return an array of type Object[] and length equal to the size of this
+   *   collection, containing the elements currently in this collection, in
+   *   any order.
+   */
+  Object[] toArray();
+
+  /**
+   * Copy the current contents of this collection into an array. If the array
+   * passed as an argument has length less than the size of this collection, an
+   * array of the same run-time type as a, and length equal to the size of this
+   * collection, is allocated using Reflection. Otherwise, a itself is used.
+   * The elements of this collection are copied into it, and if there is space
+   * in the array, the following element is set to null. The resultant array is
+   * returned.
+   * Note: The fact that the following element is set to null is only useful
+   * if it is known that this collection does not contain any null elements.
+   *
+   * @param a the array to copy this collection into.
+   * @return an array containing the elements currently in this collection, in
+   *   any order.
+   * @throws ArrayStoreException if the type of any element of the
+   *   collection is not a subtype of the element type of a.
+   */
+  Object[] toArray(Object[] a);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Collections.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Collections.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Collections.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Collections.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,5541 @@
+/* Collections.java -- Utility class with methods to operate on collections
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * Utility class consisting of static methods that operate on, or return
+ * Collections. Contains methods to sort, search, reverse, fill and shuffle
+ * Collections, methods to facilitate interoperability with legacy APIs that
+ * are unaware of collections, a method to return a list which consists of
+ * multiple copies of one element, and methods which "wrap" collections to give
+ * them extra properties, such as thread-safety and unmodifiability.
+ * <p>
+ *
+ * All methods which take a collection throw a {@link NullPointerException} if
+ * that collection is null. Algorithms which can change a collection may, but
+ * are not required, to throw the {@link UnsupportedOperationException} that
+ * the underlying collection would throw during an attempt at modification.
+ * For example,
+ * <code>Collections.singleton("").addAll(Collections.EMPTY_SET)</code>
+ * does not throw a exception, even though addAll is an unsupported operation
+ * on a singleton; the reason for this is that addAll did not attempt to
+ * modify the set.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Collection
+ * @see Set
+ * @see List
+ * @see Map
+ * @see Arrays
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class Collections
+{
+  /**
+   * Constant used to decide cutoff for when a non-RandomAccess list should
+   * be treated as sequential-access. Basically, quadratic behavior is
+   * acceptable for small lists when the overhead is so small in the first
+   * place. I arbitrarily set it to 16, so it may need some tuning.
+   */
+  private static final int LARGE_LIST_SIZE = 16;
+
+  /**
+   * Determines if a list should be treated as a sequential-access one.
+   * Rather than the old method of JDK 1.3 of assuming only instanceof
+   * AbstractSequentialList should be sequential, this uses the new method
+   * of JDK 1.4 of assuming anything that does NOT implement RandomAccess
+   * and exceeds a large (unspecified) size should be sequential.
+   *
+   * @param l the list to check
+   * @return <code>true</code> if it should be treated as sequential-access
+   */
+  private static boolean isSequential(List l)
+  {
+    return ! (l instanceof RandomAccess) && l.size() > LARGE_LIST_SIZE;
+  }
+
+  /**
+   * This class is non-instantiable.
+   */
+  private Collections()
+  {
+  }
+
+  /**
+   * An immutable, serializable, empty Set.
+   * @see Serializable
+   */
+  public static final Set EMPTY_SET = new EmptySet();
+
+  /**
+   * The implementation of {@link #EMPTY_SET}. This class name is required
+   * for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class EmptySet extends AbstractSet
+    implements Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 1582296315990362920L;
+
+    /**
+     * A private constructor adds overhead.
+     */
+    EmptySet()
+    {
+    }
+
+    /**
+     * The size: always 0!
+     * @return 0.
+     */
+    public int size()
+    {
+      return 0;
+    }
+
+    /**
+     * Returns an iterator that does not iterate.
+     * @return A non-iterating iterator.
+     */
+    // This is really cheating! I think it's perfectly valid, though.
+    public Iterator iterator()
+    {
+      return EMPTY_LIST.iterator();
+    }
+
+    // The remaining methods are optional, but provide a performance
+    // advantage by not allocating unnecessary iterators in AbstractSet.
+    /**
+     * The empty set never contains anything.
+     * @param o The object to search for.
+     * @return <code>false</code>.
+     */
+    public boolean contains(Object o)
+    {
+      return false;
+    }
+
+    /**
+     * This is true only if the given collection is also empty.
+     * @param c The collection of objects which are to be compared
+     *          against the members of this set.
+     * @return <code>true</code> if c is empty.
+     */
+    public boolean containsAll(Collection c)
+    {
+      return c.isEmpty();
+    }
+
+    /**
+     * Equal only if the other set is empty.
+     * @param o The object to compare with this set.
+     * @return <code>true</code> if o is an empty instance of <code>Set</code>.
+     */
+    public boolean equals(Object o)
+    {
+      return o instanceof Set && ((Set) o).isEmpty();
+    }
+
+    /**
+     * The hashcode is always 0.
+     * @return 0.
+     */
+    public int hashCode()
+    {
+      return 0;
+    }
+
+    /**
+     * Always succeeds with a <code>false</code> result.
+     * @param o The object to remove.
+     * @return <code>false</code>.
+     */
+    public boolean remove(Object o)
+    {
+      return false;
+    }
+
+    /**
+     * Always succeeds with a <code>false</code> result.
+     * @param c The collection of objects which should
+     *          all be removed from this set.
+     * @return <code>false</code>.
+     */
+    public boolean removeAll(Collection c)
+    {
+      return false;
+    }
+
+    /**
+     * Always succeeds with a <code>false</code> result.
+     * @param c The collection of objects which should
+     *          all be retained within this set.
+     * @return <code>false</code>.
+     */
+    public boolean retainAll(Collection c)
+    {
+      return false;
+    }
+
+    /**
+     * The array is always empty.
+     * @return A new array with a size of 0.
+     */
+    public Object[] toArray()
+    {
+      return new Object[0];
+    }
+
+    /**
+     * We don't even need to use reflection!
+     * @param a An existing array, which can be empty.
+     * @return The original array with any existing
+     *         initial element set to null.
+     */
+    public Object[] toArray(Object[] a)
+    {
+      if (a.length > 0)
+        a[0] = null;
+      return a;
+    }
+
+    /**
+     * The string never changes.
+     *
+     * @return the string "[]".
+     */
+    public String toString()
+    {
+      return "[]";
+    }
+  } // class EmptySet
+
+  /**
+   * An immutable, serializable, empty List, which implements RandomAccess.
+   * @see Serializable
+   * @see RandomAccess
+   */
+  public static final List EMPTY_LIST = new EmptyList();
+
+  /**
+   * The implementation of {@link #EMPTY_LIST}. This class name is required
+   * for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class EmptyList extends AbstractList
+    implements Serializable, RandomAccess
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 8842843931221139166L;
+
+    /**
+     * A private constructor adds overhead.
+     */
+    EmptyList()
+    {
+    }
+
+    /**
+     * The size is always 0.
+     * @return 0.
+     */
+    public int size()
+    {
+      return 0;
+    }
+
+    /**
+     * No matter the index, it is out of bounds.  This
+     * method never returns, throwing an exception instead.
+     *
+     * @param index The index of the element to retrieve.
+     * @return the object at the specified index.
+     * @throws IndexOutOfBoundsException as any given index
+     *         is outside the bounds of an empty array.
+     */
+    public Object get(int index)
+    {
+      throw new IndexOutOfBoundsException();
+    }
+
+    // The remaining methods are optional, but provide a performance
+    // advantage by not allocating unnecessary iterators in AbstractList.
+    /**
+     * Never contains anything.
+     * @param o The object to search for.
+     * @return <code>false</code>.
+     */
+    public boolean contains(Object o)
+    {
+      return false;
+    }
+
+    /**
+     * This is true only if the given collection is also empty.
+     * @param c The collection of objects, which should be compared
+     *          against the members of this list.
+     * @return <code>true</code> if c is also empty. 
+     */
+    public boolean containsAll(Collection c)
+    {
+      return c.isEmpty();
+    }
+
+    /**
+     * Equal only if the other list is empty.
+     * @param o The object to compare against this list.
+     * @return <code>true</code> if o is also an empty instance of
+     *         <code>List</code>.
+     */
+    public boolean equals(Object o)
+    {
+      return o instanceof List && ((List) o).isEmpty();
+    }
+
+    /**
+     * The hashcode is always 1.
+     * @return 1.
+     */
+    public int hashCode()
+    {
+      return 1;
+    }
+
+    /**
+     * Returns -1.
+     * @param o The object to search for.
+     * @return -1.
+     */
+    public int indexOf(Object o)
+    {
+      return -1;
+    }
+
+    /**
+     * Returns -1.
+     * @param o The object to search for.
+     * @return -1.
+     */
+    public int lastIndexOf(Object o)
+    {
+      return -1;
+    }
+
+    /**
+     * Always succeeds with <code>false</code> result.
+     * @param o The object to remove.
+     * @return -1.
+     */
+    public boolean remove(Object o)
+    {
+      return false;
+    }
+
+    /**
+     * Always succeeds with <code>false</code> result.
+     * @param c The collection of objects which should
+     *          all be removed from this list.
+     * @return <code>false</code>.
+     */
+    public boolean removeAll(Collection c)
+    {
+      return false;
+    }
+
+    /**
+     * Always succeeds with <code>false</code> result.
+     * @param c The collection of objects which should
+     *          all be retained within this list.
+     * @return <code>false</code>.
+     */
+    public boolean retainAll(Collection c)
+    {
+      return false;
+    }
+
+    /**
+     * The array is always empty.
+     * @return A new array with a size of 0.
+     */
+    public Object[] toArray()
+    {
+      return new Object[0];
+    }
+
+    /**
+     * We don't even need to use reflection!
+     * @param a An existing array, which can be empty.
+     * @return The original array with any existing
+     *         initial element set to null.
+     */
+    public Object[] toArray(Object[] a)
+    {
+      if (a.length > 0)
+        a[0] = null;
+      return a;
+    }
+
+    /**
+     * The string never changes.
+     *
+     * @return the string "[]".
+     */
+    public String toString()
+    {
+      return "[]";
+    }
+  } // class EmptyList
+
+  /**
+   * An immutable, serializable, empty Map.
+   * @see Serializable
+   */
+  public static final Map EMPTY_MAP = new EmptyMap();
+
+  /**
+   * The implementation of {@link #EMPTY_MAP}. This class name is required
+   * for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class EmptyMap extends AbstractMap
+    implements Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 6428348081105594320L;
+
+    /**
+     * A private constructor adds overhead.
+     */
+    EmptyMap()
+    {
+    }
+
+    /**
+     * There are no entries.
+     * @return The empty set.
+     */
+    public Set entrySet()
+    {
+      return EMPTY_SET;
+    }
+
+    // The remaining methods are optional, but provide a performance
+    // advantage by not allocating unnecessary iterators in AbstractMap.
+    /**
+     * No entries!
+     * @param key The key to search for.
+     * @return <code>false</code>.
+     */
+    public boolean containsKey(Object key)
+    {
+      return false;
+    }
+
+    /**
+     * No entries!
+     * @param value The value to search for.
+     * @return <code>false</code>.
+     */
+    public boolean containsValue(Object value)
+    {
+      return false;
+    }
+
+    /**
+     * Equal to all empty maps.
+     * @param o The object o to compare against this map.
+     * @return <code>true</code> if o is also an empty instance of
+     *         <code>Map</code>.
+     */
+    public boolean equals(Object o)
+    {
+      return o instanceof Map && ((Map) o).isEmpty();
+    }
+
+    /**
+     * No mappings, so this returns null.
+     * @param o The key of the object to retrieve.
+     * @return null. 
+     */
+    public Object get(Object o)
+    {
+      return null;
+    }
+
+    /**
+     * The hashcode is always 0.
+     * @return 0.
+     */
+    public int hashCode()
+    {
+      return 0;
+    }
+
+    /**
+     * No entries.
+     * @return The empty set.
+     */
+    public Set keySet()
+    {
+      return EMPTY_SET;
+    }
+
+    /**
+     * Remove always succeeds, with null result.
+     * @param o The key of the mapping to remove.
+     * @return null, as there is never a mapping for o.
+     */
+    public Object remove(Object o)
+    {
+      return null;
+    }
+
+    /**
+     * Size is always 0.
+     * @return 0.
+     */
+    public int size()
+    {
+      return 0;
+    }
+
+    /**
+     * No entries. Technically, EMPTY_SET, while more specific than a general
+     * Collection, will work. Besides, that's what the JDK uses!
+     * @return The empty set.
+     */
+    public Collection values()
+    {
+      return EMPTY_SET;
+    }
+
+    /**
+     * The string never changes.
+     *
+     * @return the string "[]".
+     */
+    public String toString()
+    {
+      return "[]";
+    }
+  } // class EmptyMap
+
+
+  /**
+   * Compare two objects with or without a Comparator. If c is null, uses the
+   * natural ordering. Slightly slower than doing it inline if the JVM isn't
+   * clever, but worth it for removing a duplicate of the search code.
+   * Note: This code is also used in Arrays (for sort as well as search).
+   */
+  static final int compare(Object o1, Object o2, Comparator c)
+  {
+    return c == null ? ((Comparable) o1).compareTo(o2) : c.compare(o1, o2);
+  }
+
+  /**
+   * Perform a binary search of a List for a key, using the natural ordering of
+   * the elements. The list must be sorted (as by the sort() method) - if it is
+   * not, the behavior of this method is undefined, and may be an infinite
+   * loop. Further, the key must be comparable with every item in the list. If
+   * the list contains the key more than once, any one of them may be found.
+   * <p>
+   *
+   * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
+   * and uses a linear search with O(n) link traversals and log(n) comparisons
+   * with {@link AbstractSequentialList} lists. Note: although the
+   * specification allows for an infinite loop if the list is unsorted, it will
+   * not happen in this (Classpath) implementation.
+   *
+   * @param l the list to search (must be sorted)
+   * @param key the value to search for
+   * @return the index at which the key was found, or -n-1 if it was not
+   *         found, where n is the index of the first value higher than key or
+   *         a.length if there is no such value
+   * @throws ClassCastException if key could not be compared with one of the
+   *         elements of l
+   * @throws NullPointerException if a null element has compareTo called
+   * @see #sort(List)
+   */
+  public static int binarySearch(List l, Object key)
+  {
+    return binarySearch(l, key, null);
+  }
+
+  /**
+   * Perform a binary search of a List for a key, using a supplied Comparator.
+   * The list must be sorted (as by the sort() method with the same Comparator)
+   * - if it is not, the behavior of this method is undefined, and may be an
+   * infinite loop. Further, the key must be comparable with every item in the
+   * list. If the list contains the key more than once, any one of them may be
+   * found. If the comparator is null, the elements' natural ordering is used.
+   * <p>
+   *
+   * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
+   * and uses a linear search with O(n) link traversals and log(n) comparisons
+   * with {@link AbstractSequentialList} lists. Note: although the
+   * specification allows for an infinite loop if the list is unsorted, it will
+   * not happen in this (Classpath) implementation.
+   *
+   * @param l the list to search (must be sorted)
+   * @param key the value to search for
+   * @param c the comparator by which the list is sorted
+   * @return the index at which the key was found, or -n-1 if it was not
+   *         found, where n is the index of the first value higher than key or
+   *         a.length if there is no such value
+   * @throws ClassCastException if key could not be compared with one of the
+   *         elements of l
+   * @throws NullPointerException if a null element is compared with natural
+   *         ordering (only possible when c is null)
+   * @see #sort(List, Comparator)
+   */
+  public static int binarySearch(List l, Object key, Comparator c)
+  {
+    int pos = 0;
+    int low = 0;
+    int hi = l.size() - 1;
+
+    // We use a linear search with log(n) comparisons using an iterator
+    // if the list is sequential-access.
+    if (isSequential(l))
+      {
+	ListIterator itr = l.listIterator();
+        int i = 0;
+	Object o = itr.next(); // Assumes list is not empty (see isSequential)
+	boolean forward = true;
+        while (low <= hi)
+          {
+            pos = (low + hi) >>> 1;
+            if (i < pos)
+	      {
+		if (!forward)
+		  itr.next(); // Changing direction first.
+		for ( ; i != pos; i++, o = itr.next());
+		forward = true;
+	      }
+            else
+	      {
+		if (forward)
+		  itr.previous(); // Changing direction first.
+		for ( ; i != pos; i--, o = itr.previous());
+		forward = false;
+	      }
+	    final int d = compare(o, key, c);
+	    if (d == 0)
+              return pos;
+	    else if (d > 0)
+              hi = pos - 1;
+	    else
+              // This gets the insertion point right on the last loop
+              low = ++pos;
+          }
+      }
+    else
+      {
+	while (low <= hi)
+	  {
+	    pos = (low + hi) >>> 1;
+	    final int d = compare(l.get(pos), key, c);
+	    if (d == 0)
+              return pos;
+	    else if (d > 0)
+              hi = pos - 1;
+	    else
+              // This gets the insertion point right on the last loop
+              low = ++pos;
+	  }
+      }
+
+    // If we failed to find it, we do the same whichever search we did.
+    return -pos - 1;
+  }
+
+  /**
+   * Copy one list to another. If the destination list is longer than the
+   * source list, the remaining elements are unaffected. This method runs in
+   * linear time.
+   *
+   * @param dest the destination list
+   * @param source the source list
+   * @throws IndexOutOfBoundsException if the destination list is shorter
+   *         than the source list (the destination will be unmodified)
+   * @throws UnsupportedOperationException if dest.listIterator() does not
+   *         support the set operation
+   */
+  public static void copy(List dest, List source)
+  {
+    int pos = source.size();
+    if (dest.size() < pos)
+      throw new IndexOutOfBoundsException("Source does not fit in dest");
+
+    Iterator i1 = source.iterator();
+    ListIterator i2 = dest.listIterator();
+
+    while (--pos >= 0)
+      {
+        i2.next();
+        i2.set(i1.next());
+      }
+  }
+
+  /**
+   * Returns an Enumeration over a collection. This allows interoperability
+   * with legacy APIs that require an Enumeration as input.
+   *
+   * @param c the Collection to iterate over
+   * @return an Enumeration backed by an Iterator over c
+   */
+  public static Enumeration enumeration(Collection c)
+  {
+    final Iterator i = c.iterator();
+    return new Enumeration()
+    {
+      /**
+       * Returns <code>true</code> if there are more elements to
+       * be enumerated.
+       *
+       * @return The result of <code>hasNext()</code>
+       *         called on the underlying iterator.
+       */
+      public final boolean hasMoreElements()
+      {
+	return i.hasNext();
+      }
+
+      /**
+       * Returns the next element to be enumerated.
+       *
+       * @return The result of <code>next()</code>
+       *         called on the underlying iterator.
+       */
+      public final Object nextElement()
+      {
+	return i.next();
+      }
+    };
+  }
+
+  /**
+   * Replace every element of a list with a given value. This method runs in
+   * linear time.
+   *
+   * @param l the list to fill.
+   * @param val the object to vill the list with.
+   * @throws UnsupportedOperationException if l.listIterator() does not
+   *         support the set operation.
+   */
+  public static void fill(List l, Object val)
+  {
+    ListIterator itr = l.listIterator();
+    for (int i = l.size() - 1; i >= 0; --i)
+      {
+	itr.next();
+	itr.set(val);
+      }
+  }
+
+  /**
+   * Returns the starting index where the specified sublist first occurs
+   * in a larger list, or -1 if there is no matching position. If
+   * <code>target.size() > source.size()</code>, this returns -1,
+   * otherwise this implementation uses brute force, checking for
+   * <code>source.sublist(i, i + target.size()).equals(target)</code>
+   * for all possible i.
+   *
+   * @param source the list to search
+   * @param target the sublist to search for
+   * @return the index where found, or -1
+   * @since 1.4
+   */
+  public static int indexOfSubList(List source, List target)
+  {
+    int ssize = source.size();
+    for (int i = 0, j = target.size(); j <= ssize; i++, j++)
+      if (source.subList(i, j).equals(target))
+        return i;
+    return -1;
+  }
+
+  /**
+   * Returns the starting index where the specified sublist last occurs
+   * in a larger list, or -1 if there is no matching position. If
+   * <code>target.size() > source.size()</code>, this returns -1,
+   * otherwise this implementation uses brute force, checking for
+   * <code>source.sublist(i, i + target.size()).equals(target)</code>
+   * for all possible i.
+   *
+   * @param source the list to search
+   * @param target the sublist to search for
+   * @return the index where found, or -1
+   * @since 1.4
+   */
+  public static int lastIndexOfSubList(List source, List target)
+  {
+    int ssize = source.size();
+    for (int i = ssize - target.size(), j = ssize; i >= 0; i--, j--)
+      if (source.subList(i, j).equals(target))
+        return i;
+    return -1;
+  }
+
+  /**
+   * Returns an ArrayList holding the elements visited by a given
+   * Enumeration. This method exists for interoperability between legacy
+   * APIs and the new Collection API.
+   *
+   * @param e the enumeration to put in a list
+   * @return a list containing the enumeration elements
+   * @see ArrayList
+   * @since 1.4
+   */
+  public static ArrayList list(Enumeration e)
+  {
+    ArrayList l = new ArrayList();
+    while (e.hasMoreElements())
+      l.add(e.nextElement());
+    return l;
+  }
+
+  /**
+   * Find the maximum element in a Collection, according to the natural
+   * ordering of the elements. This implementation iterates over the
+   * Collection, so it works in linear time.
+   *
+   * @param c the Collection to find the maximum element of
+   * @return the maximum element of c
+   * @exception NoSuchElementException if c is empty
+   * @exception ClassCastException if elements in c are not mutually comparable
+   * @exception NullPointerException if null.compareTo is called
+   */
+  public static Object max(Collection c)
+  {
+    return max(c, null);
+  }
+
+  /**
+   * Find the maximum element in a Collection, according to a specified
+   * Comparator. This implementation iterates over the Collection, so it
+   * works in linear time.
+   *
+   * @param c the Collection to find the maximum element of
+   * @param order the Comparator to order the elements by, or null for natural
+   *        ordering
+   * @return the maximum element of c
+   * @throws NoSuchElementException if c is empty
+   * @throws ClassCastException if elements in c are not mutually comparable
+   * @throws NullPointerException if null is compared by natural ordering
+   *        (only possible when order is null)
+   */
+  public static Object max(Collection c, Comparator order)
+  {
+    Iterator itr = c.iterator();
+    Object max = itr.next(); // throws NoSuchElementException
+    int csize = c.size();
+    for (int i = 1; i < csize; i++)
+      {
+	Object o = itr.next();
+	if (compare(max, o, order) < 0)
+	  max = o;
+      }
+    return max;
+  }
+
+  /**
+   * Find the minimum element in a Collection, according to the natural
+   * ordering of the elements. This implementation iterates over the
+   * Collection, so it works in linear time.
+   *
+   * @param c the Collection to find the minimum element of
+   * @return the minimum element of c
+   * @throws NoSuchElementException if c is empty
+   * @throws ClassCastException if elements in c are not mutually comparable
+   * @throws NullPointerException if null.compareTo is called
+   */
+  public static Object min(Collection c)
+  {
+    return min(c, null);
+  }
+
+  /**
+   * Find the minimum element in a Collection, according to a specified
+   * Comparator. This implementation iterates over the Collection, so it
+   * works in linear time.
+   *
+   * @param c the Collection to find the minimum element of
+   * @param order the Comparator to order the elements by, or null for natural
+   *        ordering
+   * @return the minimum element of c
+   * @throws NoSuchElementException if c is empty
+   * @throws ClassCastException if elements in c are not mutually comparable
+   * @throws NullPointerException if null is compared by natural ordering
+   *        (only possible when order is null)
+   */
+  public static Object min(Collection c, Comparator order)
+  {
+    Iterator itr = c.iterator();
+    Object min = itr.next();	// throws NoSuchElementExcception
+    int csize = c.size();
+    for (int i = 1; i < csize; i++)
+      {
+	Object o = itr.next();
+	if (compare(min, o, order) > 0)
+	  min = o;
+      }
+    return min;
+  }
+
+  /**
+   * Creates an immutable list consisting of the same object repeated n times.
+   * The returned object is tiny, consisting of only a single reference to the
+   * object and a count of the number of elements. It is Serializable, and
+   * implements RandomAccess. You can use it in tandem with List.addAll for
+   * fast list construction.
+   *
+   * @param n the number of times to repeat the object
+   * @param o the object to repeat
+   * @return a List consisting of n copies of o
+   * @throws IllegalArgumentException if n < 0
+   * @see List#addAll(Collection)
+   * @see Serializable
+   * @see RandomAccess
+   */
+  public static List nCopies(final int n, final Object o)
+  {
+    return new CopiesList(n, o);
+  }
+
+  /**
+   * The implementation of {@link #nCopies(int, Object)}. This class name
+   * is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class CopiesList extends AbstractList
+    implements Serializable, RandomAccess
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 2739099268398711800L;
+
+    /**
+     * The count of elements in this list.
+     * @serial the list size
+     */
+    private final int n;
+
+    /**
+     * The repeated list element.
+     * @serial the list contents
+     */
+    private final Object element;
+
+    /**
+     * Constructs the list.
+     *
+     * @param n the count
+     * @param o the object
+     * @throws IllegalArgumentException if n < 0
+     */
+    CopiesList(int n, Object o)
+    {
+      if (n < 0)
+	throw new IllegalArgumentException();
+      this.n = n;
+      element = o;
+    }
+
+    /**
+     * The size is fixed.
+     * @return The size of the list.
+     */
+    public int size()
+    {
+      return n;
+    }
+
+    /**
+     * The same element is returned.
+     * @param index The index of the element to be returned (irrelevant
+     *        as the list contains only copies of <code>element</code>).
+     * @return The element used by this list.
+     */
+    public Object get(int index)
+    {
+      if (index < 0 || index >= n)
+        throw new IndexOutOfBoundsException();
+      return element;
+    }
+
+    // The remaining methods are optional, but provide a performance
+    // advantage by not allocating unnecessary iterators in AbstractList.
+    /**
+     * This list only contains one element.
+     * @param o The object to search for.
+     * @return <code>true</code> if o is the element used by this list.
+     */
+    public boolean contains(Object o)
+    {
+      return n > 0 && equals(o, element);
+    }
+
+    /**
+     * The index is either 0 or -1.
+     * @param o The object to find the index of.
+     * @return 0 if <code>o == element</code>, -1 if not.
+     */
+    public int indexOf(Object o)
+    {
+      return (n > 0 && equals(o, element)) ? 0 : -1;
+    }
+
+    /**
+     * The index is either n-1 or -1.
+     * @param o The object to find the last index of.
+     * @return The last index in the list if <code>o == element</code>,
+     *         -1 if not.
+     */
+    public int lastIndexOf(Object o)
+    {
+      return equals(o, element) ? n - 1 : -1;
+    }
+
+    /**
+     * A subList is just another CopiesList.
+     * @param from The starting bound of the sublist.
+     * @param to The ending bound of the sublist.
+     * @return A list of copies containing <code>from - to</code>
+     *         elements, all of which are equal to the element
+     *         used by this list.
+     */
+    public List subList(int from, int to)
+    {
+      if (from < 0 || to > n)
+        throw new IndexOutOfBoundsException();
+      return new CopiesList(to - from, element);
+    }
+
+    /**
+     * The array is easy.
+     * @return An array of size n filled with copies of
+     *         the element used by this list.
+     */
+    public Object[] toArray()
+    {
+      Object[] a = new Object[n];
+      Arrays.fill(a, element);
+      return a;
+    }
+
+    /**
+     * The string is easy to generate.
+     * @return A string representation of the list.
+     */
+    public String toString()
+    {
+      StringBuffer r = new StringBuffer("{");
+      for (int i = n - 1; --i > 0; )
+        r.append(element).append(", ");
+      r.append(element).append("}");
+      return r.toString();
+    }
+  } // class CopiesList
+
+  /**
+   * Replace all instances of one object with another in the specified list.
+   * The list does not change size. An element e is replaced if
+   * <code>oldval == null ? e == null : oldval.equals(e)</code>.
+   *
+   * @param list the list to iterate over
+   * @param oldval the element to replace
+   * @param newval the new value for the element
+   * @return <code>true</code> if a replacement occurred.
+   * @throws UnsupportedOperationException if the list iterator does not allow
+   *         for the set operation
+   * @throws ClassCastException if newval is of a type which cannot be added
+   *         to the list
+   * @throws IllegalArgumentException if some other aspect of newval stops
+   *         it being added to the list
+   * @since 1.4
+   */
+  public static boolean replaceAll(List list, Object oldval, Object newval)
+  {
+    ListIterator itr = list.listIterator();
+    boolean replace_occured = false;
+    for (int i = list.size(); --i >= 0; )
+      if (AbstractCollection.equals(oldval, itr.next()))
+        {
+          itr.set(newval);
+          replace_occured = true;
+        }
+    return replace_occured;
+  }
+
+  /**
+   * Reverse a given list. This method works in linear time.
+   *
+   * @param l the list to reverse
+   * @throws UnsupportedOperationException if l.listIterator() does not
+   *         support the set operation
+   */
+  public static void reverse(List l)
+  {
+    ListIterator i1 = l.listIterator();
+    int pos1 = 1;
+    int pos2 = l.size();
+    ListIterator i2 = l.listIterator(pos2);
+    while (pos1 < pos2)
+      {
+	Object o = i1.next();
+	i1.set(i2.previous());
+	i2.set(o);
+	++pos1;
+	--pos2;
+      }
+  }
+
+  /**
+   * Get a comparator that implements the reverse of natural ordering. In
+   * other words, this sorts Comparable objects opposite of how their
+   * compareTo method would sort. This makes it easy to sort into reverse
+   * order, by simply passing Collections.reverseOrder() to the sort method.
+   * The return value of this method is Serializable.
+   *
+   * @return a comparator that imposes reverse natural ordering
+   * @see Comparable
+   * @see Serializable
+   */
+  public static Comparator reverseOrder()
+  {
+    return rcInstance;
+  }
+
+  /**
+   * The object for {@link #reverseOrder()}.
+   */
+  private static final ReverseComparator rcInstance = new ReverseComparator();
+
+  /**
+   * The implementation of {@link #reverseOrder()}. This class name
+   * is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class ReverseComparator
+    implements Comparator, Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 7207038068494060240L;
+
+    /**
+     * A private constructor adds overhead.
+     */
+    ReverseComparator()
+    {
+    }
+
+    /**
+     * Compare two objects in reverse natural order.
+     *
+     * @param a the first object
+     * @param b the second object
+     * @return <, ==, or > 0 according to b.compareTo(a)
+     */
+    public int compare(Object a, Object b)
+    {
+      return ((Comparable) b).compareTo(a);
+    }
+  }
+
+  /**
+   * Rotate the elements in a list by a specified distance. After calling this
+   * method, the element now at index <code>i</code> was formerly at index
+   * <code>(i - distance) mod list.size()</code>. The list size is unchanged.
+   * <p>
+   *
+   * For example, suppose a list contains <code>[t, a, n, k, s]</code>. After
+   * either <code>Collections.rotate(l, 4)</code> or
+   * <code>Collections.rotate(l, -1)</code>, the new contents are
+   * <code>[s, t, a, n, k]</code>. This can be applied to sublists to rotate
+   * just a portion of the list. For example, to move element <code>a</code>
+   * forward two positions in the original example, use
+   * <code>Collections.rotate(l.subList(1, 3+1), -1)</code>, which will
+   * result in <code>[t, n, k, a, s]</code>.
+   * <p>
+   *
+   * If the list is small or implements {@link RandomAccess}, the
+   * implementation exchanges the first element to its destination, then the
+   * displaced element, and so on until a circuit has been completed. The
+   * process is repeated if needed on the second element, and so forth, until
+   * all elements have been swapped.  For large non-random lists, the
+   * implementation breaks the list into two sublists at index
+   * <code>-distance mod size</code>, calls {@link #reverse(List)} on the
+   * pieces, then reverses the overall list.
+   *
+   * @param list the list to rotate
+   * @param distance the distance to rotate by; unrestricted in value
+   * @throws UnsupportedOperationException if the list does not support set
+   * @since 1.4
+   */
+  public static void rotate(List list, int distance)
+  {
+    int size = list.size();
+    if (size == 0)
+      return;
+    distance %= size;
+    if (distance == 0)
+      return;
+    if (distance < 0)
+      distance += size;
+
+    if (isSequential(list))
+      {
+        reverse(list);
+        reverse(list.subList(0, distance));
+        reverse(list.subList(distance, size));
+      }
+    else
+      {
+        // Determine the least common multiple of distance and size, as there
+        // are (distance / LCM) loops to cycle through.
+        int a = size;
+        int lcm = distance;
+        int b = a % lcm;
+        while (b != 0)
+          {
+            a = lcm;
+            lcm = b;
+            b = a % lcm;
+          }
+
+        // Now, make the swaps. We must take the remainder every time through
+        // the inner loop so that we don't overflow i to negative values.
+        while (--lcm >= 0)
+          {
+            Object o = list.get(lcm);
+            for (int i = lcm + distance; i != lcm; i = (i + distance) % size)
+              o = list.set(i, o);
+            list.set(lcm, o);
+          }
+      }
+  }
+
+  /**
+   * Shuffle a list according to a default source of randomness. The algorithm
+   * used iterates backwards over the list, swapping each element with an
+   * element randomly selected from the elements in positions less than or
+   * equal to it (using r.nextInt(int)).
+   * <p>
+   *
+   * This algorithm would result in a perfectly fair shuffle (that is, each
+   * element would have an equal chance of ending up in any position) if r were
+   * a perfect source of randomness. In practice the results are merely very
+   * close to perfect.
+   * <p>
+   *
+   * This method operates in linear time. To do this on large lists which do
+   * not implement {@link RandomAccess}, a temporary array is used to acheive
+   * this speed, since it would be quadratic access otherwise.
+   *
+   * @param l the list to shuffle
+   * @throws UnsupportedOperationException if l.listIterator() does not
+   *         support the set operation
+   */
+  public static void shuffle(List l)
+  {
+    if (defaultRandom == null)
+      {
+        synchronized (Collections.class)
+	{
+	  if (defaultRandom == null)
+            defaultRandom = new Random();
+	}
+      }
+    shuffle(l, defaultRandom);
+  }
+
+  /**
+   * Cache a single Random object for use by shuffle(List). This improves
+   * performance as well as ensuring that sequential calls to shuffle() will
+   * not result in the same shuffle order occurring: the resolution of
+   * System.currentTimeMillis() is not sufficient to guarantee a unique seed.
+   */
+  private static Random defaultRandom = null;
+
+  /**
+   * Shuffle a list according to a given source of randomness. The algorithm
+   * used iterates backwards over the list, swapping each element with an
+   * element randomly selected from the elements in positions less than or
+   * equal to it (using r.nextInt(int)).
+   * <p>
+   *
+   * This algorithm would result in a perfectly fair shuffle (that is, each
+   * element would have an equal chance of ending up in any position) if r were
+   * a perfect source of randomness. In practise (eg if r = new Random()) the
+   * results are merely very close to perfect.
+   * <p>
+   *
+   * This method operates in linear time. To do this on large lists which do
+   * not implement {@link RandomAccess}, a temporary array is used to acheive
+   * this speed, since it would be quadratic access otherwise.
+   *
+   * @param l the list to shuffle
+   * @param r the source of randomness to use for the shuffle
+   * @throws UnsupportedOperationException if l.listIterator() does not
+   *         support the set operation
+   */
+  public static void shuffle(List l, Random r)
+  {
+    int lsize = l.size();
+    ListIterator i = l.listIterator(lsize);
+    boolean sequential = isSequential(l);
+    Object[] a = null; // stores a copy of the list for the sequential case
+
+    if (sequential)
+      a = l.toArray();
+
+    for (int pos = lsize - 1; pos > 0; --pos)
+      {
+	// Obtain a random position to swap with. pos + 1 is used so that the
+	// range of the random number includes the current position.
+	int swap = r.nextInt(pos + 1);
+
+	// Swap the desired element.
+	Object o;
+        if (sequential)
+          {
+            o = a[swap];
+            a[swap] = i.previous();
+          }
+        else
+          o = l.set(swap, i.previous());
+
+	i.set(o);
+      }
+  }
+
+
+  /**
+   * Obtain an immutable Set consisting of a single element. The return value
+   * of this method is Serializable.
+   *
+   * @param o the single element
+   * @return an immutable Set containing only o
+   * @see Serializable
+   */
+  public static Set singleton(Object o)
+  {
+    return new SingletonSet(o);
+  }
+
+  /**
+   * The implementation of {@link #singleton(Object)}. This class name
+   * is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class SingletonSet extends AbstractSet
+    implements Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 3193687207550431679L;
+
+
+    /**
+     * The single element; package visible for use in nested class.
+     * @serial the singleton
+     */
+    final Object element;
+
+    /**
+     * Construct a singleton.
+     * @param o the element
+     */
+    SingletonSet(Object o)
+    {
+      element = o;
+    }
+
+    /**
+     * The size: always 1!
+     * @return 1.
+     */
+    public int size()
+    {
+      return 1;
+    }
+
+    /**
+     * Returns an iterator over the lone element.
+     */
+    public Iterator iterator()
+    {
+      return new Iterator()
+      {
+	/**
+	 * Flag to indicate whether or not the element has
+	 * been retrieved.
+	 */
+        private boolean hasNext = true;
+
+	/**
+	 * Returns <code>true</code> if elements still remain to be
+	 * iterated through.
+	 *
+	 * @return <code>true</code> if the element has not yet been returned.
+	 */
+        public boolean hasNext()
+        {
+          return hasNext;
+        }
+
+	/**
+	 * Returns the element.
+	 *
+	 * @return The element used by this singleton.
+	 * @throws NoSuchElementException if the object
+	 *         has already been retrieved.
+	 */ 
+        public Object next()
+        {
+          if (hasNext)
+          {
+            hasNext = false;
+            return element;
+          }
+          else
+            throw new NoSuchElementException();
+        }
+
+	/**
+	 * Removes the element from the singleton.
+	 * As this set is immutable, this will always
+	 * throw an exception.
+	 *
+	 * @throws UnsupportedOperationException as the
+	 *         singleton set doesn't support
+	 *         <code>remove()</code>.
+	 */
+        public void remove()
+        {
+          throw new UnsupportedOperationException();
+        }
+      };
+    }
+
+    // The remaining methods are optional, but provide a performance
+    // advantage by not allocating unnecessary iterators in AbstractSet.
+    /**
+     * The set only contains one element.
+     *
+     * @param o The object to search for.
+     * @return <code>true</code> if o == the element of the singleton.
+     */
+    public boolean contains(Object o)
+    {
+      return equals(o, element);
+    }
+
+    /**
+     * This is true if the other collection only contains the element.
+     *
+     * @param c A collection to compare against this singleton.
+     * @return <code>true</code> if c only contains either no elements or
+     *         elements equal to the element in this singleton.
+     */
+    public boolean containsAll(Collection c)
+    {
+      Iterator i = c.iterator();
+      int pos = c.size();
+      while (--pos >= 0)
+        if (! equals(i.next(), element))
+          return false;
+      return true;
+    }
+
+    /**
+     * The hash is just that of the element.
+     * 
+     * @return The hashcode of the element.
+     */
+    public int hashCode()
+    {
+      return hashCode(element);
+    }
+
+    /**
+     * Returning an array is simple.
+     *
+     * @return An array containing the element.
+     */
+    public Object[] toArray()
+    {
+      return new Object[] {element};
+    }
+
+    /**
+     * Obvious string.
+     *
+     * @return The string surrounded by enclosing
+     *         square brackets.
+     */
+    public String toString()
+    {
+      return "[" + element + "]";
+    }
+  } // class SingletonSet
+
+  /**
+   * Obtain an immutable List consisting of a single element. The return value
+   * of this method is Serializable, and implements RandomAccess.
+   *
+   * @param o the single element
+   * @return an immutable List containing only o
+   * @see Serializable
+   * @see RandomAccess
+   * @since 1.3
+   */
+  public static List singletonList(Object o)
+  {
+    return new SingletonList(o);
+  }
+
+  /**
+   * The implementation of {@link #singletonList(Object)}. This class name
+   * is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class SingletonList extends AbstractList
+    implements Serializable, RandomAccess
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 3093736618740652951L;
+
+    /**
+     * The single element.
+     * @serial the singleton
+     */
+    private final Object element;
+
+    /**
+     * Construct a singleton.
+     * @param o the element
+     */
+    SingletonList(Object o)
+    {
+      element = o;
+    }
+
+    /**
+     * The size: always 1!
+     * @return 1.
+     */
+    public int size()
+    {
+      return 1;
+    }
+
+    /**
+     * Only index 0 is valid.
+     * @param index The index of the element
+     *        to retrieve.
+     * @return The singleton's element if the
+     *         index is 0.
+     * @throws IndexOutOfBoundsException if
+     *         index is not 0.
+     */
+    public Object get(int index)
+    {
+      if (index == 0)
+        return element;
+      throw new IndexOutOfBoundsException();
+    }
+
+    // The remaining methods are optional, but provide a performance
+    // advantage by not allocating unnecessary iterators in AbstractList.
+    /**
+     * The set only contains one element.
+     *
+     * @param o The object to search for.
+     * @return <code>true</code> if o == the singleton element.
+     */
+    public boolean contains(Object o)
+    {
+      return equals(o, element);
+    }
+
+    /**
+     * This is true if the other collection only contains the element.
+     *
+     * @param c A collection to compare against this singleton.
+     * @return <code>true</code> if c only contains either no elements or
+     *         elements equal to the element in this singleton.
+     */
+    public boolean containsAll(Collection c)
+    {
+      Iterator i = c.iterator();
+      int pos = c.size();
+      while (--pos >= 0)
+        if (! equals(i.next(), element))
+          return false;
+      return true;
+    }
+
+    /**
+     * Speed up the hashcode computation.
+     *
+     * @return The hashcode of the list, based
+     *         on the hashcode of the singleton element.
+     */
+    public int hashCode()
+    {
+      return 31 + hashCode(element);
+    }
+
+    /**
+     * Either the list has it or not.
+     *
+     * @param o The object to find the first index of.
+     * @return 0 if o is the singleton element, -1 if not.
+     */
+    public int indexOf(Object o)
+    {
+      return equals(o, element) ? 0 : -1;
+    }
+
+    /**
+     * Either the list has it or not.
+     *
+     * @param o The object to find the last index of.
+     * @return 0 if o is the singleton element, -1 if not.
+     */
+    public int lastIndexOf(Object o)
+    {
+      return equals(o, element) ? 0 : -1;
+    }
+
+    /**
+     * Sublists are limited in scope.
+     * 
+     * @param from The starting bound for the sublist.
+     * @param to The ending bound for the sublist.
+     * @return Either an empty list if both bounds are
+     *         0 or 1, or this list if the bounds are 0 and 1.
+     * @throws IllegalArgumentException if <code>from > to</code>
+     * @throws IndexOutOfBoundsException if either bound is greater
+     *         than 1.
+     */
+    public List subList(int from, int to)
+    {
+      if (from == to && (to == 0 || to == 1))
+        return EMPTY_LIST;
+      if (from == 0 && to == 1)
+        return this;
+      if (from > to)
+        throw new IllegalArgumentException();
+      throw new IndexOutOfBoundsException();
+    }
+
+    /**
+     * Returning an array is simple.
+     *
+     * @return An array containing the element.
+     */
+    public Object[] toArray()
+    {
+      return new Object[] {element};
+    }
+
+    /**
+     * Obvious string.
+     *
+     * @return The string surrounded by enclosing
+     *         square brackets. 
+     */
+    public String toString()
+    {
+      return "[" + element + "]";
+    }
+  } // class SingletonList
+
+  /**
+   * Obtain an immutable Map consisting of a single key-value pair.
+   * The return value of this method is Serializable.
+   *
+   * @param key the single key
+   * @param value the single value
+   * @return an immutable Map containing only the single key-value pair
+   * @see Serializable
+   * @since 1.3
+   */
+  public static Map singletonMap(Object key, Object value)
+  {
+    return new SingletonMap(key, value);
+  }
+
+  /**
+   * The implementation of {@link #singletonMap(Object, Object)}. This class
+   * name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class SingletonMap extends AbstractMap
+    implements Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -6979724477215052911L;
+
+    /**
+     * The single key.
+     * @serial the singleton key
+     */
+    private final Object k;
+
+    /**
+     * The corresponding value.
+     * @serial the singleton value
+     */
+    private final Object v;
+
+    /**
+     * Cache the entry set.
+     */
+    private transient Set entries;
+
+    /**
+     * Construct a singleton.
+     * @param key the key
+     * @param value the value
+     */
+    SingletonMap(Object key, Object value)
+    {
+      k = key;
+      v = value;
+    }
+
+    /**
+     * There is a single immutable entry.
+     *
+     * @return A singleton containing the map entry.
+     */
+    public Set entrySet()
+    {
+      if (entries == null)
+        entries = singleton(new AbstractMap.BasicMapEntry(k, v)
+        {
+	  /**
+	   * Sets the value of the map entry to the supplied value.
+	   * An exception is always thrown, as the map is immutable.
+	   *
+	   * @param o The new value.
+	   * @return The old value.
+	   * @throws UnsupportedOperationException as setting the value
+	   *         is not supported.
+	   */
+          public Object setValue(Object o)
+          {
+            throw new UnsupportedOperationException();
+          }
+        });
+      return entries;
+    }
+
+    // The remaining methods are optional, but provide a performance
+    // advantage by not allocating unnecessary iterators in AbstractMap.
+    /**
+     * Single entry.
+     *
+     * @param key The key to look for.
+     * @return <code>true</code> if the key is the same as the one used by
+     *         this map.
+     */
+    public boolean containsKey(Object key)
+    {
+      return equals(key, k);
+    }
+
+    /**
+     * Single entry.
+     *
+     * @param value The value to look for.
+     * @return <code>true</code> if the value is the same as the one used by
+     *         this map.
+     */
+    public boolean containsValue(Object value)
+    {
+      return equals(value, v);
+    }
+
+    /**
+     * Single entry.
+     *
+     * @param key The key of the value to be retrieved.
+     * @return The singleton value if the key is the same as the
+     *         singleton key, null otherwise.
+     */
+    public Object get(Object key)
+    {
+      return equals(key, k) ? v : null;
+    }
+
+    /**
+     * Calculate the hashcode directly.
+     *
+     * @return The hashcode computed from the singleton key
+     *         and the singleton value.
+     */
+    public int hashCode()
+    {
+      return hashCode(k) ^ hashCode(v);
+    }
+
+    /**
+     * Return the keyset.
+     *
+     * @return A singleton containing the key.
+     */
+    public Set keySet()
+    {
+      if (keys == null)
+        keys = singleton(k);
+      return keys;
+    }
+
+    /**
+     * The size: always 1!
+     *
+     * @return 1.
+     */
+    public int size()
+    {
+      return 1;
+    }
+
+    /**
+     * Return the values. Technically, a singleton, while more specific than
+     * a general Collection, will work. Besides, that's what the JDK uses!
+     *
+     * @return A singleton containing the value.
+     */
+    public Collection values()
+    {
+      if (values == null)
+        values = singleton(v);
+      return values;
+    }
+
+    /**
+     * Obvious string.
+     *
+     * @return A string containing the string representations of the key
+     *         and its associated value.
+     */
+    public String toString()
+    {
+      return "{" + k + "=" + v + "}";
+    }
+  } // class SingletonMap
+
+  /**
+   * Sort a list according to the natural ordering of its elements. The list
+   * must be modifiable, but can be of fixed size. The sort algorithm is
+   * precisely that used by Arrays.sort(Object[]), which offers guaranteed
+   * nlog(n) performance. This implementation dumps the list into an array,
+   * sorts the array, and then iterates over the list setting each element from
+   * the array.
+   *
+   * @param l the List to sort
+   * @throws ClassCastException if some items are not mutually comparable
+   * @throws UnsupportedOperationException if the List is not modifiable
+   * @throws NullPointerException if some element is null
+   * @see Arrays#sort(Object[])
+   */
+  public static void sort(List l)
+  {
+    sort(l, null);
+  }
+
+  /**
+   * Sort a list according to a specified Comparator. The list must be
+   * modifiable, but can be of fixed size. The sort algorithm is precisely that
+   * used by Arrays.sort(Object[], Comparator), which offers guaranteed
+   * nlog(n) performance. This implementation dumps the list into an array,
+   * sorts the array, and then iterates over the list setting each element from
+   * the array.
+   *
+   * @param l the List to sort
+   * @param c the Comparator specifying the ordering for the elements, or
+   *        null for natural ordering
+   * @throws ClassCastException if c will not compare some pair of items
+   * @throws UnsupportedOperationException if the List is not modifiable
+   * @throws NullPointerException if null is compared by natural ordering
+   *        (only possible when c is null)
+   * @see Arrays#sort(Object[], Comparator)
+   */
+  public static void sort(List l, Comparator c)
+  {
+    Object[] a = l.toArray();
+    Arrays.sort(a, c);
+    ListIterator i = l.listIterator();
+    for (int pos = 0, alen = a.length;  pos < alen;  pos++)
+      {
+        i.next();
+        i.set(a[pos]);
+      }
+  }
+
+  /**
+   * Swaps the elements at the specified positions within the list. Equal
+   * positions have no effect.
+   *
+   * @param l the list to work on
+   * @param i the first index to swap
+   * @param j the second index
+   * @throws UnsupportedOperationException if list.set is not supported
+   * @throws IndexOutOfBoundsException if either i or j is < 0 or >=
+   *         list.size()
+   * @since 1.4
+   */
+  public static void swap(List l, int i, int j)
+  {
+    l.set(i, l.set(j, l.get(i)));
+  }
+
+
+  /**
+   * Returns a synchronized (thread-safe) collection wrapper backed by the
+   * given collection. Notice that element access through the iterators
+   * is thread-safe, but if the collection can be structurally modified
+   * (adding or removing elements) then you should synchronize around the
+   * iteration to avoid non-deterministic behavior:<br>
+   * <pre>
+   * Collection c = Collections.synchronizedCollection(new Collection(...));
+   * ...
+   * synchronized (c)
+   *   {
+   *     Iterator i = c.iterator();
+   *     while (i.hasNext())
+   *       foo(i.next());
+   *   }
+   * </pre><p>
+   *
+   * Since the collection might be a List or a Set, and those have incompatible
+   * equals and hashCode requirements, this relies on Object's implementation
+   * rather than passing those calls on to the wrapped collection. The returned
+   * Collection implements Serializable, but can only be serialized if
+   * the collection it wraps is likewise Serializable.
+   *
+   * @param c the collection to wrap
+   * @return a synchronized view of the collection
+   * @see Serializable
+   */
+  public static Collection synchronizedCollection(Collection c)
+  {
+    return new SynchronizedCollection(c);
+  }
+
+  /**
+   * The implementation of {@link #synchronizedCollection(Collection)}. This
+   * class name is required for compatibility with Sun's JDK serializability.
+   * Package visible, so that collections such as the one for
+   * Hashtable.values() can specify which object to synchronize on.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  static class SynchronizedCollection
+    implements Collection, Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 3053995032091335093L;
+
+    /**
+     * The wrapped collection. Package visible for use by subclasses.
+     * @serial the real collection
+     */
+    final Collection c;
+
+    /**
+     * The object to synchronize on.  When an instance is created via public
+     * methods, it will be this; but other uses like SynchronizedMap.values()
+     * must specify another mutex. Package visible for use by subclasses.
+     * @serial the lock
+     */
+    final Object mutex;
+
+    /**
+     * Wrap a given collection.
+     * @param c the collection to wrap
+     * @throws NullPointerException if c is null
+     */
+    SynchronizedCollection(Collection c)
+    {
+      this.c = c;
+      mutex = this;
+      if (c == null)
+        throw new NullPointerException();
+    }
+
+    /**
+     * Called only by trusted code to specify the mutex as well as the
+     * collection.
+     * @param sync the mutex
+     * @param c the collection
+     */
+    SynchronizedCollection(Object sync, Collection c)
+    {
+      this.c = c;
+      mutex = sync;
+    }
+
+    /**
+     * Adds the object to the underlying collection, first
+     * obtaining a lock on the mutex.
+     *
+     * @param o The object to add.
+     * @return <code>true</code> if the collection was modified as a result
+     *         of this action.
+     * @throws UnsupportedOperationException if this collection does not
+     *         support the add operation.
+     * @throws ClassCastException if o cannot be added to this collection due
+     *         to its type.
+     * @throws NullPointerException if o is null and this collection doesn't
+     *         support the addition of null values.
+     * @throws IllegalArgumentException if o cannot be added to this
+     *         collection for some other reason.
+     */
+    public boolean add(Object o)
+    {
+      synchronized (mutex)
+        {
+          return c.add(o);
+        }
+    }
+
+    /**
+     * Adds the objects in col to the underlying collection, first
+     * obtaining a lock on the mutex.
+     *
+     * @param col The collection to take the new objects from.
+     * @return <code>true</code> if the collection was modified as a result
+     *          of this action.
+     * @throws UnsupportedOperationException if this collection does not
+     *         support the addAll operation.
+     * @throws ClassCastException if some element of col cannot be added to this
+     *         collection due to its type.
+     * @throws NullPointerException if some element of col is null and this
+     *         collection does not support the addition of null values.
+     * @throws NullPointerException if col itself is null.
+     * @throws IllegalArgumentException if some element of col cannot be added
+     *         to this collection for some other reason.
+     */
+    public boolean addAll(Collection col)
+    {
+      synchronized (mutex)
+        {
+          return c.addAll(col);
+        }
+    }
+
+    /**
+     * Removes all objects from the underlying collection,
+     * first obtaining a lock on the mutex.
+     *
+     * @throws UnsupportedOperationException if this collection does not
+     *         support the clear operation.
+     */
+    public void clear()
+    {
+      synchronized (mutex)
+        {
+          c.clear();
+        }
+    }
+
+    /**
+     * Checks for the existence of o within the underlying
+     * collection, first obtaining a lock on the mutex.
+     *
+     * @param o the element to look for.
+     * @return <code>true</code> if this collection contains at least one
+     *         element e such that <code>o == null ? e == null : o.equals(e)</code>.
+     * @throws ClassCastException if the type of o is not a valid type for this
+     *         collection.
+     * @throws NullPointerException if o is null and this collection doesn't
+     *         support null values.
+     */
+    public boolean contains(Object o)
+    {
+      synchronized (mutex)
+        {
+          return c.contains(o);
+        }
+    }
+
+    /**
+     * Checks for the existence of each object in cl
+     * within the underlying collection, first obtaining
+     * a lock on the mutex.
+     *
+     * @param c1 the collection to test for.
+     * @return <code>true</code> if for every element o in c, contains(o)
+     *         would return <code>true</code>.
+     * @throws ClassCastException if the type of any element in cl is not a valid
+     *         type for this collection.
+     * @throws NullPointerException if some element of cl is null and this
+     *         collection does not support null values.
+     * @throws NullPointerException if cl itself is null.
+     */
+    public boolean containsAll(Collection c1)
+    {
+      synchronized (mutex)
+        {
+          return c.containsAll(c1);
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if there are no objects in the underlying
+     * collection.  A lock on the mutex is obtained before the
+     * check is performed.
+     *
+     * @return <code>true</code> if this collection contains no elements.
+     */
+    public boolean isEmpty()
+    {
+      synchronized (mutex)
+        {
+          return c.isEmpty();
+        }
+    }
+
+    /**
+     * Returns a synchronized iterator wrapper around the underlying
+     * collection's iterator.  A lock on the mutex is obtained before
+     * retrieving the collection's iterator.
+     *
+     * @return An iterator over the elements in the underlying collection,
+     *         which returns each element in any order.
+     */
+    public Iterator iterator()
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedIterator(mutex, c.iterator());
+        }
+    }
+
+    /**
+     * Removes the specified object from the underlying collection,
+     * first obtaining a lock on the mutex.
+     *
+     * @param o The object to remove.
+     * @return <code>true</code> if the collection changed as a result of this call, that is,
+     *         if the collection contained at least one occurrence of o.
+     * @throws UnsupportedOperationException if this collection does not
+     *         support the remove operation.
+     * @throws ClassCastException if the type of o is not a valid type
+     *         for this collection.
+     * @throws NullPointerException if o is null and the collection doesn't
+     *         support null values.
+     */
+    public boolean remove(Object o)
+    {
+      synchronized (mutex)
+        {
+          return c.remove(o);
+        }
+    }
+
+    /**
+     * Removes all elements, e, of the underlying
+     * collection for which <code>col.contains(e)</code>
+     * returns <code>true</code>.  A lock on the mutex is obtained
+     * before the operation proceeds.
+     *
+     * @param col The collection of objects to be removed.
+     * @return <code>true</code> if this collection was modified as a result of this call.
+     * @throws UnsupportedOperationException if this collection does not
+     *   support the removeAll operation.
+     * @throws ClassCastException if the type of any element in c is not a valid
+     *   type for this collection.
+     * @throws NullPointerException if some element of c is null and this
+     *   collection does not support removing null values.
+     * @throws NullPointerException if c itself is null.
+     */
+    public boolean removeAll(Collection col)
+    {
+      synchronized (mutex)
+        {
+          return c.removeAll(col);
+        }
+    }
+
+    /**
+     * Retains all elements, e, of the underlying
+     * collection for which <code>col.contains(e)</code>
+     * returns <code>true</code>.  That is, every element that doesn't
+     * exist in col is removed.  A lock on the mutex is obtained
+     * before the operation proceeds.
+     *
+     * @param col The collection of objects to be removed.
+     * @return <code>true</code> if this collection was modified as a result of this call.
+     * @throws UnsupportedOperationException if this collection does not
+     *   support the removeAll operation.
+     * @throws ClassCastException if the type of any element in c is not a valid
+     *   type for this collection.
+     * @throws NullPointerException if some element of c is null and this
+     *   collection does not support removing null values.
+     * @throws NullPointerException if c itself is null.
+     */
+    public boolean retainAll(Collection col)
+    {
+      synchronized (mutex)
+        {
+          return c.retainAll(col);
+        }
+    }
+
+    /**
+     * Retrieves the size of the underlying collection.
+     * A lock on the mutex is obtained before the collection
+     * is accessed.
+     *
+     * @return The size of the collection.
+     */
+    public int size()
+    {
+      synchronized (mutex)
+        {
+          return c.size();
+        }
+    }
+
+    /**
+     * Returns an array containing each object within the underlying
+     * collection.  A lock is obtained on the mutex before the collection
+     * is accessed.
+     *
+     * @return An array of objects, matching the collection in size.  The
+     *         elements occur in any order.
+     */
+    public Object[] toArray()
+    {
+      synchronized (mutex)
+        {
+          return c.toArray();
+        }
+    }
+
+    /**
+     * Copies the elements in the underlying collection to the supplied
+     * array.  If <code>a.length < size()</code>, a new array of the
+     * same run-time type is created, with a size equal to that of
+     * the collection.  If <code>a.length > size()</code>, then the
+     * elements from 0 to <code>size() - 1</code> contain the elements
+     * from this collection.  The following element is set to null
+     * to indicate the end of the collection objects.  However, this
+     * only makes a difference if null is not a permitted value within
+     * the collection.
+     * Before the copying takes place, a lock is obtained on the mutex.
+     *
+     * @param a An array to copy elements to.
+     * @return An array containing the elements of the underlying collection.
+     * @throws ArrayStoreException if the type of any element of the
+     *         collection is not a subtype of the element type of a.
+     */
+    public Object[] toArray(Object[] a)
+    {
+      synchronized (mutex)
+        {
+          return c.toArray(a);
+        }
+    }
+
+    /**
+     * Returns a string representation of the underlying collection.
+     * A lock is obtained on the mutex before the string is created.
+     *
+     * @return A string representation of the collection.
+     */
+    public String toString()
+    {
+      synchronized (mutex)
+        {
+          return c.toString();
+        }
+    }
+  } // class SynchronizedCollection
+
+  /**
+   * The implementation of the various iterator methods in the
+   * synchronized classes. These iterators must "sync" on the same object
+   * as the collection they iterate over.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class SynchronizedIterator implements Iterator
+  {
+    /**
+     * The object to synchronize on. Package visible for use by subclass.
+     */
+    final Object mutex;
+
+    /**
+     * The wrapped iterator.
+     */
+    private final Iterator i;
+
+    /**
+     * Only trusted code creates a wrapper, with the specified sync.
+     * @param sync the mutex
+     * @param i the wrapped iterator
+     */
+    SynchronizedIterator(Object sync, Iterator i)
+    {
+      this.i = i;
+      mutex = sync;
+    }
+
+    /**
+     * Retrieves the next object in the underlying collection.
+     * A lock is obtained on the mutex before the collection is accessed.
+     * 
+     * @return The next object in the collection.
+     * @throws NoSuchElementException if there are no more elements
+     */
+    public Object next()
+    {
+      synchronized (mutex)
+        {
+          return i.next();
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if objects can still be retrieved from the iterator
+     * using <code>next()</code>.  A lock is obtained on the mutex before
+     * the collection is accessed.
+     *
+     * @return <code>true</code> if at least one element is still to be returned by
+     *         <code>next()</code>.
+     */
+    public boolean hasNext()
+    {
+      synchronized (mutex)
+        {
+          return i.hasNext();
+        }
+    }
+
+    /**
+     * Removes the object that was last returned by <code>next()</code>
+     * from the underlying collection.  Only one call to this method is
+     * allowed per call to the <code>next()</code> method, and it does
+     * not affect the value that will be returned by <code>next()</code>.
+     * Thus, if element n was retrieved from the collection by
+     * <code>next()</code>, it is this element that gets removed.
+     * Regardless of whether this takes place or not, element n+1 is
+     * still returned on the subsequent <code>next()</code> call.
+     *
+     * @throws IllegalStateException if next has not yet been called or remove
+     *         has already been called since the last call to next.
+     * @throws UnsupportedOperationException if this Iterator does not support
+     *         the remove operation.
+     */
+    public void remove()
+    {
+      synchronized (mutex)
+        {
+          i.remove();
+        }
+    }
+  } // class SynchronizedIterator
+
+  /**
+   * Returns a synchronized (thread-safe) list wrapper backed by the
+   * given list. Notice that element access through the iterators
+   * is thread-safe, but if the list can be structurally modified
+   * (adding or removing elements) then you should synchronize around the
+   * iteration to avoid non-deterministic behavior:<br>
+   * <pre>
+   * List l = Collections.synchronizedList(new List(...));
+   * ...
+   * synchronized (l)
+   *   {
+   *     Iterator i = l.iterator();
+   *     while (i.hasNext())
+   *       foo(i.next());
+   *   }
+   * </pre><p>
+   *
+   * The returned List implements Serializable, but can only be serialized if
+   * the list it wraps is likewise Serializable. In addition, if the wrapped
+   * list implements RandomAccess, this does too.
+   *
+   * @param l the list to wrap
+   * @return a synchronized view of the list
+   * @see Serializable
+   * @see RandomAccess
+   */
+  public static List synchronizedList(List l)
+  {
+    if (l instanceof RandomAccess)
+      return new SynchronizedRandomAccessList(l);
+    return new SynchronizedList(l);
+  }
+
+  /**
+   * The implementation of {@link #synchronizedList(List)} for sequential
+   * lists. This class name is required for compatibility with Sun's JDK
+   * serializability. Package visible, so that lists such as Vector.subList()
+   * can specify which object to synchronize on.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  static class SynchronizedList extends SynchronizedCollection
+    implements List
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -7754090372962971524L;
+
+    /**
+     * The wrapped list; stored both here and in the superclass to avoid
+     * excessive casting. Package visible for use by subclass.
+     * @serial the wrapped list
+     */
+    final List list;
+
+    /**
+     * Wrap a given list.
+     * @param l the list to wrap
+     * @throws NullPointerException if l is null
+     */
+    SynchronizedList(List l)
+    {
+      super(l);
+      list = l;
+    }
+
+    /**
+     * Called only by trusted code to specify the mutex as well as the list.
+     * @param sync the mutex
+     * @param l the list
+     */
+    SynchronizedList(Object sync, List l)
+    {
+      super(sync, l);
+      list = l;
+    }
+
+  /**
+   * Insert an element into the underlying list at a given position (optional
+   * operation).  This shifts all existing elements from that position to the
+   * end one index to the right. This version of add has no return, since it is
+   * assumed to always succeed if there is no exception.  Before the
+   * addition takes place, a lock is obtained on the mutex.
+   *
+   * @param index the location to insert the item
+   * @param o the object to insert
+   * @throws UnsupportedOperationException if this list does not support the
+   *         add operation
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   * @throws ClassCastException if o cannot be added to this list due to its
+   *         type
+   * @throws IllegalArgumentException if o cannot be added to this list for
+   *         some other reason
+   * @throws NullPointerException if o is null and this list doesn't support
+   *         the addition of null values.
+   */
+    public void add(int index, Object o)
+    {
+      synchronized (mutex)
+        {
+          list.add(index, o);
+        }
+    }
+
+  /**
+   * Add the contents of a collection to the underlying list at the given
+   * index (optional operation).  If the list imposes restraints on what 
+   * can be inserted, such as no null elements, this should be documented.
+   * A lock is obtained on the mutex before any of the elements are added.
+   *
+   * @param index the index at which to insert
+   * @param c the collection to add
+   * @return <code>true</code>, as defined by Collection for a modified list
+   * @throws UnsupportedOperationException if this list does not support the
+   *         add operation
+   * @throws ClassCastException if o cannot be added to this list due to its
+   *         type
+   * @throws IllegalArgumentException if o cannot be added to this list for
+   *         some other reason
+   * @throws NullPointerException if o is null and this list doesn't support
+   *         the addition of null values.
+   */
+    public boolean addAll(int index, Collection c)
+    {
+      synchronized (mutex)
+        {
+          return list.addAll(index, c);
+        }
+    }
+
+   /**
+    * Tests whether the underlying list is equal to the supplied object.
+    * The object is deemed to be equal if it is also a <code>List</code>
+    * of equal size and with the same elements (i.e. each element, e1,
+    * in list, l1, and each element, e2, in l2, must return <code>true</code> for
+    * <code>e1 == null ? e2 == null : e1.equals(e2)</code>.  Before the
+    * comparison is made, a lock is obtained on the mutex.
+    *
+    * @param o The object to test for equality with the underlying list.
+    * @return <code>true</code> if o is equal to the underlying list under the above
+    *         definition.
+    */
+    public boolean equals(Object o)
+    {
+      synchronized (mutex)
+        {
+          return list.equals(o);
+        }
+    }
+
+    /**
+     * Retrieves the object at the specified index.  A lock
+     * is obtained on the mutex before the list is accessed.
+     *
+     * @param index the index of the element to be returned
+     * @return the element at index index in this list
+     * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+     */
+    public Object get(int index)
+    {
+      synchronized (mutex)
+        {
+          return list.get(index);
+        }
+    }
+
+    /**
+     * Obtains a hashcode for the underlying list, first obtaining
+     * a lock on the mutex.  The calculation of the hashcode is
+     * detailed in the documentation for the <code>List</code>
+     * interface.
+     *
+     * @return The hashcode of the underlying list.
+     * @see List#hashCode()
+     */
+    public int hashCode()
+    {
+      synchronized (mutex)
+        {
+          return list.hashCode();
+        }
+    }
+
+    /**
+     * Obtain the first index at which a given object is to be found in the
+     * underlying list.  A lock is obtained on the mutex before the list is
+     * accessed.
+     *
+     * @param o the object to search for
+     * @return the least integer n such that <code>o == null ? get(n) == null :
+     *         o.equals(get(n))</code>, or -1 if there is no such index.
+     * @throws ClassCastException if the type of o is not a valid
+     *         type for this list.
+     * @throws NullPointerException if o is null and this
+     *         list does not support null values.
+     */
+
+    public int indexOf(Object o)
+    {
+      synchronized (mutex)
+        {
+          return list.indexOf(o);
+        }
+    }
+
+    /**
+     * Obtain the last index at which a given object is to be found in this
+     * underlying list.  A lock is obtained on the mutex before the list
+     * is accessed.
+     *
+     * @return the greatest integer n such that <code>o == null ? get(n) == null
+     *         : o.equals(get(n))</code>, or -1 if there is no such index.
+     * @throws ClassCastException if the type of o is not a valid
+     *         type for this list.
+     * @throws NullPointerException if o is null and this
+     *         list does not support null values.
+     */
+    public int lastIndexOf(Object o)
+    {
+      synchronized (mutex)
+        {
+          return list.lastIndexOf(o);
+        }
+    }
+
+    /**
+     * Retrieves a synchronized wrapper around the underlying list's
+     * list iterator.  A lock is obtained on the mutex before the
+     * list iterator is retrieved.
+     *
+     * @return A list iterator over the elements in the underlying list.
+     *         The list iterator allows additional list-specific operations
+     *         to be performed, in addition to those supplied by the
+     *         standard iterator.
+     */
+    public ListIterator listIterator()
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedListIterator(mutex, list.listIterator());
+        }
+    }
+
+    /**
+     * Retrieves a synchronized wrapper around the underlying list's
+     * list iterator.  A lock is obtained on the mutex before the
+     * list iterator is retrieved.  The iterator starts at the
+     * index supplied, leading to the element at that index being
+     * the first one returned by <code>next()</code>.  Calling
+     * <code>previous()</code> from this initial position returns
+     * index - 1.
+     *
+     * @param index the position, between 0 and size() inclusive, to begin the
+     *        iteration from
+     * @return A list iterator over the elements in the underlying list.
+     *         The list iterator allows additional list-specific operations
+     *         to be performed, in addition to those supplied by the
+     *         standard iterator.
+     * @throws IndexOutOfBoundsException if index < 0 || index > size()
+     */
+    public ListIterator listIterator(int index)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedListIterator(mutex, list.listIterator(index));
+        }
+    }
+
+    /**
+     * Remove the element at a given position in the underlying list (optional
+     * operation).  All remaining elements are shifted to the left to fill the gap.
+     * A lock on the mutex is obtained before the element is removed.
+     *
+     * @param index the position within the list of the object to remove
+     * @return the object that was removed
+     * @throws UnsupportedOperationException if this list does not support the
+     *         remove operation
+     * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+     */
+    public Object remove(int index)
+    {
+      synchronized (mutex)
+        {
+          return list.remove(index);
+        }
+    }
+
+  /**
+   * Replace an element of the underlying list with another object (optional
+   * operation).  A lock is obtained on the mutex before the element is
+   * replaced.
+   *
+   * @param index the position within this list of the element to be replaced
+   * @param o the object to replace it with
+   * @return the object that was replaced
+   * @throws UnsupportedOperationException if this list does not support the
+   *         set operation.
+   * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+   * @throws ClassCastException if o cannot be added to this list due to its
+   *         type
+   * @throws IllegalArgumentException if o cannot be added to this list for
+   *         some other reason
+   * @throws NullPointerException if o is null and this
+   *         list does not support null values.
+   */
+    public Object set(int index, Object o)
+    {
+      synchronized (mutex)
+        {
+          return list.set(index, o);
+        }
+    }
+
+    /**
+     * Obtain a List view of a subsection of the underlying list, from fromIndex
+     * (inclusive) to toIndex (exclusive). If the two indices are equal, the
+     * sublist is empty. The returned list should be modifiable if and only
+     * if this list is modifiable. Changes to the returned list should be
+     * reflected in this list. If this list is structurally modified in
+     * any way other than through the returned list, the result of any subsequent
+     * operations on the returned list is undefined.  A lock is obtained
+     * on the mutex before the creation of the sublist.  The returned list
+     * is also synchronized, using the same mutex.
+     *
+     * @param fromIndex the index that the returned list should start from
+     *        (inclusive)
+     * @param toIndex the index that the returned list should go to (exclusive)
+     * @return a List backed by a subsection of this list
+     * @throws IndexOutOfBoundsException if fromIndex < 0
+     *         || toIndex > size() || fromIndex > toIndex
+     */
+    public List subList(int fromIndex, int toIndex)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedList(mutex, list.subList(fromIndex, toIndex));
+        }
+    }
+  } // class SynchronizedList
+
+  /**
+   * The implementation of {@link #synchronizedList(List)} for random-access
+   * lists. This class name is required for compatibility with Sun's JDK
+   * serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class SynchronizedRandomAccessList
+    extends SynchronizedList implements RandomAccess
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 1530674583602358482L;
+
+    /**
+     * Wrap a given list.
+     * @param l the list to wrap
+     * @throws NullPointerException if l is null
+     */
+    SynchronizedRandomAccessList(List l)
+    {
+      super(l);
+    }
+
+    /**
+     * Called only by trusted code to specify the mutex as well as the
+     * collection.
+     * @param sync the mutex
+     * @param l the list
+     */
+    SynchronizedRandomAccessList(Object sync, List l)
+    {
+      super(sync, l);
+    }
+
+    /**
+     * Obtain a List view of a subsection of the underlying list, from fromIndex
+     * (inclusive) to toIndex (exclusive). If the two indices are equal, the
+     * sublist is empty. The returned list should be modifiable if and only
+     * if this list is modifiable. Changes to the returned list should be
+     * reflected in this list. If this list is structurally modified in
+     * any way other than through the returned list, the result of any subsequent
+     * operations on the returned list is undefined.    A lock is obtained
+     * on the mutex before the creation of the sublist.  The returned list
+     * is also synchronized, using the same mutex.  Random accessibility
+     * is also extended to the new list.
+     *
+     * @param fromIndex the index that the returned list should start from
+     *        (inclusive)
+     * @param toIndex the index that the returned list should go to (exclusive)
+     * @return a List backed by a subsection of this list
+     * @throws IndexOutOfBoundsException if fromIndex < 0
+     *         || toIndex > size() || fromIndex > toIndex
+     */
+    public List subList(int fromIndex, int toIndex)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedRandomAccessList(mutex,
+                                                  list.subList(fromIndex,
+                                                               toIndex));
+        }
+    }
+  } // class SynchronizedRandomAccessList
+
+  /**
+   * The implementation of {@link SynchronizedList#listIterator()}. This
+   * iterator must "sync" on the same object as the list it iterates over.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class SynchronizedListIterator
+    extends SynchronizedIterator implements ListIterator
+  {
+    /**
+     * The wrapped iterator, stored both here and in the superclass to
+     * avoid excessive casting.
+     */
+    private final ListIterator li;
+
+    /**
+     * Only trusted code creates a wrapper, with the specified sync.
+     * @param sync the mutex
+     * @param li the wrapped iterator
+     */
+    SynchronizedListIterator(Object sync, ListIterator li)
+    {
+      super(sync, li);
+      this.li = li;
+    }
+
+    /**
+     * Insert an element into the underlying list at the current position of
+     * the iterator (optional operation). The element is inserted in between
+     * the element that would be returned by <code>previous()</code> and the
+     * element that would be returned by <code>next()</code>. After the
+     * insertion, a subsequent call to next is unaffected, but
+     * a call to previous returns the item that was added. The values returned
+     * by nextIndex() and previousIndex() are incremented.  A lock is obtained
+     * on the mutex before the addition takes place.
+     *
+     * @param o the object to insert into the list
+     * @throws ClassCastException if the object is of a type which cannot be added
+     *         to this list.
+     * @throws IllegalArgumentException if some other aspect of the object stops
+     *         it being added to this list.
+     * @throws UnsupportedOperationException if this ListIterator does not
+     *         support the add operation.
+     */
+    public void add(Object o)
+    {
+      synchronized (mutex)
+        {
+          li.add(o);
+        }
+    }
+
+    /**
+     * Tests whether there are elements remaining in the underlying list
+     * in the reverse direction. In other words, <code>previous()</code>
+     * will not fail with a NoSuchElementException.  A lock is obtained
+     * on the mutex before the check takes place.
+     *
+     * @return <code>true</code> if the list continues in the reverse direction
+     */
+    public boolean hasPrevious()
+    {
+      synchronized (mutex)
+        {
+          return li.hasPrevious();
+        }
+    }
+
+    /**
+      * Find the index of the element that would be returned by a call to
+      * <code>next()</code>.  If hasNext() returns <code>false</code>, this
+      * returns the list size.  A lock is obtained on the mutex before the
+      * query takes place.
+      *
+      * @return the index of the element that would be returned by next()
+      */
+    public int nextIndex()
+    {
+      synchronized (mutex)
+        {
+          return li.nextIndex();
+        }
+    }
+
+    /**
+     * Obtain the previous element from the underlying list. Repeated
+     * calls to previous may be used to iterate backwards over the entire list,
+     * or calls to next and previous may be used together to go forwards and
+     * backwards. Alternating calls to next and previous will return the same
+     * element.  A lock is obtained on the mutex before the object is retrieved.
+     *
+     * @return the next element in the list in the reverse direction
+     * @throws NoSuchElementException if there are no more elements
+     */
+    public Object previous()
+    {
+      synchronized (mutex)
+        {
+          return li.previous();
+        }
+    }
+
+    /**
+     * Find the index of the element that would be returned by a call to
+     * previous. If hasPrevious() returns <code>false</code>, this returns -1.
+     * A lock is obtained on the mutex before the query takes place.
+     *
+     * @return the index of the element that would be returned by previous()
+     */
+    public int previousIndex()
+    {
+      synchronized (mutex)
+        {
+          return li.previousIndex();
+        }
+    }
+
+    /**
+     * Replace the element last returned by a call to <code>next()</code> or
+     * <code>previous()</code> with a given object (optional operation).  This
+     * method may only be called if neither <code>add()</code> nor
+     * <code>remove()</code> have been called since the last call to
+     * <code>next()</code> or <code>previous</code>.  A lock is obtained
+     * on the mutex before the list is modified.
+     *
+     * @param o the object to replace the element with
+     * @throws ClassCastException the object is of a type which cannot be added
+     *         to this list
+     * @throws IllegalArgumentException some other aspect of the object stops
+     *         it being added to this list
+     * @throws IllegalStateException if neither next or previous have been
+     *         called, or if add or remove has been called since the last call
+     *         to next or previous
+     * @throws UnsupportedOperationException if this ListIterator does not
+     *         support the set operation
+     */
+    public void set(Object o)
+    {
+      synchronized (mutex)
+        {
+          li.set(o);
+        }
+    }
+  } // class SynchronizedListIterator
+
+  /**
+   * Returns a synchronized (thread-safe) map wrapper backed by the given
+   * map. Notice that element access through the collection views and their
+   * iterators are thread-safe, but if the map can be structurally modified
+   * (adding or removing elements) then you should synchronize around the
+   * iteration to avoid non-deterministic behavior:<br>
+   * <pre>
+   * Map m = Collections.synchronizedMap(new Map(...));
+   * ...
+   * Set s = m.keySet(); // safe outside a synchronized block
+   * synchronized (m) // synch on m, not s
+   *   {
+   *     Iterator i = s.iterator();
+   *     while (i.hasNext())
+   *       foo(i.next());
+   *   }
+   * </pre><p>
+   *
+   * The returned Map implements Serializable, but can only be serialized if
+   * the map it wraps is likewise Serializable.
+   *
+   * @param m the map to wrap
+   * @return a synchronized view of the map
+   * @see Serializable
+   */
+  public static Map synchronizedMap(Map m)
+  {
+    return new SynchronizedMap(m);
+  }
+
+  /**
+   * The implementation of {@link #synchronizedMap(Map)}. This
+   * class name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class SynchronizedMap implements Map, Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 1978198479659022715L;
+
+    /**
+     * The wrapped map.
+     * @serial the real map
+     */
+    private final Map m;
+
+    /**
+     * The object to synchronize on.  When an instance is created via public
+     * methods, it will be this; but other uses like
+     * SynchronizedSortedMap.subMap() must specify another mutex. Package
+     * visible for use by subclass.
+     * @serial the lock
+     */
+    final Object mutex;
+
+    /**
+     * Cache the entry set.
+     */
+    private transient Set entries;
+
+    /**
+     * Cache the key set.
+     */
+    private transient Set keys;
+
+    /**
+     * Cache the value collection.
+     */
+    private transient Collection values;
+
+    /**
+     * Wrap a given map.
+     * @param m the map to wrap
+     * @throws NullPointerException if m is null
+     */
+    SynchronizedMap(Map m)
+    {
+      this.m = m;
+      mutex = this;
+      if (m == null)
+        throw new NullPointerException();
+    }
+
+    /**
+     * Called only by trusted code to specify the mutex as well as the map.
+     * @param sync the mutex
+     * @param m the map
+     */
+    SynchronizedMap(Object sync, Map m)
+    {
+      this.m = m;
+      mutex = sync;
+    }
+
+    /**
+     * Clears all the entries from the underlying map.  A lock is obtained
+     * on the mutex before the map is cleared.
+     *
+     * @throws UnsupportedOperationException if clear is not supported
+     */
+    public void clear()
+    {
+      synchronized (mutex)
+        {
+          m.clear();
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if the underlying map contains a entry for the given key.
+     * A lock is obtained on the mutex before the map is queried.
+     *
+     * @param key the key to search for.
+     * @return <code>true</code> if the underlying map contains the key.
+     * @throws ClassCastException if the key is of an inappropriate type.
+     * @throws NullPointerException if key is <code>null</code> but the map
+     *         does not permit null keys.
+     */
+    public boolean containsKey(Object key)
+    {
+      synchronized (mutex)
+        {
+          return m.containsKey(key);
+        }
+    }
+
+  /**
+   * Returns <code>true</code> if the underlying map contains at least one entry with the
+   * given value.  In other words, returns <code>true</code> if a value v exists where
+   * <code>(value == null ? v == null : value.equals(v))</code>. This usually
+   * requires linear time.  A lock is obtained on the mutex before the map
+   * is queried.
+   *
+   * @param value the value to search for
+   * @return <code>true</code> if the map contains the value
+   * @throws ClassCastException if the type of the value is not a valid type
+   *         for this map.
+   * @throws NullPointerException if the value is null and the map doesn't
+   *         support null values.
+   */
+    public boolean containsValue(Object value)
+    {
+      synchronized (mutex)
+        {
+          return m.containsValue(value);
+        }
+    }
+
+    // This is one of the ickiest cases of nesting I've ever seen. It just
+    // means "return a SynchronizedSet, except that the iterator() method
+    // returns an SynchronizedIterator whose next() method returns a
+    // synchronized wrapper around its normal return value".
+    public Set entrySet()
+    {
+      // Define this here to spare some nesting.
+      class SynchronizedMapEntry implements Map.Entry
+      {
+        final Map.Entry e;
+        SynchronizedMapEntry(Object o)
+        {
+          e = (Map.Entry) o;
+        }
+
+	/**
+	 * Returns <code>true</code> if the object, o, implements <code>Map.Entry</code>
+	 * with the same key and value as the underlying entry.  A lock is
+	 * obtained on the mutex before the comparison takes place.
+	 *
+	 * @param o The object to compare with this entry.
+	 * @return <code>true</code> if o is equivalent to the underlying map entry.
+	 */
+        public boolean equals(Object o)
+        {
+          synchronized (mutex)
+            {
+              return e.equals(o);
+            }
+        }
+
+	/**
+	 * Returns the key used in the underlying map entry.  A lock is obtained
+	 * on the mutex before the key is retrieved.
+	 *
+	 * @return The key of the underlying map entry.
+	 */
+        public Object getKey()
+        {
+          synchronized (mutex)
+            {
+              return e.getKey();
+            }
+        }
+
+	/**
+	 * Returns the value used in the underlying map entry.  A lock is obtained
+	 * on the mutex before the value is retrieved.
+	 *
+	 * @return The value of the underlying map entry.
+	 */
+        public Object getValue()
+        {
+          synchronized (mutex)
+            {
+              return e.getValue();
+            }
+        }
+
+	/**
+	 * Computes the hash code for the underlying map entry.
+	 * This computation is described in the documentation for the
+	 * <code>Map</code> interface.  A lock is obtained on the mutex
+	 * before the underlying map is accessed.
+	 *
+	 * @return The hash code of the underlying map entry.
+	 * @see Map#hashCode()
+	 */
+        public int hashCode()
+        {
+          synchronized (mutex)
+            {
+              return e.hashCode();
+            }
+        }
+
+	/**
+	 * Replaces the value in the underlying map entry with the specified
+	 * object (optional operation).  A lock is obtained on the mutex
+	 * before the map is altered.  The map entry, in turn, will alter
+	 * the underlying map object.  The operation is undefined if the
+	 * <code>remove()</code> method of the iterator has been called
+	 * beforehand.
+	 *
+	 * @param value the new value to store
+	 * @return the old value
+	 * @throws UnsupportedOperationException if the operation is not supported.
+	 * @throws ClassCastException if the value is of the wrong type.
+	 * @throws IllegalArgumentException if something about the value
+	 *         prevents it from existing in this map.
+	 * @throws NullPointerException if the map forbids null values.
+	 */
+        public Object setValue(Object value)
+        {
+          synchronized (mutex)
+            {
+              return e.setValue(value);
+            }
+        }
+
+	/**
+	 * Returns a textual representation of the underlying map entry.
+	 * A lock is obtained on the mutex before the entry is accessed.
+	 *
+	 * @return The contents of the map entry in <code>String</code> form.
+	 */
+        public String toString()
+        {
+          synchronized (mutex)
+            {
+              return e.toString();
+            }
+        }
+      } // class SynchronizedMapEntry
+
+      // Now the actual code.
+      if (entries == null)
+        synchronized (mutex)
+          {
+            entries = new SynchronizedSet(mutex, m.entrySet())
+            {
+	      /**
+	       * Returns an iterator over the set.  The iterator has no specific order,
+	       * unless further specified.  A lock is obtained on the set's mutex
+	       * before the iterator is created.  The created iterator is also
+	       * thread-safe.
+	       *
+	       * @return A synchronized set iterator.
+	       */
+	      public Iterator iterator()
+              {
+                synchronized (super.mutex)
+                  {
+                    return new SynchronizedIterator(super.mutex, c.iterator())
+                    {
+		      /**
+		       * Retrieves the next map entry from the iterator.
+		       * A lock is obtained on the iterator's mutex before
+		       * the entry is created.  The new map entry is enclosed in
+		       * a thread-safe wrapper.
+		       *
+		       * @return A synchronized map entry.
+		       */
+                      public Object next()
+                      {
+                        synchronized (super.mutex)
+                          {
+                            return new SynchronizedMapEntry(super.next());
+                          }
+                      }
+                    };
+                  }
+              }
+            };
+          }
+      return entries;
+    }
+
+    /**
+     * Returns <code>true</code> if the object, o, is also an instance
+     * of <code>Map</code> and contains an equivalent
+     * entry set to that of the underlying map.  A lock
+     * is obtained on the mutex before the objects are
+     * compared.
+     *
+     * @param o The object to compare.
+     * @return <code>true</code> if o and the underlying map are equivalent.
+     */
+    public boolean equals(Object o)
+    {
+      synchronized (mutex)
+        {
+          return m.equals(o);
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null
+     * if no such mapping exists.  An ambiguity exists with maps
+     * that accept null values as a return value of null could
+     * be due to a non-existent mapping or simply a null value
+     * for that key.  To resolve this, <code>containsKey</code>
+     * should be used.  A lock is obtained on the mutex before
+     * the value is retrieved from the underlying map.
+     *
+     * @param key The key of the required mapping.
+     * @return The value associated with the given key, or
+     *         null if no such mapping exists.
+     * @throws ClassCastException if the key is an inappropriate type.
+     * @throws NullPointerException if this map does not accept null keys.
+     */
+    public Object get(Object key)
+    {
+      synchronized (mutex)
+        {
+          return m.get(key);
+        }
+    }
+
+    /**
+     * Calculates the hash code of the underlying map as the
+     * sum of the hash codes of all entries.  A lock is obtained
+     * on the mutex before the hash code is computed.
+     *
+     * @return The hash code of the underlying map.
+     */
+    public int hashCode()
+    {
+      synchronized (mutex)
+        {
+          return m.hashCode();
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if the underlying map contains no entries.
+     * A lock is obtained on the mutex before the map is examined.
+     *
+     * @return <code>true</code> if the map is empty.
+     */
+    public boolean isEmpty()
+    {
+      synchronized (mutex)
+        {
+          return m.isEmpty();
+        }
+    }
+
+    /**
+     * Returns a thread-safe set view of the keys in the underlying map.  The
+     * set is backed by the map, so that changes in one show up in the other.
+     * Modifications made while an iterator is in progress cause undefined
+     * behavior.  If the set supports removal, these methods remove the
+     * underlying mapping from the map: <code>Iterator.remove</code>,
+     * <code>Set.remove</code>, <code>removeAll</code>, <code>retainAll</code>,
+     * and <code>clear</code>.  Element addition, via <code>add</code> or
+     * <code>addAll</code>, is not supported via this set.  A lock is obtained
+     * on the mutex before the set is created.
+     *
+     * @return A synchronized set containing the keys of the underlying map.
+     */
+    public Set keySet()
+    {
+      if (keys == null)
+        synchronized (mutex)
+          {
+            keys = new SynchronizedSet(mutex, m.keySet());
+          }
+      return keys;
+    }
+
+    /**
+     * Associates the given key to the given value (optional operation). If the
+     * underlying map already contains the key, its value is replaced. Be aware
+     * that in a map that permits <code>null</code> values, a null return does not
+     * always imply that the mapping was created.  A lock is obtained on the mutex
+     * before the modification is made.
+     *
+     * @param key the key to map.
+     * @param value the value to be mapped.
+     * @return the previous value of the key, or null if there was no mapping
+     * @throws UnsupportedOperationException if the operation is not supported
+     * @throws ClassCastException if the key or value is of the wrong type
+     * @throws IllegalArgumentException if something about this key or value
+     *         prevents it from existing in this map
+     * @throws NullPointerException if either the key or the value is null,
+     *         and the map forbids null keys or values
+     * @see #containsKey(Object)
+     */
+    public Object put(Object key, Object value)
+    {
+      synchronized (mutex)
+        {
+          return m.put(key, value);
+        }
+    }
+
+    /**
+     * Copies all entries of the given map to the underlying one (optional
+     * operation). If the map already contains a key, its value is replaced.
+     * A lock is obtained on the mutex before the operation proceeds.
+     *
+     * @param map the mapping to load into this map
+     * @throws UnsupportedOperationException if the operation is not supported
+     * @throws ClassCastException if a key or value is of the wrong type
+     * @throws IllegalArgumentException if something about a key or value
+     *         prevents it from existing in this map
+     * @throws NullPointerException if the map forbids null keys or values, or
+     *         if <code>m</code> is null.
+     * @see #put(Object, Object)
+     */
+    public void putAll(Map map)
+    {
+      synchronized (mutex)
+        {
+          m.putAll(map);
+        }
+    }
+
+    /**
+     * Removes the mapping for the key, o, if present (optional operation). If
+     * the key is not present, this returns null. Note that maps which permit
+     * null values may also return null if the key was removed.  A prior
+     * <code>containsKey()</code> check is required to avoid this ambiguity.
+     * Before the mapping is removed, a lock is obtained on the mutex.
+     *
+     * @param o the key to remove
+     * @return the value the key mapped to, or null if not present
+     * @throws UnsupportedOperationException if deletion is unsupported
+     * @throws NullPointerException if the key is null and this map doesn't
+     *         support null keys.
+     * @throws ClassCastException if the type of the key is not a valid type
+     *         for this map.
+     */
+    public Object remove(Object o)
+    {
+      synchronized (mutex)
+        {
+          return m.remove(o);
+        }
+    }
+
+    /**
+     * Retrieves the size of the underlying map.  A lock
+     * is obtained on the mutex before access takes place.
+     * Maps with a size greater than <code>Integer.MAX_VALUE</code>
+     * return <code>Integer.MAX_VALUE</code> instead.
+     *
+     * @return The size of the underlying map.
+     */
+    public int size()
+    {
+      synchronized (mutex)
+        {
+          return m.size();
+        }
+    }
+
+    /**
+     * Returns a textual representation of the underlying
+     * map.  A lock is obtained on the mutex before the map
+     * is accessed.
+     *
+     * @return The map in <code>String</code> form.
+     */
+    public String toString()
+    {
+      synchronized (mutex)
+        {
+          return m.toString();
+        }
+    }
+
+    /**
+     * Returns a synchronized collection view of the values in the underlying
+     * map.  The collection is backed by the map, so that changes in one show up in
+     * the other.  Modifications made while an iterator is in progress cause
+     * undefined behavior.  If the collection supports removal, these methods
+     * remove the underlying mapping from the map: <code>Iterator.remove</code>,
+     * <code>Collection.remove</code>, <code>removeAll</code>,
+     * <code>retainAll</code>, and <code>clear</code>. Element addition, via
+     * <code>add</code> or <code>addAll</code>, is not supported via this
+     * collection.  A lock is obtained on the mutex before the collection
+     * is created.
+     * 
+     * @return the collection of all values in the underlying map.
+     */
+    public Collection values()
+    {
+      if (values == null)
+        synchronized (mutex)
+          {
+            values = new SynchronizedCollection(mutex, m.values());
+          }
+      return values;
+    }
+  } // class SynchronizedMap
+
+  /**
+   * Returns a synchronized (thread-safe) set wrapper backed by the given
+   * set. Notice that element access through the iterator is thread-safe, but
+   * if the set can be structurally modified (adding or removing elements)
+   * then you should synchronize around the iteration to avoid
+   * non-deterministic behavior:<br>
+   * <pre>
+   * Set s = Collections.synchronizedSet(new Set(...));
+   * ...
+   * synchronized (s)
+   *   {
+   *     Iterator i = s.iterator();
+   *     while (i.hasNext())
+   *       foo(i.next());
+   *   }
+   * </pre><p>
+   *
+   * The returned Set implements Serializable, but can only be serialized if
+   * the set it wraps is likewise Serializable.
+   *
+   * @param s the set to wrap
+   * @return a synchronized view of the set
+   * @see Serializable
+   */
+  public static Set synchronizedSet(Set s)
+  {
+    return new SynchronizedSet(s);
+  }
+
+  /**
+   * The implementation of {@link #synchronizedSet(Set)}. This class
+   * name is required for compatibility with Sun's JDK serializability.
+   * Package visible, so that sets such as Hashtable.keySet()
+   * can specify which object to synchronize on.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  static class SynchronizedSet extends SynchronizedCollection
+    implements Set
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 487447009682186044L;
+
+    /**
+     * Wrap a given set.
+     * @param s the set to wrap
+     * @throws NullPointerException if s is null
+     */
+    SynchronizedSet(Set s)
+    {
+      super(s);
+    }
+
+    /**
+     * Called only by trusted code to specify the mutex as well as the set.
+     * @param sync the mutex
+     * @param s the set
+     */
+    SynchronizedSet(Object sync, Set s)
+    {
+      super(sync, s);
+    }
+
+    /**
+     * Returns <code>true</code> if the object, o, is a <code>Set</code>
+     * of the same size as the underlying set, and contains
+     * each element, e, which occurs in the underlying set.
+     * A lock is obtained on the mutex before the comparison
+     * takes place.
+     *
+     * @param o The object to compare against.
+     * @return <code>true</code> if o is an equivalent set.
+     */
+    public boolean equals(Object o)
+    {
+      synchronized (mutex)
+        {
+          return c.equals(o);
+        }
+    }
+
+    /**
+     * Computes the hash code for the underlying set as the
+     * sum of the hash code of all elements within the set.
+     * A lock is obtained on the mutex before the computation
+     * occurs.
+     *
+     * @return The hash code for the underlying set.
+     */
+    public int hashCode()
+    {
+      synchronized (mutex)
+        {
+          return c.hashCode();
+        }
+    }
+  } // class SynchronizedSet
+
+  /**
+   * Returns a synchronized (thread-safe) sorted map wrapper backed by the
+   * given map. Notice that element access through the collection views,
+   * subviews, and their iterators are thread-safe, but if the map can be
+   * structurally modified (adding or removing elements) then you should
+   * synchronize around the iteration to avoid non-deterministic behavior:<br>
+   * <pre>
+   * SortedMap m = Collections.synchronizedSortedMap(new SortedMap(...));
+   * ...
+   * Set s = m.keySet(); // safe outside a synchronized block
+   * SortedMap m2 = m.headMap(foo); // safe outside a synchronized block
+   * Set s2 = m2.keySet(); // safe outside a synchronized block
+   * synchronized (m) // synch on m, not m2, s or s2
+   *   {
+   *     Iterator i = s.iterator();
+   *     while (i.hasNext())
+   *       foo(i.next());
+   *     i = s2.iterator();
+   *     while (i.hasNext())
+   *       bar(i.next());
+   *   }
+   * </pre><p>
+   *
+   * The returned SortedMap implements Serializable, but can only be
+   * serialized if the map it wraps is likewise Serializable.
+   *
+   * @param m the sorted map to wrap
+   * @return a synchronized view of the sorted map
+   * @see Serializable
+   */
+  public static SortedMap synchronizedSortedMap(SortedMap m)
+  {
+    return new SynchronizedSortedMap(m);
+  }
+
+  /**
+   * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
+   * class name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class SynchronizedSortedMap extends SynchronizedMap
+    implements SortedMap
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -8798146769416483793L;
+
+    /**
+     * The wrapped map; stored both here and in the superclass to avoid
+     * excessive casting.
+     * @serial the wrapped map
+     */
+    private final SortedMap sm;
+
+    /**
+     * Wrap a given map.
+     * @param sm the map to wrap
+     * @throws NullPointerException if sm is null
+     */
+    SynchronizedSortedMap(SortedMap sm)
+    {
+      super(sm);
+      this.sm = sm;
+    }
+
+    /**
+     * Called only by trusted code to specify the mutex as well as the map.
+     * @param sync the mutex
+     * @param sm the map
+     */
+    SynchronizedSortedMap(Object sync, SortedMap sm)
+    {
+      super(sync, sm);
+      this.sm = sm;
+    }
+
+    /**
+     * Returns the comparator used in sorting the underlying map, or null if
+     * it is the keys' natural ordering.  A lock is obtained on the mutex
+     * before the comparator is retrieved.
+     *
+     * @return the sorting comparator.
+     */
+    public Comparator comparator()
+    {
+      synchronized (mutex)
+        {
+          return sm.comparator();
+        }
+    }
+
+    /**
+     * Returns the first, lowest sorted, key from the underlying map.
+     * A lock is obtained on the mutex before the map is accessed.
+     *
+     * @return the first key.
+     * @throws NoSuchElementException if this map is empty.
+     */
+    public Object firstKey()
+    {
+      synchronized (mutex)
+        {
+          return sm.firstKey();
+        }
+    }
+
+    /**
+     * Returns a submap containing the keys from the first
+     * key (as returned by <code>firstKey()</code>) to
+     * the key before that specified.  The submap supports all
+     * operations supported by the underlying map and all actions
+     * taking place on the submap are also reflected in the underlying
+     * map.  A lock is obtained on the mutex prior to submap creation.
+     * This operation is equivalent to <code>subMap(firstKey(), toKey)</code>.
+     * The submap retains the thread-safe status of this map.
+     *
+     * @param toKey the exclusive upper range of the submap.
+     * @return a submap from <code>firstKey()</code> to the
+     *         the key preceding toKey.
+     * @throws ClassCastException if toKey is not comparable to the underlying
+     *         map's contents.
+     * @throws IllegalArgumentException if toKey is outside the map's range.
+     * @throws NullPointerException if toKey is null. but the map does not allow
+     *         null keys.
+     */
+    public SortedMap headMap(Object toKey)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedSortedMap(mutex, sm.headMap(toKey));
+        }
+    }
+
+    /**
+     * Returns the last, highest sorted, key from the underlying map.
+     * A lock is obtained on the mutex before the map is accessed.
+     *
+     * @return the last key.
+     * @throws NoSuchElementException if this map is empty.
+     */
+    public Object lastKey()
+    {
+      synchronized (mutex)
+        {
+          return sm.lastKey();
+        }
+    }
+
+    /**
+     * Returns a submap containing the keys from fromKey to
+     * the key before toKey.  The submap supports all
+     * operations supported by the underlying map and all actions
+     * taking place on the submap are also reflected in the underlying
+     * map.  A lock is obtained on the mutex prior to submap creation.
+     * The submap retains the thread-safe status of this map.
+     *
+     * @param fromKey the inclusive lower range of the submap.
+     * @param toKey the exclusive upper range of the submap.
+     * @return a submap from fromKey to the key preceding toKey.
+     * @throws ClassCastException if fromKey or toKey is not comparable
+     *         to the underlying map's contents.
+     * @throws IllegalArgumentException if fromKey or toKey is outside the map's
+     *         range.
+     * @throws NullPointerException if fromKey or toKey is null. but the map does
+     *         not allow  null keys.
+     */
+    public SortedMap subMap(Object fromKey, Object toKey)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedSortedMap(mutex, sm.subMap(fromKey, toKey));
+        }
+    }
+
+    /**
+     * Returns a submap containing all the keys from fromKey onwards.
+     * The submap supports all operations supported by the underlying
+     * map and all actions taking place on the submap are also reflected
+     * in the underlying map.  A lock is obtained on the mutex prior to
+     * submap creation.  The submap retains the thread-safe status of
+     * this map.
+     *
+     * @param fromKey the inclusive lower range of the submap.
+     * @return a submap from fromKey to <code>lastKey()</code>.
+     * @throws ClassCastException if fromKey is not comparable to the underlying
+     *         map's contents.
+     * @throws IllegalArgumentException if fromKey is outside the map's range.
+     * @throws NullPointerException if fromKey is null. but the map does not allow
+     *         null keys.
+     */
+    public SortedMap tailMap(Object fromKey)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedSortedMap(mutex, sm.tailMap(fromKey));
+        }
+    }
+  } // class SynchronizedSortedMap
+
+  /**
+   * Returns a synchronized (thread-safe) sorted set wrapper backed by the
+   * given set. Notice that element access through the iterator and through
+   * subviews are thread-safe, but if the set can be structurally modified
+   * (adding or removing elements) then you should synchronize around the
+   * iteration to avoid non-deterministic behavior:<br>
+   * <pre>
+   * SortedSet s = Collections.synchronizedSortedSet(new SortedSet(...));
+   * ...
+   * SortedSet s2 = s.headSet(foo); // safe outside a synchronized block
+   * synchronized (s) // synch on s, not s2
+   *   {
+   *     Iterator i = s2.iterator();
+   *     while (i.hasNext())
+   *       foo(i.next());
+   *   }
+   * </pre><p>
+   *
+   * The returned SortedSet implements Serializable, but can only be
+   * serialized if the set it wraps is likewise Serializable.
+   *
+   * @param s the sorted set to wrap
+   * @return a synchronized view of the sorted set
+   * @see Serializable
+   */
+  public static SortedSet synchronizedSortedSet(SortedSet s)
+  {
+    return new SynchronizedSortedSet(s);
+  }
+
+  /**
+   * The implementation of {@link #synchronizedSortedSet(SortedSet)}. This
+   * class name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class SynchronizedSortedSet extends SynchronizedSet
+    implements SortedSet
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 8695801310862127406L;
+
+    /**
+     * The wrapped set; stored both here and in the superclass to avoid
+     * excessive casting.
+     * @serial the wrapped set
+     */
+    private final SortedSet ss;
+
+    /**
+     * Wrap a given set.
+     * @param ss the set to wrap
+     * @throws NullPointerException if ss is null
+     */
+    SynchronizedSortedSet(SortedSet ss)
+    {
+      super(ss);
+      this.ss = ss;
+    }
+
+    /**
+     * Called only by trusted code to specify the mutex as well as the set.
+     * @param sync the mutex
+     * @param ss the set
+     */
+    SynchronizedSortedSet(Object sync, SortedSet ss)
+    {
+      super(sync, ss);
+      this.ss = ss;
+    }
+
+    /**
+     * Returns the comparator used in sorting the underlying set, or null if
+     * it is the elements' natural ordering.  A lock is obtained on the mutex
+     * before the comparator is retrieved.
+     *
+     * @return the sorting comparator.
+     */
+    public Comparator comparator()
+    {
+      synchronized (mutex)
+        {
+          return ss.comparator();
+        }
+    }
+
+    /**
+     * Returns the first, lowest sorted, element from the underlying set.
+     * A lock is obtained on the mutex before the set is accessed.
+     *
+     * @return the first element.
+     * @throws NoSuchElementException if this set is empty.
+     */
+    public Object first()
+    {
+      synchronized (mutex)
+        {
+          return ss.first();
+        }
+    }
+
+    /**
+     * Returns a subset containing the element from the first
+     * element (as returned by <code>first()</code>) to
+     * the element before that specified.  The subset supports all
+     * operations supported by the underlying set and all actions
+     * taking place on the subset are also reflected in the underlying
+     * set.  A lock is obtained on the mutex prior to subset creation.
+     * This operation is equivalent to <code>subSet(first(), toElement)</code>.
+     * The subset retains the thread-safe status of this set.
+     *
+     * @param toElement the exclusive upper range of the subset.
+     * @return a subset from <code>first()</code> to the
+     *         the element preceding toElement.
+     * @throws ClassCastException if toElement is not comparable to the underlying
+     *         set's contents.
+     * @throws IllegalArgumentException if toElement is outside the set's range.
+     * @throws NullPointerException if toElement is null. but the set does not allow
+     *         null elements.
+     */
+    public SortedSet headSet(Object toElement)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedSortedSet(mutex, ss.headSet(toElement));
+        }
+    }
+
+    /**
+     * Returns the last, highest sorted, element from the underlying set.
+     * A lock is obtained on the mutex before the set is accessed.
+     *
+     * @return the last element.
+     * @throws NoSuchElementException if this set is empty.
+     */
+    public Object last()
+    {
+      synchronized (mutex)
+        {
+          return ss.last();
+        }
+    }
+
+    /**
+     * Returns a subset containing the elements from fromElement to
+     * the element before toElement.  The subset supports all
+     * operations supported by the underlying set and all actions
+     * taking place on the subset are also reflected in the underlying
+     * set.  A lock is obtained on the mutex prior to subset creation.
+     * The subset retains the thread-safe status of this set.
+     *
+     * @param fromElement the inclusive lower range of the subset.
+     * @param toElement the exclusive upper range of the subset.
+     * @return a subset from fromElement to the element preceding toElement.
+     * @throws ClassCastException if fromElement or toElement is not comparable
+     *         to the underlying set's contents.
+     * @throws IllegalArgumentException if fromElement or toElement is outside the set's
+     *         range.
+     * @throws NullPointerException if fromElement or toElement is null. but the set does
+     *         not allow null elements.
+     */
+    public SortedSet subSet(Object fromElement, Object toElement)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedSortedSet(mutex,
+                                           ss.subSet(fromElement, toElement));
+        }
+    }
+
+    /**
+     * Returns a subset containing all the elements from fromElement onwards.
+     * The subset supports all operations supported by the underlying
+     * set and all actions taking place on the subset are also reflected
+     * in the underlying set.  A lock is obtained on the mutex prior to
+     * subset creation.  The subset retains the thread-safe status of
+     * this set.
+     *
+     * @param fromElement the inclusive lower range of the subset.
+     * @return a subset from fromElement to <code>last()</code>.
+     * @throws ClassCastException if fromElement is not comparable to the underlying
+     *         set's contents.
+     * @throws IllegalArgumentException if fromElement is outside the set's range.
+     * @throws NullPointerException if fromElement is null. but the set does not allow
+     *         null elements.
+     */
+    public SortedSet tailSet(Object fromElement)
+    {
+      synchronized (mutex)
+        {
+          return new SynchronizedSortedSet(mutex, ss.tailSet(fromElement));
+        }
+    }
+  } // class SynchronizedSortedSet
+
+
+  /**
+   * Returns an unmodifiable view of the given collection. This allows
+   * "read-only" access, although changes in the backing collection show up
+   * in this view. Attempts to modify the collection directly or via iterators
+   * will fail with {@link UnsupportedOperationException}.  Although this view
+   * prevents changes to the structure of the collection and its elements, the values
+   * referenced by the objects in the collection can still be modified.
+   * <p>
+   *
+   * Since the collection might be a List or a Set, and those have incompatible
+   * equals and hashCode requirements, this relies on Object's implementation
+   * rather than passing those calls on to the wrapped collection. The returned
+   * Collection implements Serializable, but can only be serialized if
+   * the collection it wraps is likewise Serializable.
+   *
+   * @param c the collection to wrap
+   * @return a read-only view of the collection
+   * @see Serializable
+   */
+  public static Collection unmodifiableCollection(Collection c)
+  {
+    return new UnmodifiableCollection(c);
+  }
+
+  /**
+   * The implementation of {@link #unmodifiableCollection(Collection)}. This
+   * class name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class UnmodifiableCollection
+    implements Collection, Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = 1820017752578914078L;
+
+    /**
+     * The wrapped collection. Package visible for use by subclasses.
+     * @serial the real collection
+     */
+    final Collection c;
+
+    /**
+     * Wrap a given collection.
+     * @param c the collection to wrap
+     * @throws NullPointerException if c is null
+     */
+    UnmodifiableCollection(Collection c)
+    {
+      this.c = c;
+      if (c == null)
+        throw new NullPointerException();
+    }
+
+    /**
+     * Blocks the addition of elements to the underlying collection.
+     * This method never returns, throwing an exception instead.
+     *
+     * @param o the object to add.
+     * @return <code>true</code> if the collection was modified as a result of this action.
+     * @throws UnsupportedOperationException as an unmodifiable collection does not
+     *         support the add operation.
+     */
+    public boolean add(Object o)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Blocks the addition of a collection of elements to the underlying
+     * collection.  This method never returns, throwing an exception instead.
+     *
+     * @param c the collection to add.
+     * @return <code>true</code> if the collection was modified as a result of this action.
+     * @throws UnsupportedOperationException as an unmodifiable collection does not
+     *         support the <code>addAll</code> operation.
+     */
+    public boolean addAll(Collection c)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Blocks the clearing of the underlying collection.  This method never
+     * returns, throwing an exception instead.
+     *
+     * @throws UnsupportedOperationException as an unmodifiable collection does
+     *         not support the <code>clear()</code> operation.
+     */
+    public void clear()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Test whether the underlying collection contains a given object as one of its
+     * elements.
+     *
+     * @param o the element to look for.
+     * @return <code>true</code> if the underlying collection contains at least
+     *         one element e such that
+     *         <code>o == null ? e == null : o.equals(e)</code>.
+     * @throws ClassCastException if the type of o is not a valid type for the
+     *         underlying collection.
+     * @throws NullPointerException if o is null and the underlying collection
+     *         doesn't support null values.
+     */
+    public boolean contains(Object o)
+    {
+      return c.contains(o);
+    }
+
+    /**
+     * Test whether the underlying collection contains every element in a given
+     * collection.
+     *
+     * @param c1 the collection to test for.
+     * @return <code>true</code> if for every element o in c, contains(o) would
+     *         return <code>true</code>.
+     * @throws ClassCastException if the type of any element in c is not a valid
+     *   type for the underlying collection.
+     * @throws NullPointerException if some element of c is null and the underlying
+     *   collection does not support null values.
+     * @throws NullPointerException if c itself is null.
+     */
+    public boolean containsAll(Collection c1)
+    {
+      return c.containsAll(c1);
+    }
+
+    /**
+     * Tests whether the underlying collection is empty, that is,
+     * if size() == 0.
+     *
+     * @return <code>true</code> if this collection contains no elements.
+     */
+    public boolean isEmpty()
+    {
+      return c.isEmpty();
+    }
+
+    /**
+     * Obtain an Iterator over the underlying collection, which maintains
+     * its unmodifiable nature.
+     *
+     * @return an UnmodifiableIterator over the elements of the underlying
+     *         collection, in any order.
+     */
+    public Iterator iterator()
+    {
+      return new UnmodifiableIterator(c.iterator());
+    }
+
+    /**
+     * Blocks the removal of an object from the underlying collection.
+     * This method never returns, throwing an exception instead.
+     *
+     * @param o The object to remove.
+     * @return <code>true</code> if the object was removed (i.e. the underlying
+     *         collection returned 1 or more instances of o).
+     * @throws UnsupportedOperationException as an unmodifiable collection
+     *         does not support the <code>remove()</code> operation.
+     */
+    public boolean remove(Object o)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Blocks the removal of a collection of objects from the underlying
+     * collection.  This method never returns, throwing an exception
+     * instead.
+     *
+     * @param c The collection of objects to remove.
+     * @return <code>true</code> if the collection was modified.
+     * @throws UnsupportedOperationException as an unmodifiable collection
+     *         does not support the <code>removeAll()</code> operation.
+     */
+    public boolean removeAll(Collection c)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Blocks the removal of all elements from the underlying collection,
+     * except those in the supplied collection.  This method never returns,
+     * throwing an exception instead.
+     *
+     * @param c The collection of objects to retain.
+     * @return <code>true</code> if the collection was modified.
+     * @throws UnsupportedOperationException as an unmodifiable collection
+     *         does not support the <code>retainAll()</code> operation.
+     */
+    public boolean retainAll(Collection c)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Retrieves the number of elements in the underlying collection.
+     *
+     * @return the number of elements in the collection.
+     */
+    public int size()
+    {
+      return c.size();
+    }
+
+    /**
+     * Copy the current contents of the underlying collection into an array.
+     *
+     * @return an array of type Object[] with a length equal to the size of the
+     *         underlying collection and containing the elements currently in
+     *         the underlying collection, in any order.
+     */
+    public Object[] toArray()
+    {
+      return c.toArray();
+    }
+
+    /**
+     * Copy the current contents of the underlying collection into an array.  If
+     * the array passed as an argument has length less than the size of the
+     * underlying collection, an array of the same run-time type as a, with a length
+     * equal to the size of the underlying collection, is allocated using reflection.
+     * Otherwise, a itself is used.  The elements of the underlying collection are
+     * copied into it, and if there is space in the array, the following element is
+     * set to null. The resultant array is returned.
+     * Note: The fact that the following element is set to null is only useful
+     * if it is known that this collection does not contain any null elements.
+     *
+     * @param a the array to copy this collection into.
+     * @return an array containing the elements currently in the underlying
+     *         collection, in any order.
+     * @throws ArrayStoreException if the type of any element of the
+     *         collection is not a subtype of the element type of a.
+     */
+    public Object[] toArray(Object[] a)
+    {
+      return c.toArray(a);
+    }
+
+    /**
+     * A textual representation of the unmodifiable collection.
+     *
+     * @return The unmodifiable collection in the form of a <code>String</code>.
+     */
+    public String toString()
+    {
+      return c.toString();
+    }
+  } // class UnmodifiableCollection
+
+  /**
+   * The implementation of the various iterator methods in the
+   * unmodifiable classes.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class UnmodifiableIterator implements Iterator
+  {
+    /**
+     * The wrapped iterator.
+     */
+    private final Iterator i;
+
+    /**
+     * Only trusted code creates a wrapper.
+     * @param i the wrapped iterator
+     */
+    UnmodifiableIterator(Iterator i)
+    {
+      this.i = i;
+    }
+
+    /**
+     * Obtains the next element in the underlying collection.
+     *
+     * @return the next element in the collection.
+     * @throws NoSuchElementException if there are no more elements.
+     */
+    public Object next()
+    {
+      return i.next();
+    }
+    /**
+     * Tests whether there are still elements to be retrieved from the
+     * underlying collection by <code>next()</code>.  When this method
+     * returns <code>true</code>, an exception will not be thrown on calling
+     * <code>next()</code>.
+     *
+     * @return <code>true</code> if there is at least one more element in the underlying
+     *         collection.
+     */
+    public boolean hasNext()
+    {
+      return i.hasNext();
+    }
+
+    /**
+     * Blocks the removal of elements from the underlying collection by the
+     * iterator.
+     *
+     * @throws UnsupportedOperationException as an unmodifiable collection
+     *         does not support the removal of elements by its iterator.
+     */
+    public void remove()
+    {
+      throw new UnsupportedOperationException();
+    }
+  } // class UnmodifiableIterator
+
+  /**
+   * Returns an unmodifiable view of the given list. This allows
+   * "read-only" access, although changes in the backing list show up
+   * in this view. Attempts to modify the list directly, via iterators, or
+   * via sublists, will fail with {@link UnsupportedOperationException}.
+   * Although this view prevents changes to the structure of the list and
+   * its elements, the values referenced by the objects in the list can
+   * still be modified.   
+   * <p>
+   *
+   * The returned List implements Serializable, but can only be serialized if
+   * the list it wraps is likewise Serializable. In addition, if the wrapped
+   * list implements RandomAccess, this does too.
+   *
+   * @param l the list to wrap
+   * @return a read-only view of the list
+   * @see Serializable
+   * @see RandomAccess
+   */
+  public static List unmodifiableList(List l)
+  {
+    if (l instanceof RandomAccess)
+      return new UnmodifiableRandomAccessList(l);
+    return new UnmodifiableList(l);
+  }
+
+  /**
+   * The implementation of {@link #unmodifiableList(List)} for sequential
+   * lists. This class name is required for compatibility with Sun's JDK
+   * serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class UnmodifiableList extends UnmodifiableCollection
+    implements List
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -283967356065247728L;
+
+
+    /**
+     * The wrapped list; stored both here and in the superclass to avoid
+     * excessive casting. Package visible for use by subclass.
+     * @serial the wrapped list
+     */
+    final List list;
+
+    /**
+     * Wrap a given list.
+     * @param l the list to wrap
+     * @throws NullPointerException if l is null
+     */
+    UnmodifiableList(List l)
+    {
+      super(l);
+      list = l;
+    }
+
+    /**
+     * Blocks the addition of an element to the underlying
+     * list at a specific index.  This method never returns,
+     * throwing an exception instead.
+     *
+     * @param index The index at which to place the new element.
+     * @param o the object to add.
+     * @throws UnsupportedOperationException as an unmodifiable
+     *         list doesn't support the <code>add()</code> operation.
+     */
+    public void add(int index, Object o)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Blocks the addition of a collection of elements to the
+     * underlying list at a specific index.  This method never
+     * returns, throwing an exception instead.
+     *
+     * @param index The index at which to place the new element.
+     * @param c the collections of objects to add.
+     * @throws UnsupportedOperationException as an unmodifiable
+     *         list doesn't support the <code>addAll()</code> operation.
+     */
+    public boolean addAll(int index, Collection c)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns <code>true</code> if the object, o, is an instance of
+     * <code>List</code> with the same size and elements
+     * as the underlying list.
+     *
+     * @param o The object to compare.
+     * @return <code>true</code> if o is equivalent to the underlying list.
+     */
+    public boolean equals(Object o)
+    {
+      return list.equals(o);
+    }
+
+    /**
+     * Retrieves the element at a given index in the underlying list.
+     *
+     * @param index the index of the element to be returned
+     * @return the element at index index in this list
+     * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+     */
+    public Object get(int index)
+    {
+      return list.get(index);
+    }
+
+    /**
+     * Computes the hash code for the underlying list.
+     * The exact computation is described in the documentation
+     * of the <code>List</code> interface.
+     *
+     * @return The hash code of the underlying list.
+     * @see List#hashCode()
+     */
+    public int hashCode()
+    {
+      return list.hashCode();
+    }
+
+    /**
+     * Obtain the first index at which a given object is to be found in the
+     * underlying list.
+     *
+     * @param o the object to search for
+     * @return the least integer n such that <code>o == null ? get(n) == null :
+     *         o.equals(get(n))</code>, or -1 if there is no such index.
+     * @throws ClassCastException if the type of o is not a valid
+     *         type for the underlying list.
+     * @throws NullPointerException if o is null and the underlying
+     *         list does not support null values.
+     */
+    public int indexOf(Object o)
+    {
+      return list.indexOf(o);
+    }
+
+    /**
+     * Obtain the last index at which a given object is to be found in the
+     * underlying list.
+     *
+     * @return the greatest integer n such that <code>o == null ? get(n) == null
+     *         : o.equals(get(n))</code>, or -1 if there is no such index.
+     * @throws ClassCastException if the type of o is not a valid
+     *         type for the underlying list.
+     * @throws NullPointerException if o is null and the underlying
+     *         list does not support null values.
+     */
+    public int lastIndexOf(Object o)
+    {
+      return list.lastIndexOf(o);
+    }
+
+  /**
+   * Obtains a list iterator over the underlying list, starting at the beginning
+   * and maintaining the unmodifiable nature of this list.
+   *
+   * @return a <code>UnmodifiableListIterator</code> over the elements of the
+   *         underlying list, in order, starting at the beginning.
+   */
+    public ListIterator listIterator()
+    {
+      return new UnmodifiableListIterator(list.listIterator());
+    }
+
+  /**
+   * Obtains a list iterator over the underlying list, starting at the specified
+   * index and maintaining the unmodifiable nature of this list.  An initial call
+   * to <code>next()</code> will retrieve the element at the specified index,
+   * and an initial call to <code>previous()</code> will retrieve the element
+   * at index - 1.
+   *
+   *
+   * @param index the position, between 0 and size() inclusive, to begin the
+   *        iteration from.
+   * @return a <code>UnmodifiableListIterator</code> over the elements of the
+   *         underlying list, in order, starting at the specified index.
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   */
+    public ListIterator listIterator(int index)
+    {
+      return new UnmodifiableListIterator(list.listIterator(index));
+    }
+
+    /**
+     * Blocks the removal of the element at the specified index.
+     * This method never returns, throwing an exception instead.
+     *
+     * @param index The index of the element to remove.
+     * @return the removed element.
+     * @throws UnsupportedOperationException as an unmodifiable
+     *         list does not support the <code>remove()</code>
+     *         operation.
+     */
+    public Object remove(int index)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Blocks the replacement of the element at the specified index.
+     * This method never returns, throwing an exception instead.
+     *
+     * @param index The index of the element to replace.
+     * @param o The new object to place at the specified index.
+     * @return the replaced element.
+     * @throws UnsupportedOperationException as an unmodifiable
+     *         list does not support the <code>set()</code>
+     *         operation.
+     */
+    public Object set(int index, Object o)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Obtain a List view of a subsection of the underlying list, from
+     * fromIndex (inclusive) to toIndex (exclusive). If the two indices
+     * are equal, the sublist is empty. The returned list will be
+     * unmodifiable, like this list.  Changes to the elements of the
+     * returned list will be reflected in the underlying list. No structural
+     * modifications can take place in either list.
+     *
+     * @param fromIndex the index that the returned list should start from
+     *        (inclusive).
+     * @param toIndex the index that the returned list should go to (exclusive).
+     * @return a List backed by a subsection of the underlying list.
+     * @throws IndexOutOfBoundsException if fromIndex < 0
+     *         || toIndex > size() || fromIndex > toIndex.
+     */
+    public List subList(int fromIndex, int toIndex)
+    {
+      return unmodifiableList(list.subList(fromIndex, toIndex));
+    }
+  } // class UnmodifiableList
+
+  /**
+   * The implementation of {@link #unmodifiableList(List)} for random-access
+   * lists. This class name is required for compatibility with Sun's JDK
+   * serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class UnmodifiableRandomAccessList
+    extends UnmodifiableList implements RandomAccess
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -2542308836966382001L;
+
+    /**
+     * Wrap a given list.
+     * @param l the list to wrap
+     * @throws NullPointerException if l is null
+     */
+    UnmodifiableRandomAccessList(List l)
+    {
+      super(l);
+    }
+  } // class UnmodifiableRandomAccessList
+
+  /**
+   * The implementation of {@link UnmodifiableList#listIterator()}.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class UnmodifiableListIterator
+    extends UnmodifiableIterator implements ListIterator
+  {
+    /**
+     * The wrapped iterator, stored both here and in the superclass to
+     * avoid excessive casting.
+     */
+    private final ListIterator li;
+
+    /**
+     * Only trusted code creates a wrapper.
+     * @param li the wrapped iterator
+     */
+    UnmodifiableListIterator(ListIterator li)
+    {
+      super(li);
+      this.li = li;
+    }
+
+    /**
+     * Blocks the addition of an object to the list underlying this iterator.
+     * This method never returns, throwing an exception instead.
+     *
+     * @param o The object to add.
+     * @throws UnsupportedOperationException as the iterator of an unmodifiable
+     *         list does not support the <code>add()</code> operation.
+     */
+    public void add(Object o)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Tests whether there are still elements to be retrieved from the
+     * underlying collection by <code>previous()</code>.  When this method
+     * returns <code>true</code>, an exception will not be thrown on calling
+     * <code>previous()</code>.
+     *
+     * @return <code>true</code> if there is at least one more element prior to the
+     *         current position in the underlying list.
+     */
+    public boolean hasPrevious()
+    {
+      return li.hasPrevious();
+    }
+
+    /**
+     * Find the index of the element that would be returned by a call to next.
+     * If <code>hasNext()</code> returns <code>false</code>, this returns the list size.
+     *
+     * @return the index of the element that would be returned by
+     *         <code>next()</code>.
+     */
+    public int nextIndex()
+    {
+      return li.nextIndex();
+    }
+
+    /**
+     * Obtains the previous element in the underlying list.
+     *
+     * @return the previous element in the list.
+     * @throws NoSuchElementException if there are no more prior elements.
+     */
+    public Object previous()
+    {
+      return li.previous();
+    }
+
+    /**
+     * Find the index of the element that would be returned by a call to
+     * previous. If <code>hasPrevious()</code> returns <code>false</code>,
+     * this returns -1.
+     *
+     * @return the index of the element that would be returned by
+     *         <code>previous()</code>.
+     */
+    public int previousIndex()
+    {
+      return li.previousIndex();
+    }
+
+    /**
+     * Blocks the replacement of an element in the list underlying this
+     * iterator.  This method never returns, throwing an exception instead.
+     *
+     * @param o The new object to replace the existing one.
+     * @throws UnsupportedOperationException as the iterator of an unmodifiable
+     *         list does not support the <code>set()</code> operation.
+     */
+    public void set(Object o)
+    {
+      throw new UnsupportedOperationException();
+    }
+  } // class UnmodifiableListIterator
+
+  /**
+   * Returns an unmodifiable view of the given map. This allows "read-only"
+   * access, although changes in the backing map show up in this view.
+   * Attempts to modify the map directly, or via collection views or their
+   * iterators will fail with {@link UnsupportedOperationException}.
+   * Although this view prevents changes to the structure of the map and its
+   * entries, the values referenced by the objects in the map can still be
+   * modified.   
+   * <p>
+   *
+   * The returned Map implements Serializable, but can only be serialized if
+   * the map it wraps is likewise Serializable.
+   *
+   * @param m the map to wrap
+   * @return a read-only view of the map
+   * @see Serializable
+   */
+  public static Map unmodifiableMap(Map m)
+  {
+    return new UnmodifiableMap(m);
+  }
+
+  /**
+   * The implementation of {@link #unmodifiableMap(Map)}. This
+   * class name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class UnmodifiableMap implements Map, Serializable
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -1034234728574286014L;
+
+    /**
+     * The wrapped map.
+     * @serial the real map
+     */
+    private final Map m;
+
+    /**
+     * Cache the entry set.
+     */
+    private transient Set entries;
+
+    /**
+     * Cache the key set.
+     */
+    private transient Set keys;
+
+    /**
+     * Cache the value collection.
+     */
+    private transient Collection values;
+
+    /**
+     * Wrap a given map.
+     * @param m the map to wrap
+     * @throws NullPointerException if m is null
+     */
+    UnmodifiableMap(Map m)
+    {
+      this.m = m;
+      if (m == null)
+        throw new NullPointerException();
+    }
+
+    /**
+     * Blocks the clearing of entries from the underlying map.
+     * This method never returns, throwing an exception instead.
+     *
+     * @throws UnsupportedOperationException as an unmodifiable
+     *         map does not support the <code>clear()</code> operation.
+     */
+    public void clear()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns <code>true</code> if the underlying map contains a mapping for
+     * the given key.
+     *
+     * @param key the key to search for
+     * @return <code>true</code> if the map contains the key
+     * @throws ClassCastException if the key is of an inappropriate type
+     * @throws NullPointerException if key is <code>null</code> but the map
+     *         does not permit null keys
+     */
+    public boolean containsKey(Object key)
+    {
+      return m.containsKey(key);
+    }
+
+    /**
+     * Returns <code>true</code> if the underlying map contains at least one mapping with
+     * the given value.  In other words, it returns <code>true</code> if a value v exists where
+     * <code>(value == null ? v == null : value.equals(v))</code>. This usually
+     * requires linear time.
+     *
+     * @param value the value to search for
+     * @return <code>true</code> if the map contains the value
+     * @throws ClassCastException if the type of the value is not a valid type
+     *         for this map.
+     * @throws NullPointerException if the value is null and the map doesn't
+     *         support null values.
+     */
+    public boolean containsValue(Object value)
+    {
+      return m.containsValue(value);
+    }
+
+    /**
+     * Returns a unmodifiable set view of the entries in the underlying map.
+     * Each element in the set is a unmodifiable variant of <code>Map.Entry</code>.
+     * The set is backed by the map, so that changes in one show up in the other.
+     * Modifications made while an iterator is in progress cause undefined
+     * behavior.  These modifications are again limited to the values of
+     * the objects.
+     *
+     * @return the unmodifiable set view of all mapping entries.
+     * @see Map.Entry
+     */
+    public Set entrySet()
+    {
+      if (entries == null)
+        entries = new UnmodifiableEntrySet(m.entrySet());
+      return entries;
+    }
+
+    /**
+     * The implementation of {@link UnmodifiableMap#entrySet()}. This class
+     * name is required for compatibility with Sun's JDK serializability.
+     *
+     * @author Eric Blake (ebb9 at email.byu.edu)
+     */
+    private static final class UnmodifiableEntrySet extends UnmodifiableSet
+      implements Serializable
+    {
+      // Unmodifiable implementation of Map.Entry used as return value for
+      // UnmodifiableEntrySet accessors (iterator, toArray, toArray(Object[]))
+      private static final class UnmodifiableMapEntry
+          implements Map.Entry
+      {
+        private final Map.Entry e;
+
+        private UnmodifiableMapEntry(Map.Entry e)
+        {
+          super();
+          this.e = e;
+        }
+
+        /**
+         * Returns <code>true</code> if the object, o, is also a map entry
+         * with an identical key and value.
+         * 
+         * @param o the object to compare.
+         * @return <code>true</code> if o is an equivalent map entry.
+         */
+        public boolean equals(Object o)
+        {
+          return e.equals(o);
+        }
+
+        /**
+         * Returns the key of this map entry.
+         * 
+         * @return the key.
+         */
+        public Object getKey()
+        {
+          return e.getKey();
+        }
+
+        /**
+         * Returns the value of this map entry.
+         * 
+         * @return the value.
+         */
+        public Object getValue()
+        {
+          return e.getValue();
+        }
+
+        /**
+         * Computes the hash code of this map entry. The computation is
+         * described in the <code>Map</code> interface documentation.
+         * 
+         * @return the hash code of this entry.
+         * @see Map#hashCode()
+         */
+        public int hashCode()
+        {
+          return e.hashCode();
+        }
+
+        /**
+         * Blocks the alteration of the value of this map entry. This method
+         * never returns, throwing an exception instead.
+         * 
+         * @param value The new value.
+         * @throws UnsupportedOperationException as an unmodifiable map entry
+         *           does not support the <code>setValue()</code> operation.
+         */
+        public Object setValue(Object value)
+        {
+          throw new UnsupportedOperationException();
+        }
+
+        /**
+         * Returns a textual representation of the map entry.
+         * 
+         * @return The map entry as a <code>String</code>.
+         */
+        public String toString()
+        {
+          return e.toString();
+        }
+      }
+
+      /**
+       * Compatible with JDK 1.4.
+       */
+      private static final long serialVersionUID = 7854390611657943733L;
+
+      /**
+       * Wrap a given set.
+       * @param s the set to wrap
+       */
+      UnmodifiableEntrySet(Set s)
+      {
+        super(s);
+      }
+
+      // The iterator must return unmodifiable map entries.
+      public Iterator iterator()
+      {
+        return new UnmodifiableIterator(c.iterator())
+	{
+	  /**
+	   * Obtains the next element from the underlying set of
+	   * map entries.
+	   *
+	   * @return the next element in the collection.
+	   * @throws NoSuchElementException if there are no more elements.
+	   */
+          public Object next()
+          {
+            final Map.Entry e = (Map.Entry) super.next();
+            return new UnmodifiableMapEntry(e);
+          }
+	};
+      }
+
+      // The array returned is an array of UnmodifiableMapEntry instead of
+      // Map.Entry
+      public Object[] toArray()
+      {
+        Object[] mapEntryResult = super.toArray();
+        UnmodifiableMapEntry result[] = null;
+
+        if (mapEntryResult != null)
+          {
+            result = new UnmodifiableMapEntry[mapEntryResult.length];
+            for (int i = 0; i < mapEntryResult.length; i++)
+              {
+                Map.Entry r = (Map.Entry) mapEntryResult[i];
+                result[i] = new UnmodifiableMapEntry(r);
+              }
+          }
+        return result;
+      }
+
+      // The array returned is an array of UnmodifiableMapEntry instead of
+      // Map.Entry
+      public Object[] toArray(Object[] array)
+      {
+        super.toArray(array);
+
+        if (array != null)
+          {
+            for (int i = 0; i < array.length; i++)
+              {
+                array[i] = new UnmodifiableMapEntry((Map.Entry) array[i]);
+              }
+          }
+        return array;
+      }
+      
+    } // class UnmodifiableEntrySet
+
+    /**
+     * Returns <code>true</code> if the object, o, is also an instance
+     * of <code>Map</code> with an equal set of map entries.
+     *
+     * @param o The object to compare.
+     * @return <code>true</code> if o is an equivalent map.
+     */
+    public boolean equals(Object o)
+    {
+      return m.equals(o);
+    }
+
+    /**
+     * Returns the value associated with the supplied key or
+     * null if no such mapping exists.  An ambiguity can occur
+     * if null values are accepted by the underlying map.
+     * In this case, <code>containsKey()</code> can be used
+     * to separate the two possible cases of a null result.
+     *
+     * @param key The key to look up.
+     * @return the value associated with the key, or null if key not in map.
+     * @throws ClassCastException if the key is an inappropriate type.
+     * @throws NullPointerException if this map does not accept null keys.
+     * @see #containsKey(Object)
+     */
+    public Object get(Object key)
+    {
+      return m.get(key);
+    }
+
+    /**
+     * Blocks the addition of a new entry to the underlying map.
+     * This method never returns, throwing an exception instead.
+     *
+     * @param key The new key.
+     * @param value The new value.
+     * @return the previous value of the key, or null if there was no mapping.
+     * @throws UnsupportedOperationException as an unmodifiable
+     *         map does not support the <code>put()</code> operation.
+     */
+    public Object put(Object key, Object value)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Computes the hash code for the underlying map, as the sum
+     * of the hash codes of all entries.
+     *
+     * @return The hash code of the underlying map.
+     * @see Map.Entry#hashCode()
+     */
+    public int hashCode()
+    {
+      return m.hashCode();
+    }
+
+    /**
+     * Returns <code>true</code> if the underlying map contains no entries.
+     *
+     * @return <code>true</code> if the map is empty.
+     */
+    public boolean isEmpty()
+    {
+      return m.isEmpty();
+    }
+
+    /**
+     * Returns a unmodifiable set view of the keys in the underlying map.
+     * The set is backed by the map, so that changes in one show up in the other.
+     * Modifications made while an iterator is in progress cause undefined
+     * behavior.  These modifications are again limited to the values of
+     * the keys.
+     *
+     * @return the set view of all keys.
+     */
+    public Set keySet()
+    {
+      if (keys == null)
+        keys = new UnmodifiableSet(m.keySet());
+      return keys;
+    }
+
+    /**
+     * Blocks the addition of the entries in the supplied map.
+     * This method never returns, throwing an exception instead.
+     *
+     * @param m The map, the entries of which should be added
+     *          to the underlying map.
+     * @throws UnsupportedOperationException as an unmodifiable
+     *         map does not support the <code>putAll</code> operation.
+     */
+    public void putAll(Map m)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Blocks the removal of an entry from the map.
+     * This method never returns, throwing an exception instead.
+     *
+     * @param o The key of the entry to remove.
+     * @return The value the key was associated with, or null
+     *         if no such mapping existed.  Null is also returned
+     *         if the removed entry had a null key.
+     * @throws UnsupportedOperationException as an unmodifiable
+     *         map does not support the <code>remove</code> operation.
+     */
+    public Object remove(Object o)
+    {
+      throw new UnsupportedOperationException();
+    }
+
+
+    /**
+     * Returns the number of key-value mappings in the underlying map.
+     * If there are more than Integer.MAX_VALUE mappings, Integer.MAX_VALUE
+     * is returned.
+     *
+     * @return the number of mappings.
+     */
+    public int size()
+    {
+      return m.size();
+    }
+
+    /**
+     * Returns a textual representation of the map.
+     *
+     * @return The map in the form of a <code>String</code>.
+     */
+    public String toString()
+    {
+      return m.toString();
+    }
+
+    /**
+     * Returns a unmodifiable collection view of the values in the underlying map.
+     * The collection is backed by the map, so that changes in one show up in the other.
+     * Modifications made while an iterator is in progress cause undefined
+     * behavior.  These modifications are again limited to the values of
+     * the keys.
+     *
+     * @return the collection view of all values.
+     */
+    public Collection values()
+    {
+      if (values == null)
+        values = new UnmodifiableCollection(m.values());
+      return values;
+    }
+  } // class UnmodifiableMap
+
+  /**
+   * Returns an unmodifiable view of the given set. This allows
+   * "read-only" access, although changes in the backing set show up
+   * in this view. Attempts to modify the set directly or via iterators
+   * will fail with {@link UnsupportedOperationException}.
+   * Although this view prevents changes to the structure of the set and its
+   * entries, the values referenced by the objects in the set can still be
+   * modified.   
+   * <p>
+   *
+   * The returned Set implements Serializable, but can only be serialized if
+   * the set it wraps is likewise Serializable.
+   *
+   * @param s the set to wrap
+   * @return a read-only view of the set
+   * @see Serializable
+   */
+  public static Set unmodifiableSet(Set s)
+  {
+    return new UnmodifiableSet(s);
+  }
+
+  /**
+   * The implementation of {@link #unmodifiableSet(Set)}. This class
+   * name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class UnmodifiableSet extends UnmodifiableCollection
+    implements Set
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -9215047833775013803L;
+
+    /**
+     * Wrap a given set.
+     * @param s the set to wrap
+     * @throws NullPointerException if s is null
+     */
+    UnmodifiableSet(Set s)
+    {
+      super(s);
+    }
+
+    /**
+     * Returns <code>true</code> if the object, o, is also an instance of
+     * <code>Set</code> of the same size and with the same entries.
+     *
+     * @return <code>true</code> if o is an equivalent set.
+     */
+    public boolean equals(Object o)
+    {
+      return c.equals(o);
+    }
+
+    /**
+     * Computes the hash code of this set, as the sum of the
+     * hash codes of all elements within the set.
+     *
+     * @return the hash code of the set.
+     */ 
+    public int hashCode()
+    {
+      return c.hashCode();
+    }
+  } // class UnmodifiableSet
+
+  /**
+   * Returns an unmodifiable view of the given sorted map. This allows
+   * "read-only" access, although changes in the backing map show up in this
+   * view. Attempts to modify the map directly, via subviews, via collection
+   * views, or iterators, will fail with {@link UnsupportedOperationException}.
+   * Although this view prevents changes to the structure of the map and its
+   * entries, the values referenced by the objects in the map can still be
+   * modified.   
+   * <p>
+   *
+   * The returned SortedMap implements Serializable, but can only be
+   * serialized if the map it wraps is likewise Serializable.
+   *
+   * @param m the map to wrap
+   * @return a read-only view of the map
+   * @see Serializable
+   */
+  public static SortedMap unmodifiableSortedMap(SortedMap m)
+  {
+    return new UnmodifiableSortedMap(m);
+  }
+
+  /**
+   * The implementation of {@link #unmodifiableSortedMap(SortedMap)}. This
+   * class name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class UnmodifiableSortedMap extends UnmodifiableMap
+    implements SortedMap
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -8806743815996713206L;
+
+    /**
+     * The wrapped map; stored both here and in the superclass to avoid
+     * excessive casting.
+     * @serial the wrapped map
+     */
+    private final SortedMap sm;
+
+    /**
+     * Wrap a given map.
+     * @param sm the map to wrap
+     * @throws NullPointerException if sm is null
+     */
+    UnmodifiableSortedMap(SortedMap sm)
+    {
+      super(sm);
+      this.sm = sm;
+    }
+
+    /**
+     * Returns the comparator used in sorting the underlying map,
+     * or null if it is the keys' natural ordering.
+     *
+     * @return the sorting comparator.
+     */
+    public Comparator comparator()
+    {
+      return sm.comparator();
+    }
+
+    /**
+     * Returns the first (lowest sorted) key in the map.
+     *
+     * @return the first key.
+     * @throws NoSuchElementException if this map is empty.
+     */
+    public Object firstKey()
+    {
+      return sm.firstKey();
+    }
+
+    /**
+     * Returns a unmodifiable view of the portion of the map strictly less
+     * than toKey. The view is backed by the underlying map, so changes in
+     * one show up in the other.  The submap supports all optional operations
+     * of the original.  This operation is equivalent to
+     * <code>subMap(firstKey(), toKey)</code>.
+     * <p>
+     *
+     * The returned map throws an IllegalArgumentException any time a key is
+     * used which is out of the range of toKey. Note that the endpoint, toKey,
+     * is not included; if you want this value to be included, pass its successor
+     * object in to toKey.  For example, for Integers, you could request
+     * <code>headMap(new Integer(limit.intValue() + 1))</code>.
+     *
+     * @param toKey the exclusive upper range of the submap.
+     * @return the submap.
+     * @throws ClassCastException if toKey is not comparable to the map contents.
+     * @throws IllegalArgumentException if this is a subMap, and toKey is out
+     *         of range.
+     * @throws NullPointerException if toKey is null but the map does not allow
+     *         null keys.
+     */
+    public SortedMap headMap(Object toKey)
+    {
+      return new UnmodifiableSortedMap(sm.headMap(toKey));
+    }
+
+    /**
+     * Returns the last (highest sorted) key in the map.
+     *
+     * @return the last key.
+     * @throws NoSuchElementException if this map is empty.
+     */
+    public Object lastKey()
+    {
+      return sm.lastKey();
+    }
+
+    /**
+     * Returns a unmodifiable view of the portion of the map greater than or
+     * equal to fromKey, and strictly less than toKey. The view is backed by
+     * the underlying map, so changes in one show up in the other. The submap
+     * supports all optional operations of the original.
+     * <p>
+     *
+     * The returned map throws an IllegalArgumentException any time a key is
+     * used which is out of the range of fromKey and toKey. Note that the
+     * lower endpoint is included, but the upper is not; if you want to
+     * change the inclusion or exclusion of an endpoint, pass its successor
+     * object in instead.  For example, for Integers, you could request
+     * <code>subMap(new Integer(lowlimit.intValue() + 1),
+     * new Integer(highlimit.intValue() + 1))</code> to reverse
+     * the inclusiveness of both endpoints.
+     *
+     * @param fromKey the inclusive lower range of the submap.
+     * @param toKey the exclusive upper range of the submap.
+     * @return the submap.
+     * @throws ClassCastException if fromKey or toKey is not comparable to
+     *         the map contents.
+     * @throws IllegalArgumentException if this is a subMap, and fromKey or
+     *         toKey is out of range.
+     * @throws NullPointerException if fromKey or toKey is null but the map
+     *         does not allow null keys.
+     */
+    public SortedMap subMap(Object fromKey, Object toKey)
+    {
+      return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
+    }
+
+    /**
+     * Returns a unmodifiable view of the portion of the map greater than or
+     * equal to fromKey. The view is backed by the underlying map, so changes
+     * in one show up in the other. The submap supports all optional operations
+     * of the original.
+     * <p>
+     *
+     * The returned map throws an IllegalArgumentException any time a key is
+     * used which is out of the range of fromKey. Note that the endpoint, fromKey, is
+     * included; if you do not want this value to be included, pass its successor object in
+     * to fromKey.  For example, for Integers, you could request
+     * <code>tailMap(new Integer(limit.intValue() + 1))</code>.
+     *
+     * @param fromKey the inclusive lower range of the submap
+     * @return the submap
+     * @throws ClassCastException if fromKey is not comparable to the map
+     *         contents
+     * @throws IllegalArgumentException if this is a subMap, and fromKey is out
+     *         of range
+     * @throws NullPointerException if fromKey is null but the map does not allow
+     *         null keys
+     */
+    public SortedMap tailMap(Object fromKey)
+    {
+      return new UnmodifiableSortedMap(sm.tailMap(fromKey));
+    }
+  } // class UnmodifiableSortedMap
+
+  /**
+   * Returns an unmodifiable view of the given sorted set. This allows
+   * "read-only" access, although changes in the backing set show up
+   * in this view. Attempts to modify the set directly, via subsets, or via
+   * iterators, will fail with {@link UnsupportedOperationException}.
+   * Although this view prevents changes to the structure of the set and its
+   * entries, the values referenced by the objects in the set can still be
+   * modified.   
+   * <p>
+   *
+   * The returns SortedSet implements Serializable, but can only be
+   * serialized if the set it wraps is likewise Serializable.
+   *
+   * @param s the set to wrap
+   * @return a read-only view of the set
+   * @see Serializable
+   */
+  public static SortedSet unmodifiableSortedSet(SortedSet s)
+  {
+    return new UnmodifiableSortedSet(s);
+  }
+
+  /**
+   * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
+   * class name is required for compatibility with Sun's JDK serializability.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static class UnmodifiableSortedSet extends UnmodifiableSet
+    implements SortedSet
+  {
+    /**
+     * Compatible with JDK 1.4.
+     */
+    private static final long serialVersionUID = -4929149591599911165L;
+
+    /**
+     * The wrapped set; stored both here and in the superclass to avoid
+     * excessive casting.
+     * @serial the wrapped set
+     */
+    private SortedSet ss;
+
+    /**
+     * Wrap a given set.
+     * @param ss the set to wrap
+     * @throws NullPointerException if ss is null
+     */
+    UnmodifiableSortedSet(SortedSet ss)
+    {
+      super(ss);
+      this.ss = ss;
+    }
+
+    /**
+     * Returns the comparator used in sorting the underlying set,
+     * or null if it is the elements' natural ordering.
+     *
+     * @return the sorting comparator
+     */
+    public Comparator comparator()
+    {
+      return ss.comparator();
+    }
+
+    /**
+     * Returns the first (lowest sorted) element in the underlying
+     * set.
+     *
+     * @return the first element.
+     * @throws NoSuchElementException if the set is empty.
+     */
+    public Object first()
+    {
+      return ss.first();
+    }
+
+    /**
+     * Returns a unmodifiable view of the portion of the set strictly
+     * less than toElement. The view is backed by the underlying set,
+     * so changes in one show up in the other.  The subset supports
+     * all optional operations of the original.  This operation
+     * is equivalent to <code>subSet(first(), toElement)</code>.
+     * <p>
+     *
+     * The returned set throws an IllegalArgumentException any time an element is
+     * used which is out of the range of toElement. Note that the endpoint, toElement,
+     * is not included; if you want this value included, pass its successor object in to
+     * toElement.  For example, for Integers, you could request
+     * <code>headSet(new Integer(limit.intValue() + 1))</code>.
+     *
+     * @param toElement the exclusive upper range of the subset
+     * @return the subset.
+     * @throws ClassCastException if toElement is not comparable to the set
+     *         contents.
+     * @throws IllegalArgumentException if this is a subSet, and toElement is out
+     *         of range.
+     * @throws NullPointerException if toElement is null but the set does not
+     *         allow null elements.
+     */
+    public SortedSet headSet(Object toElement)
+    {
+      return new UnmodifiableSortedSet(ss.headSet(toElement));
+    }
+
+    /**
+     * Returns the last (highest sorted) element in the underlying
+     * set.
+     *
+     * @return the last element.
+     * @throws NoSuchElementException if the set is empty.
+     */
+    public Object last()
+    {
+      return ss.last();
+    }
+
+    /**
+     * Returns a unmodifiable view of the portion of the set greater than or
+     * equal to fromElement, and strictly less than toElement. The view is backed by
+     * the underlying set, so changes in one show up in the other. The subset
+     * supports all optional operations of the original.
+     * <p>
+     *
+     * The returned set throws an IllegalArgumentException any time an element is
+     * used which is out of the range of fromElement and toElement. Note that the
+     * lower endpoint is included, but the upper is not; if you want to
+     * change the inclusion or exclusion of an endpoint, pass its successor
+     * object in instead.  For example, for Integers, you can request
+     * <code>subSet(new Integer(lowlimit.intValue() + 1),
+     * new Integer(highlimit.intValue() + 1))</code> to reverse
+     * the inclusiveness of both endpoints.
+     *
+     * @param fromElement the inclusive lower range of the subset.
+     * @param toElement the exclusive upper range of the subset.
+     * @return the subset.
+     * @throws ClassCastException if fromElement or toElement is not comparable
+     *         to the set contents.
+     * @throws IllegalArgumentException if this is a subSet, and fromElement or
+     *         toElement is out of range.
+     * @throws NullPointerException if fromElement or toElement is null but the
+     *         set does not allow null elements.
+     */
+    public SortedSet subSet(Object fromElement, Object toElement)
+    {
+      return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
+    }
+
+    /**
+     * Returns a unmodifiable view of the portion of the set greater than or equal to
+     * fromElement. The view is backed by the underlying set, so changes in one show up
+     * in the other. The subset supports all optional operations of the original.
+     * <p>
+     *
+     * The returned set throws an IllegalArgumentException any time an element is
+     * used which is out of the range of fromElement. Note that the endpoint,
+     * fromElement, is included; if you do not want this value to be included, pass its
+     * successor object in to fromElement.  For example, for Integers, you could request
+     * <code>tailSet(new Integer(limit.intValue() + 1))</code>.
+     *
+     * @param fromElement the inclusive lower range of the subset
+     * @return the subset.
+     * @throws ClassCastException if fromElement is not comparable to the set
+     *         contents.
+     * @throws IllegalArgumentException if this is a subSet, and fromElement is
+     *         out of range.
+     * @throws NullPointerException if fromElement is null but the set does not
+     *         allow null elements.
+     */
+    public SortedSet tailSet(Object fromElement)
+    {
+      return new UnmodifiableSortedSet(ss.tailSet(fromElement));
+    }
+  } // class UnmodifiableSortedSet
+} // class Collections

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Comparator.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Comparator.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Comparator.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Comparator.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,119 @@
+/* Comparator.java -- Interface for objects that specify an ordering
+   Copyright (C) 1998, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Interface for objects that specify an ordering between objects. The ordering
+ * should be <em>total</em>, such that any two objects of the correct type
+ * can be compared, and the comparison is reflexive, anti-symmetric, and
+ * transitive.  It is also recommended that the comparator be <em>consistent
+ * with equals</em>, although this is not a strict requirement. A relation
+ * is consistent with equals if these two statements always have the same
+ * results (if no exceptions occur):<br>
+ * <code>compare((Object) e1, (Object) e2) == 0</code> and
+ * <code>e1.equals((Object) e2)</code><br>
+ * Comparators that violate consistency with equals may cause strange behavior
+ * in sorted lists and sets.  For example, a case-sensitive dictionary order
+ * comparison of Strings is consistent with equals, but if it is
+ * case-insensitive it is not, because "abc" and "ABC" compare as equal even
+ * though "abc".equals("ABC") returns false.
+ * <P>
+ * In general, Comparators should be Serializable, because when they are passed
+ * to Serializable data structures such as SortedMap or SortedSet, the entire
+ * data structure will only serialize correctly if the comparator is
+ * Serializable.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Comparable
+ * @see TreeMap
+ * @see TreeSet
+ * @see SortedMap
+ * @see SortedSet
+ * @see Arrays#sort(Object[], Comparator)
+ * @see java.io.Serializable
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Comparator
+{
+  /**
+   * Return an integer that is negative, zero or positive depending on whether
+   * the first argument is less than, equal to or greater than the second
+   * according to this ordering. This method should obey the following
+   * contract:
+   * <ul>
+   *   <li>if compare(a, b) < 0 then compare(b, a) > 0</li>
+   *   <li>if compare(a, b) throws an exception, so does compare(b, a)</li>
+   *   <li>if compare(a, b) < 0 and compare(b, c) < 0 then compare(a, c)
+   *       < 0</li>
+   *   <li>if compare(a, b) == 0 then compare(a, c) and compare(b, c) must
+   *       have the same sign</li>
+   * </ul>
+   * To be consistent with equals, the following additional constraint is
+   * in place:
+   * <ul>
+   *   <li>if a.equals(b) or both a and b are null, then
+   *       compare(a, b) == 0.</li>
+   * </ul><p>
+   *
+   * Although it is permissible for a comparator to provide an order
+   * inconsistent with equals, that should be documented.
+   *
+   * @param o1 the first object
+   * @param o2 the second object
+   * @return the comparison
+   * @throws ClassCastException if the elements are not of types that can be
+   *         compared by this ordering.
+   */
+  int compare(Object o1, Object o2);
+
+  /**
+   * Return true if the object is equal to this object.  To be
+   * considered equal, the argument object must satisfy the constraints
+   * of <code>Object.equals()</code>, be a Comparator, and impose the
+   * same ordering as this Comparator. The default implementation
+   * inherited from Object is usually adequate.
+   *
+   * @param obj The object
+   * @return true if it is a Comparator that imposes the same order
+   * @see Object#equals(Object)
+   */
+  boolean equals(Object obj);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/ConcurrentModificationException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/ConcurrentModificationException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/ConcurrentModificationException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/ConcurrentModificationException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,92 @@
+/* ConcurrentModificationException.java -- Data structure concurrently modified
+   Copyright (C) 1998, 1999, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ */
+
+/**
+ * Exception that is thrown by the collections classes when it is detected that
+ * a modification has been made to a data structure when this is not allowed,
+ * such as when a collection is structurally modified while an Iterator is
+ * operating over it. In cases where this can be detected, a
+ * ConcurrentModificationException will be thrown. An Iterator that detects
+ * this condition is referred to as fail-fast. Notice that this can occur
+ * even in single-threaded designs, if you call methods out of order.
+ *
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Collection
+ * @see Iterator
+ * @see ListIterator
+ * @see Vector
+ * @see LinkedList
+ * @see HashSet
+ * @see Hashtable
+ * @see TreeMap
+ * @see AbstractList
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class ConcurrentModificationException extends RuntimeException
+{
+  /**
+   * Compatible with JDK 1.2.
+   */
+  private static final long serialVersionUID = -3666751008965953603L;
+
+  /**
+   * Constructs a ConcurrentModificationException with no detail message.
+   */
+  public ConcurrentModificationException()
+  {
+  }
+
+  /**
+   * Constructs a ConcurrentModificationException with a detail message.
+   *
+   * @param detail the detail message for the exception
+   */
+  public ConcurrentModificationException(String detail)
+  {
+    super(detail);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Currency.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Currency.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Currency.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Currency.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,437 @@
+/* Currency.java -- Representation of a currency
+   Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.java.locale.LocaleHelper;
+
+import java.io.IOException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
+/**
+ * Representation of a currency for a particular locale.  Each currency
+ * is identified by its ISO 4217 code, and only one instance of this
+ * class exists per currency.  As a result, instances are created
+ * via the <code>getInstance()</code> methods rather than by using
+ * a constructor.
+ *
+ * @see java.util.Locale
+ * @author Guilhem Lavaux  (guilhem.lavaux at free.fr)
+ * @author Dalibor Topic (robilad at kaffe.org)
+ * @author Bryce McKinlay (mckinlay at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.4
+ */
+public final class Currency 
+  implements Serializable
+{
+  /**
+   * For compatability with Sun's JDK
+   */
+  static final long serialVersionUID = -158308464356906721L;
+
+  /**
+   * The set of properties which map a currency to
+   * the currency information such as the ISO 4217
+   * currency code and the number of decimal points.
+   *
+   * @see #getCurrencyCode()
+   * @serial ignored.
+   */
+  private static transient Properties properties;
+
+  /**
+   * The ISO 4217 currency code associated with this
+   * particular instance.
+   *
+   * @see #getCurrencyCode()
+   * @serial the ISO 4217 currency code
+   */
+  private String currencyCode;
+
+  /**
+   * The number of fraction digits associated with this
+   * particular instance.
+   *
+   * @see #getDefaultFractionDigits()
+   * @serial the number of fraction digits
+   */
+  private transient int fractionDigits;
+  
+  /**
+   * A cached map of country codes
+   * instances to international currency code
+   * <code>String</code>s.  Seperating this
+   * from the <code>Currency</code> instances
+   * ensures we have a common lookup between
+   * the two <code>getInstance()</code> methods.
+   *
+   * @see #getInstance(java.util.Locale)
+   * @serial ignored.
+   */
+  private static transient Map countryMap;
+
+  /**
+   * A cache of <code>Currency</code> instances to
+   * ensure the singleton nature of this class.  The key
+   * is the international currency code.
+   *
+   * @see #getInstance(java.util.Locale)
+   * @see #getInstance(java.lang.String) 
+   * @see #readResolve()
+   * @serial ignored.
+   */
+  private static transient Map cache;
+
+  /**
+   * Instantiates the cache and reads in the properties.
+   */
+  static
+  {
+    /* Create a hash map for the locale mappings */
+    countryMap = new HashMap();
+    /* Create a hash map for the cache */
+    cache = new HashMap();
+    /* Create the properties object */
+    properties = new Properties();
+    /* Try and load the properties from our iso4217.properties resource */
+    try 
+      {
+        properties.load(Currency.class.getResourceAsStream("iso4217.properties"));
+      }
+    catch (IOException exception)
+      {
+        System.out.println("Failed to load currency resource: " + exception);
+      }
+  }
+
+  /**
+   * Default constructor for deserialization
+   */
+  private Currency()
+  {
+  }
+
+  /**
+   * Constructor to create a <code>Currency</code> object
+   * for a particular <code>Locale</code>.
+   * All components of the given locale, other than the
+   * country code, are ignored.  The results of calling this
+   * method may vary over time, as the currency associated with
+   * a particular country changes.  For countries without
+   * a given currency (e.g. Antarctica), the result is null. 
+   *
+   * @param loc the locale for the new currency, or null if
+   *        there is no country code specified or a currency
+   *        for this country.
+   */
+  private Currency(Locale loc)
+  {
+    String countryCode;
+    String currencyKey;
+    String fractionDigitsKey;
+    int commaPosition;
+
+    /* Retrieve the country code from the locale */
+    countryCode = loc.getCountry();
+    /* If there is no country code, return */
+    if (countryCode.equals(""))
+      {
+        throw new
+	  IllegalArgumentException("Invalid (empty) country code for locale:"
+			  	   + loc);
+      }
+    /* Construct the key for the currency */
+    currencyKey = countryCode + ".currency";
+    /* Construct the key for the fraction digits */
+    fractionDigitsKey = countryCode + ".fractionDigits";
+    /* Retrieve the currency */
+    currencyCode = properties.getProperty(currencyKey);
+    /* Return if the currency code is null */
+    if (currencyCode == null)
+      {
+        return;
+      }
+    /* Split off the first currency code (we only use the first for now) */
+    commaPosition = currencyCode.indexOf(",");
+    if (commaPosition != -1)
+      {
+        currencyCode = currencyCode.substring(0, commaPosition);
+      }
+    /* Retrieve the fraction digits */
+    fractionDigits = Integer.parseInt(properties.getProperty(fractionDigitsKey));
+  }
+
+  /**
+   * Constructor for the "XXX" special case.  This allows
+   * a Currency to be constructed from an assumed good
+   * currency code.
+   *
+   * @param code the code to use.
+   */  
+  private Currency(String code)
+  {
+    currencyCode = code;
+    fractionDigits = -1; /* Pseudo currency */
+  }
+
+  /**
+   * Returns the ISO4217 currency code of this currency.
+   *
+   * @return a <code>String</code> containing currency code.
+   */
+  public String getCurrencyCode()
+  {
+    return currencyCode;
+  }
+
+  /**
+   * Returns the number of digits which occur after the decimal point
+   * for this particular currency.  For example, currencies such
+   * as the U.S. dollar, the Euro and the Great British pound have two
+   * digits following the decimal point to indicate the value which exists
+   * in the associated lower-valued coinage (cents in the case of the first
+   * two, pennies in the latter).  Some currencies such as the Japanese
+   * Yen have no digits after the decimal point.  In the case of pseudo
+   * currencies, such as IMF Special Drawing Rights, -1 is returned.
+   *
+   * @return the number of digits after the decimal separator for this currency.
+   */   
+  public int getDefaultFractionDigits()
+  {
+    return fractionDigits;
+  }
+    
+  /**
+   * Builds a new currency instance for this locale.
+   * All components of the given locale, other than the
+   * country code, are ignored.  The results of calling this
+   * method may vary over time, as the currency associated with
+   * a particular country changes.  For countries without
+   * a given currency (e.g. Antarctica), the result is null. 
+   *
+   * @param locale a <code>Locale</code> instance.
+   * @return a new <code>Currency</code> instance.
+   * @throws NullPointerException if the locale or its
+   *         country code is null.
+   * @throws IllegalArgumentException if the country of
+   *         the given locale is not a supported ISO3166 code.
+   */ 
+  public static Currency getInstance(Locale locale)
+  {
+    /**
+     * The new instance must be the only available instance
+     * for the currency it supports.  We ensure this happens,
+     * while maintaining a suitable performance level, by
+     * creating the appropriate object on the first call to
+     * this method, and returning the cached instance on
+     * later calls.
+     */
+    Currency newCurrency;
+
+    String country = locale.getCountry();
+    if (locale == null || country == null)
+      {
+	throw new
+	  NullPointerException("The locale or its country is null.");
+      }
+    /* Attempt to get the currency from the cache */
+    String code = (String) countryMap.get(country);
+    if (code == null)
+      {
+        /* Create the currency for this locale */
+        newCurrency = new Currency(locale);
+        /* 
+         * If the currency code is null, then creation failed
+         * and we return null.
+         */
+	code = newCurrency.getCurrencyCode();
+        if (code == null)
+          {
+            return null;
+          }
+        else 
+          {
+            /* Cache it */
+            countryMap.put(country, code);
+	    cache.put(code, newCurrency);
+          }
+      }
+    else
+      {
+	newCurrency = (Currency) cache.get(code);
+      }
+    /* Return the instance */
+    return newCurrency;
+  }
+
+  /**
+   * Builds the currency corresponding to the specified currency code.
+   *
+   * @param currencyCode a string representing a currency code.
+   * @return a new <code>Currency</code> instance.
+   * @throws NullPointerException if currencyCode is null.
+   * @throws IllegalArgumentException if the supplied currency code
+   *         is not a supported ISO 4217 code.
+   */
+  public static Currency getInstance(String currencyCode)
+  {
+    Locale[] allLocales;
+
+    /* 
+     * Throw a null pointer exception explicitly if currencyCode is null.
+     * One is not thrown otherwise.  It results in an
+     * IllegalArgumentException. 
+     */
+    if (currencyCode == null)
+      {
+        throw new NullPointerException("The supplied currency code is null.");
+      }
+    /* Nasty special case to allow an erroneous currency... blame Sun */
+    if (currencyCode.equals("XXX"))
+      return new Currency("XXX");
+    Currency newCurrency = (Currency) cache.get(currencyCode);
+    if (newCurrency == null)
+      {
+	/* Get all locales */
+	allLocales = Locale.getAvailableLocales();
+	/* Loop through each locale, looking for the code */
+	for (int i = 0;i < allLocales.length; i++)
+	  {
+	    try
+	      {
+		Currency testCurrency = getInstance (allLocales[i]);
+		if (testCurrency != null &&
+		    testCurrency.getCurrencyCode().equals(currencyCode))
+		  {
+		    return testCurrency;
+		  }
+	      }
+	    catch (IllegalArgumentException exception)
+	      {
+		/* Ignore locales without valid countries */
+	      }
+	  }
+	/* 
+	 * If we get this far, the code is not supported by any of
+	 * our locales.
+	 */
+	throw new IllegalArgumentException("The currency code, " + currencyCode +
+					   ", is not supported.");
+      }
+    else
+      {
+	return newCurrency;
+      }
+  }
+
+  /**
+   * This method returns the symbol which precedes or follows a
+   * value in this particular currency in the default locale.
+   * In cases where there is no such symbol for the currency,
+   * the ISO 4217 currency code is returned.
+   *
+   * @return the currency symbol, or the ISO 4217 currency code if
+   *         one doesn't exist.
+   */
+  public String getSymbol()
+  {
+    return getSymbol(Locale.getDefault());
+  }
+
+  /**
+   * <p>
+   * This method returns the symbol which precedes or follows a
+   * value in this particular currency.  The returned value is
+   * the symbol used to denote the currency in the specified locale.
+   * </p>
+   * <p>
+   * For example, a supplied locale may specify a different symbol
+   * for the currency, due to conflicts with its own currency.
+   * This would be the case with the American currency, the dollar.
+   * Locales that also use a dollar-based currency (e.g. Canada, Australia)
+   * need to differentiate the American dollar using 'US$' rather than '$'.
+   * So, supplying one of these locales to <code>getSymbol()</code> would
+   * return this value, rather than the standard '$'.
+   * </p>
+   * <p>
+   * In cases where there is no such symbol for a particular currency,
+   * the ISO 4217 currency code is returned.
+   * </p>
+   *
+   * @param locale the locale to express the symbol in.
+   * @return the currency symbol, or the ISO 4217 currency code if
+   *         one doesn't exist.
+   * @throws NullPointerException if the locale is null.
+   */
+  public String getSymbol(Locale locale)
+  {
+    return LocaleHelper.getLocalizedString(locale, currencyCode,
+					   "currenciesSymbol", false, true);
+  }
+
+  /**
+   * Returns the international ISO4217 currency code of this currency.
+   *
+   * @return a <code>String</code> containing the ISO4217 currency code.
+   */
+  public String toString()
+  {
+    return getCurrencyCode();
+  }
+
+  /**
+   * Resolves the deserialized object to the singleton instance for its
+   * particular currency.  The currency code of the deserialized instance
+   * is used to return the correct instance.
+   *
+   * @return the singleton instance for the currency specified by the
+   *         currency code of the deserialized object.  This replaces
+   *         the deserialized object as the returned object from
+   *         deserialization.
+   * @throws ObjectStreamException if a problem occurs with deserializing
+   *         the object.
+   */
+  private Object readResolve()
+    throws ObjectStreamException
+  {
+    return getInstance(currencyCode);
+  }
+
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Date.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Date.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Date.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Date.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1263 @@
+/* java.util.Date
+   Copyright (C) 1998, 1999, 2000, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+/**
+ * <p>
+ * This class represents a specific time in milliseconds since the epoch.
+ * The epoch is 1970, January 1 00:00:00.0000 UTC.  
+ * </p>
+ * <p>
+ * <code>Date</code> is intended to reflect universal time coordinate (UTC),
+ * but this depends on the underlying host environment.  Most operating systems 
+ * don't handle the leap second, which occurs about once every year or
+ * so.  The leap second is added to the last minute of the day on either
+ * the 30th of June or the 31st of December, creating a minute 61 seconds
+ * in length.
+ * </p>
+ * <p>
+ * The representations of the date fields are as follows:
+ * <ul>
+ * <li>
+ * Years are specified as the difference between the year
+ * and 1900.  Thus, the final year used is equal to
+ * 1900 + y, where y is the input value.
+ * </li>
+ * <li>
+ * Months are represented using zero-based indexing,
+ * making 0 January and 11 December.
+ * </li>
+ * <li>
+ * Dates are represented with the usual values of
+ * 1 through to 31.
+ * </li>
+ * <li>
+ * Hours are represented in the twenty-four hour clock,
+ * with integer values from 0 to 23.  12am is 0, and
+ * 12pm is 12.
+ * </li>
+ * <li>
+ * Minutes are again as usual, with values from 0 to 59.
+ * </li>
+ * <li>
+ * Seconds are represented with the values 0 through to 61,
+ * with 60 and 61 being leap seconds (as per the ISO C standard).
+ * </li>
+ * </ul>
+ * </p>
+ * <p>
+ * Prior to JDK 1.1, this class was the sole class handling date and time
+ * related functionality.  However, this particular solution was not
+ * amenable to internationalization.  The new <code>Calendar</code>
+ * class should now be used to handle dates and times, with <code>Date</code>
+ * being used only for values in milliseconds since the epoch.  The
+ * <code>Calendar</code> class, and its concrete implementations, handle
+ * the interpretation of these values into minutes, hours, days, months
+ * and years.  The formatting and parsing of dates is left to the
+ * <code>DateFormat</code> class, which is able to handle the different
+ * types of date format which occur in different locales.
+ * </p>
+ *
+ * @see Calendar
+ * @see GregorianCalendar
+ * @see java.text.DateFormat
+ * @author Jochen Hoenicke
+ * @author Per Bothner (bothner at cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ */
+public class Date
+    implements Cloneable, Comparable, Serializable
+{
+  /**
+   * This is the serialization UID for this class
+   * for compatability with Sun's JDK.
+   */
+  private static final long serialVersionUID = 7523967970034938905L;
+
+  /**
+   * The time in milliseconds since the epoch.
+   */
+  private transient long time;
+
+  /**
+   * An array of week names used to map names to integer values.
+   */
+  private static final String[] weekNames = { "Sun", "Mon", "Tue", "Wed",
+					      "Thu", "Fri", "Sat" };
+  /**
+   * An array of month names used to map names to integer values.
+   */
+  private static final String[] monthNames = { "Jan", "Feb", "Mar", "Apr",
+					       "May", "Jun", "Jul", "Aug",
+					       "Sep", "Oct", "Nov", "Dec" };
+  /**
+   * Creates a new Date Object representing the current time.
+   */
+  public Date()
+  {
+    time = System.currentTimeMillis();
+  }
+
+  /**
+   * Creates a new Date Object representing the given time.
+   *
+   * @param time the time in milliseconds since the epoch.
+   */
+  public Date(long time)
+  {
+    this.time = time;
+  }
+
+  /**
+   * Creates a new Date Object representing the given time.
+   *
+   * @deprecated use <code>new GregorianCalendar(year+1900, month,
+   * day)</code> instead.
+   * @param year the difference between the required year and 1900.
+   * @param month the month as a value between 0 and 11.
+   * @param day the day as a value between 0 and 31.
+   */
+  public Date(int year, int month, int day)
+  {
+    this(year, month, day, 0, 0, 0);
+  }
+
+  /**
+   * Creates a new Date Object representing the given time.
+   *
+   * @deprecated use <code>new GregorianCalendar(year+1900, month,
+   * day, hour, min)</code> instead.
+   * @param year the difference between the required year and 1900.
+   * @param month the month as a value between 0 and 11.
+   * @param day the day as a value between 0 and 31.
+   * @param hour the hour as a value between 0 and 23, in 24-hour
+   *        clock notation.
+   * @param min the minute as a value between 0 and 59.
+   */
+  public Date(int year, int month, int day, int hour, int min)
+  {
+    this(year, month, day, hour, min, 0);
+  }
+
+  /**
+   * Creates a new Date Object representing the given time.
+   *
+   * @deprecated use <code>new GregorianCalendar(year+1900, month,
+   * day, hour, min, sec)</code> instead. 
+   * @param year the difference between the required year and 1900.
+   * @param month the month as a value between 0 and 11.
+   * @param day the day as a value between 0 and 31.
+   * @param hour the hour as a value between 0 and 23, in 24-hour
+   *        clock notation.
+   * @param min the minute as a value between 0 and 59.
+   * @param sec the second as a value between 0 and 61 (with 60
+   *        and 61 being leap seconds).
+   */
+  public Date(int year, int month, int day, int hour, int min, int sec)
+  {
+    GregorianCalendar cal =
+	new GregorianCalendar(year + 1900, month, day, hour, min, sec);
+    time = cal.getTimeInMillis();
+  }
+
+  /**
+   * Creates a new Date from the given string representation.  This
+   * does the same as <code>new Date(Date.parse(s))</code>
+   * @see #parse
+   * @deprecated use <code>java.text.DateFormat.parse(s)</code> instead.  
+   */
+  public Date(String s)
+  {
+    time = parse(s);
+  }
+
+  /**
+   * Returns a copy of this <code>Date</code> object.
+   *
+   * @return a copy, or null if the object couldn't be
+   *         cloned.
+   * @see Object#clone()
+   */
+  public Object clone()
+  {
+    try
+      {
+	return super.clone();
+      }
+    catch (CloneNotSupportedException ex)
+      {
+	return null;
+      }
+  }
+
+  /**
+   * Returns the number of milliseconds since the epoch
+   * specified by the given arguments.  The arguments are
+   * interpreted relative to UTC rather than the local
+   * time zone.
+   *
+   * @deprecated Use <code>Calendar</code> with a UTC
+   *             <code>TimeZone</code> instead.
+   * @param year the difference between the required year and 1900.
+   * @param month the month as a value between 0 and 11.
+   * @param date the day as a value between 0 and 31.
+   * @param hrs the hour as a value between 0 and 23, in 24-hour
+   *        clock notation.
+   * @param min the minute as a value between 0 and 59.
+   * @param sec the second as a value between 0 and 61 (with 60
+   *        and 61 being leap seconds).
+   * @return the time in milliseconds since the epoch.
+   */
+  public static long UTC(int year, int month, int date,
+			 int hrs, int min, int sec)
+  {
+    GregorianCalendar cal =
+      new GregorianCalendar(year + 1900, month, date, hrs, min, sec);
+    cal.set(Calendar.ZONE_OFFSET, 0);
+    cal.set(Calendar.DST_OFFSET, 0);
+    return cal.getTimeInMillis();
+  }
+
+  /**
+   * Gets the time represented by this object.
+   *
+   * @return the time in milliseconds since the epoch.
+   */
+  public long getTime()
+  {
+    return time;
+  }
+
+  /**
+   * Returns the number of minutes offset used with UTC to give the time
+   * represented by this object in the current time zone.  The date information
+   * from this object is also used to determine whether or not daylight savings
+   * time is in effect.  For example, the offset for the UK would be 0 if the
+   * month of the date object was January, and 1 if the month was August.
+   * 
+   * @deprecated use
+   * <code>Calendar.get(Calendar.ZONE_OFFSET)+Calendar.get(Calendar.DST_OFFSET)</code>
+   * instead.
+   * @return The time zone offset in minutes of the local time zone
+   * relative to UTC.  The time represented by this object is used to
+   * determine if we should use daylight savings.
+   */
+  public int getTimezoneOffset()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    return - (cal.get(Calendar.ZONE_OFFSET)
+	    + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
+  }
+
+  /**
+   * Sets the time which this object should represent.
+   *
+   * @param time the time in milliseconds since the epoch.  
+   */
+  public void setTime(long time)
+  {
+    this.time = time;
+  }
+
+  /**
+   * Tests if this date is after the specified date.
+   *
+   * @param when the other date
+   * @return true, if the date represented by this object is
+   * strictly later than the time represented by when.  
+   */
+  public boolean after(Date when)
+  {
+    return time > when.time;
+  }
+
+  /**
+   * Tests if this date is before the specified date.
+   *
+   * @param when the other date
+   * @return true, if the date represented by when is strictly later
+   * than the time represented by this object.
+   */
+  public boolean before(Date when)
+  {
+    return time < when.time;
+  }
+
+  /**
+   * Compares two dates for equality.
+   *
+   * @param obj the object to compare.
+   * @return true, if obj is a Date object and the time represented
+   * by obj is exactly the same as the time represented by this
+   * object.  
+   */
+  public boolean equals(Object obj)
+  {
+    return (obj instanceof Date && time == ((Date) obj).time);
+  }
+
+  /**
+   * Compares two dates.
+   *
+   * @param when the other date.
+   * @return 0, if the date represented
+   * by obj is exactly the same as the time represented by this
+   * object, a negative if this Date is before the other Date, and
+   * a positive value otherwise.  
+   */
+  public int compareTo(Date when)
+  {
+    return (time < when.time) ? -1 : (time == when.time) ? 0 : 1;
+  }
+
+  /**
+   * Compares this Date to another object.  This behaves like
+   * <code>compareTo(Date)</code>, but it takes a generic object
+   * and throws a <code>ClassCastException</code> if obj is
+   * not a <code>Date</code>.
+   * 
+   * @param obj the other date.
+   * @return 0, if the date represented
+   * by obj is exactly the same as the time represented by this
+   * object, a negative if this Date is before the other Date, and
+   * a positive value otherwise.  
+   * @exception ClassCastException if obj is not of type Date.
+   */
+  public int compareTo(Object obj)
+  {
+    return compareTo((Date) obj);
+  }
+
+  /**
+   * Computes the hash code of this <code>Date</code> as the
+   * XOR of the most significant and the least significant
+   * 32 bits of the 64 bit milliseconds value.
+   *
+   * @return the hash code.
+   */
+  public int hashCode()
+  {
+    return (int) time ^ (int) (time >>> 32);
+  }
+
+  /**
+   * <p>
+   * Returns a string representation of this date using
+   * the following date format:
+   * </p>
+   * <p>
+   * <code>day mon dd hh:mm:ss zz yyyy</code>
+   * </p>
+   * <p>where the fields used here are:
+   * <ul>
+   * <li>
+   * <code>day</code> -- the day of the week
+   * (Sunday through to Saturday).
+   * </li>
+   * <li>
+   * <code>mon</code> -- the month (Jan to Dec).
+   * </li>
+   * <li>
+   * <code>dd</code> -- the day of the month
+   * as two decimal digits (01 to 31).
+   * </li>
+   * <li>
+   * <code>hh</code> -- the hour of the day
+   * as two decimal digits in 24-hour clock notation
+   * (01 to 23).
+   * </li>
+   * <li>
+   * <code>mm</code> -- the minute of the day
+   * as two decimal digits (01 to 59).
+   * </li>
+   * <li>
+   * <code>ss</code> -- the second of the day
+   * as two decimal digits (01 to 61).
+   * </li>
+   * <li>
+   * <code>zz</code> -- the time zone information if available.
+   * The possible time zones used include the abbreviations
+   * recognised by <code>parse()</code> (e.g. GMT, CET, etc.)
+   * and may reflect the fact that daylight savings time is in
+   * effect.  The empty string is used if there is no time zone
+   * information.
+   * </li>
+   * <li>
+   * <code>yyyy</code> -- the year as four decimal digits.
+   * </li>
+   * </ul>
+   * <p>
+   * The <code>DateFormat</code> class should now be 
+   * preferred over using this method.
+   * </p>
+   *
+   * @return A string of the form 'day mon dd hh:mm:ss zz yyyy'
+   * @see #parse(String)
+   * @see DateFormat
+   */
+  public String toString()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    String day = "0" + cal.get(Calendar.DATE);
+    String hour = "0" + cal.get(Calendar.HOUR_OF_DAY);
+    String min = "0" + cal.get(Calendar.MINUTE);
+    String sec = "0" + cal.get(Calendar.SECOND);
+    String year = "000" + cal.get(Calendar.YEAR);
+    return weekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " "
+      + monthNames[cal.get(Calendar.MONTH)] + " "
+      + day.substring(day.length() - 2) + " "
+      + hour.substring(hour.length() - 2) + ":"
+      + min.substring(min.length() - 2) + ":"
+      + sec.substring(sec.length() - 2) + " "
+      +
+      cal.getTimeZone().getDisplayName(cal.getTimeZone().inDaylightTime(this),
+				       TimeZone.SHORT) + " " +
+      year.substring(year.length() - 4);
+  }
+
+  /** 
+   * Returns a locale-dependent string representation of this
+   * <code>Date</code> object.
+   *
+   * @deprecated Use DateFormat.format(Date)
+   * @return A locale-dependent string representation.
+   * @see #parse(String)
+   * @see DateFormat
+   */
+  public String toLocaleString()
+  {
+    return java.text.DateFormat.getInstance().format(this);
+  }
+
+  /** 
+   * <p>
+   * Returns a string representation of this <code>Date</code>
+   * object using GMT rather than the local timezone.
+   * The following date format is used:
+   * </p>
+   * <p>
+   * <code>d mon yyyy hh:mm:ss GMT</code>
+   * </p>
+   * <p>where the fields used here are:
+   * <ul>
+   * <li>
+   * <code>d</code> -- the day of the month
+   * as one or two decimal digits (1 to 31).
+   * </li>
+   * <li>
+   * <code>mon</code> -- the month (Jan to Dec).
+   * </li>
+   * <li>
+   * <code>yyyy</code> -- the year as four decimal digits.
+   * </li>
+   * <li>
+   * <code>hh</code> -- the hour of the day
+   * as two decimal digits in 24-hour clock notation
+   * (01 to 23).
+   * </li>
+   * <li>
+   * <code>mm</code> -- the minute of the day
+   * as two decimal digits (01 to 59).
+   * </li>
+   * <li>
+   * <code>ss</code> -- the second of the day
+   * as two decimal digits (01 to 61).
+   * </li>
+   * <li>
+   * <code>GMT</code> -- the literal string "GMT"
+   * indicating Greenwich Mean Time as opposed to
+   * the local timezone.
+   * </li>
+   * </ul>
+   * 
+   * @deprecated Use DateFormat.format(Date) with a GMT TimeZone.
+   * @return A string of the form 'd mon yyyy hh:mm:ss GMT' using
+   *         GMT as opposed to the local timezone.
+   * @see #parse(String)
+   * @see DateFormat
+   */
+  public String toGMTString()
+  {
+    java.text.DateFormat format = java.text.DateFormat.getInstance();
+    format.setTimeZone(TimeZone.getTimeZone("GMT"));
+    return format.format(this);
+  }
+
+  /**
+   * Parses the time zone string.
+   *
+   * @param tok The token containing the time zone.
+   * @param sign The sign (+ or -) used by the time zone.
+   * @return An integer representing the number of minutes offset
+   *         from GMT for the time zone.
+   */
+  private static int parseTz(String tok, char sign)
+    throws IllegalArgumentException
+  {
+    int num;
+
+    try
+      {
+	// parseInt doesn't handle '+' so strip off sign.
+	num = Integer.parseInt(tok.substring(1));
+      }
+    catch (NumberFormatException ex)
+      {
+	throw new IllegalArgumentException(tok);
+      }
+
+    // Convert hours to minutes.
+    if (num < 24)
+      num *= 60;
+    else
+      num = (num / 100) * 60 + num % 100;
+
+    return sign == '-' ? -num : num;
+  }
+
+  /**
+   * Parses the month string.
+   *
+   * @param tok the token containing the month.
+   * @return An integer between 0 and 11, representing
+   *         a month from January (0) to December (11),
+   *         or -1 if parsing failed.
+   */
+  private static int parseMonth(String tok)
+  {
+    // Initialize strings for month names.
+    // We could possibly use the fields of DateFormatSymbols but that is
+    // localized and thus might not match the English words specified.
+    String months[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY",
+			"JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER",
+			"NOVEMBER", "DECEMBER" };
+
+    int i;
+    for (i = 0; i < 12; i++)
+      if (months[i].startsWith(tok))
+        return i;
+
+    // Return -1 if not found.
+    return -1;
+  }
+
+  /**
+   * Parses the day of the week string.
+   *
+   * @param tok the token containing the day of the week.
+   * @return true if the token was parsed successfully.
+   */
+  private static boolean parseDayOfWeek(String tok)
+  {
+    // Initialize strings for days of the week names.
+    // We could possibly use the fields of DateFormatSymbols but that is
+    // localized and thus might not match the English words specified.
+    String daysOfWeek[] = { "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
+			    "THURSDAY", "FRIDAY", "SATURDAY" };
+
+    int i;
+    for (i = 0; i < 7; i++)
+      if (daysOfWeek[i].startsWith(tok))
+        return true;
+
+    return false;
+  }
+
+  /** 
+   * <p>
+   * Parses a String and returns the time, in milliseconds since the
+   * epoch, it represents.  Most syntaxes are handled, including
+   * the IETF date standard "day, dd mon yyyy hh:mm:ss zz" (see
+   * <code>toString()</code> for definitions of these fields).
+   * Standard U.S. time zone abbreviations are recognised, in
+   * addition to time zone offsets in positive or negative minutes.
+   * If a time zone is specified, the specified time is assumed to
+   * be in UTC and the appropriate conversion is applied, following
+   * parsing, to convert this to the local time zone.  If no zone
+   * is specified, the time is assumed to already be in the local
+   * time zone.
+   * </p>
+   * <p>
+   * The method parses the string progressively from left to right.
+   * At the end of the parsing process, either a time is returned
+   * or an <code>IllegalArgumentException</code> is thrown to signify
+   * failure.  The ASCII characters A-Z, a-z, 0-9, and ',', '+', '-',
+   * ':' and '/' are the only characters permitted within the string,
+   * besides whitespace and characters enclosed within parantheses
+   * '(' and ')'.  
+   * </p>
+   * <p>
+   * A sequence of consecutive digits are recognised as a number,
+   * and interpreted as follows:
+   * <ul>
+   * <li>
+   * A number preceded by a sign (+ or -) is taken to be a time zone
+   * offset.  The time zone offset can be specified in either hours
+   * or minutes.  The former is assumed if the number is less than 24.
+   * Otherwise, the offset is assumed to be in minutes.  A - indicates
+   * a time zone west of GMT, while a + represents a time zone to the
+   * east of GMT.  The time zones are always assumed to be relative
+   * to GMT, and a (redundant) specification of this can be included
+   * with the time zone.  For example, '-9', 'utc-9' and 'GMT-9' all
+   * represent a time zone nine hours west of GMT.  Similarly,
+   * '+4', 'ut+4' and 'UTC+4' all give 4 hours east of GMT.
+   * </li>
+   * <li>
+   * A number equal to or greater than 70 is regarded as a year specification.
+   * Values lower than 70 are only assumed to indicate a year if both the
+   * day of the month and the month itself have already been recognised.
+   * Year values less than 100 are interpreted as being relative to the current
+   * century when the <code>Date</code> class is initialised..  Given a century,
+   * x, the year is assumed to be within the range x - 80 to x + 19.  The value
+   * itself is then used as a match against the two last digits of one of these
+   * years.  For example, take x to be 2004.  A two-digit year is assumed to fall
+   * within the range x - 80 (1924) and x + 19 (2023).  Thus, any intepreted value
+   * between 0 and 23 is assumed to be 2000 to 2023 and values between 24 and 99
+   * are taken as being 1924 to 1999.  This only applies for the case of 2004.
+   * With a different year, the values will be interpreted differently. 2005
+   * will used 0 to 24 as 2000 to 2024 and 25 to 99 as 1925 to 1999, for example.
+   * This behaviour differs from that of <code>SimpleDateFormat</code> and is
+   * time-dependent (a two-digit year will be interpreted differently depending
+   * on the time the code is run).
+   * </li>
+   * <li>
+   * Numbers followed by a colon are interpreted by first an hour, and then
+   * as a minute, once an hour has been found.
+   * </li>
+   * <li>
+   * <li>
+   * Numbers followed by a slash are regarded first as a month, and then as
+   * a day of the month once the month has been found.  This follows the
+   * U.S. date format of mm/dd, rather than the European dd/mm.  Months
+   * are converted to the recognised value - 1 before storage, in order
+   * to put the number within the range 0 to 11.
+   * </li>
+   * <li>
+   * Numbers followed by commas, whitespace, hyphens or the end of the string
+   * are interpreted in the following order: hour, minute, second, day of month.
+   * The first type not already recognised in the current string being parsed is
+   * assumed.
+   * </li>
+   * </ul>
+   * </p>
+   * <p>
+   * A sequence of consecutive alphabetic characters is recognised as a word,
+   * and interpreted as follows, in a case-insentive fashion:
+   * <ul>
+   * <li>
+   * The characters 'AM' or 'PM' restrict the hour value to a value between 0
+   * and 12.  In the latter case, 12 is added to the hour value before storage.
+   * </li>
+   * <li>
+   * Any words which match any prefix of one of the days of the week ('Monday',
+   * 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' and 'Sunday'),
+   * are simply ignored.
+   * </li>
+   * <li>
+   * Any words which match any prefix of one of the months of the year ('January',
+   * 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September',
+   * 'October', 'November', 'December') are recognised and interpreted as the
+   * appropriate value between 0 and 11.  The first match made against a
+   * month is the one used, in the order specified here.  For example, 'Ma' is
+   * intepreted as 'March' (2) and not as 'May' (4).  Similarly, 'Ju' is 'June',
+   * and not 'July'.
+   * </li>
+   * <li>
+   * The words 'GMT', 'UT' and 'UTC' are interpreted as specifying UTC as the
+   * time zone in use for this date.
+   * </li>
+   * <li>
+   * The word pairs 'EST'/'EDT', 'CST'/'CDT', 'MST'/'MDT' and 'PST'/'PDT' are
+   * interpreted as the appropriate U.S. time zone abbreviation.  Each pair
+   * is the standard and daylight savings time zone specification, respectively,
+   * for each zone within the U.S, these being Eastern Standard/Daylight Time
+   * (-5), Central Standard/Daylight Time (-6), Mountain Standard/Daylight Time
+   * (-7) and Pacific Standard/Daylight Time (-8).
+   * </li>
+   * </ul>
+   *
+   * @param string The String to parse.
+   * @return The time in milliseconds since the epoch.
+   * @throws IllegalArgumentException if the string fails to parse.
+   * @deprecated Use DateFormat.parse(String)
+   * @see #toString()
+   * @see SimpleDateFormat
+   */
+  public static long parse(String string)
+  {
+    // Initialize date/time fields before parsing begins.
+    int year = -1;
+    int month = -1;
+    int day = -1;
+    int hour = -1;
+    int minute = -1;
+    int second = -1;
+    int timezone = 0;
+    boolean localTimezone = true;
+
+    // Trim out any nested stuff in parentheses now to make parsing easier.
+    StringBuffer buf = new StringBuffer();
+    int parenNesting = 0;
+    int len = string.length();
+    for (int i = 0;  i < len;  i++)
+      {
+	char ch = string.charAt(i);
+	if (ch >= 'a' && ch <= 'z')
+	  ch -= 'a' - 'A';
+	if (ch == '(')
+	  parenNesting++;
+	else if (parenNesting == 0)
+	  buf.append(ch);
+	else if (ch == ')')
+	  parenNesting--;
+      }
+    int tmpMonth;
+
+    // Make all chars upper case to simplify comparisons later.
+    // Also ignore commas; treat them as delimiters.
+    StringTokenizer strtok = new StringTokenizer(buf.toString(), " \t\n\r,");
+
+    while (strtok.hasMoreTokens())
+      {
+	String tok = strtok.nextToken();
+	char firstch = tok.charAt(0);
+	if ((firstch == '+' || firstch == '-') && year >= 0)
+	  {
+	    timezone = parseTz(tok, firstch);
+	    localTimezone = false;
+	  }
+	else if (firstch >= '0' && firstch <= '9')
+	  {
+	    while (tok != null && tok.length() > 0)
+	      {
+		int punctOffset = tok.length();
+		int num = 0;
+		int punct;
+		for (int i = 0;  ;  i++)
+		  {
+		    if (i >= punctOffset)
+		      {
+			punct = -1;
+			break;
+		      }
+		    else
+		      {
+			punct = tok.charAt(i);
+			if (punct >= '0' && punct <= '9')
+			  {
+			    if (num > 999999999) // in case of overflow
+			      throw new IllegalArgumentException(tok);
+			    num = 10 * num + (punct - '0');
+			  }
+			else
+			  {
+			    punctOffset = i;
+			    break;
+			  }
+		      }
+		      
+		  }
+
+		if (punct == ':')
+		  {
+		    if (hour < 0)
+		      hour = num;
+		    else
+		      minute = num;
+		  }
+	        else if ((num >= 70
+			  && (punct == ' ' || punct == ','
+			      || punct == '/' || punct < 0))
+			 || (num < 70 && day >= 0 && month >= 0 && year < 0))
+		  {
+		    if (num >= 100)
+		      year = num;
+		    else
+		      {
+			int curYear = 1900 + new Date().getYear();
+			int firstYear = curYear - 80;
+			year = firstYear / 100 * 100 + num;
+			if (year < firstYear)
+			  year += 100;
+		      }
+		  }
+		else if (punct == '/')
+		  {
+		    if (month < 0)
+		      month = num - 1;
+		    else
+		      day = num;
+		  }
+		else if (hour >= 0 && minute < 0)
+		  minute = num;
+		else if (minute >= 0 && second < 0)
+		  second = num;
+		else if (day < 0)
+		  day = num;
+		else
+		  throw new IllegalArgumentException(tok);
+
+		// Advance string if there's more to process in this token.
+		if (punct < 0 || punctOffset + 1 >= tok.length())
+		  tok = null;
+		else
+		  tok = tok.substring(punctOffset + 1);
+	      }
+	  }
+	else if (firstch >= 'A' && firstch <= 'Z')
+	  {
+	    if (tok.equals("AM"))
+	      {
+		if (hour < 1 || hour > 12)
+		  throw new IllegalArgumentException(tok);
+		if (hour == 12)
+		  hour = 0;
+	      }
+	    else if (tok.equals("PM"))
+	      {
+		if (hour < 1 || hour > 12)
+		  throw new IllegalArgumentException(tok);
+		if (hour < 12)
+		  hour += 12;
+	      }
+	    else if (parseDayOfWeek(tok))
+	      ; // Ignore it; throw the token away.
+	    else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))
+	      localTimezone = false;
+	    else if (tok.startsWith("UT") || tok.startsWith("GMT"))
+	      {
+		int signOffset = 3;
+		if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')
+		  signOffset = 2;
+
+	        char sign = tok.charAt(signOffset);
+		if (sign != '+' && sign != '-')
+		  throw new IllegalArgumentException(tok);
+
+	        timezone = parseTz(tok.substring(signOffset), sign);
+	        localTimezone = false;
+	      }
+	    else if ((tmpMonth = parseMonth(tok)) >= 0)
+	      month = tmpMonth;
+	    else if (tok.length() == 3 && tok.charAt(2) == 'T')
+	      {
+		// Convert timezone offset from hours to minutes.
+		char ch = tok.charAt(0);
+		if (ch == 'E')
+		  timezone = -5 * 60;
+		else if (ch == 'C')
+		  timezone = -6 * 60;
+		else if (ch == 'M')
+		  timezone = -7 * 60;
+		else if (ch == 'P')
+		  timezone = -8 * 60;
+		else
+		  throw new IllegalArgumentException(tok);
+
+		// Shift 60 minutes for Daylight Savings Time.
+		if (tok.charAt(1) == 'D')
+		  timezone += 60;
+		else if (tok.charAt(1) != 'S')
+		  throw new IllegalArgumentException(tok);
+
+	        localTimezone = false;
+	      }
+	    else
+	      throw new IllegalArgumentException(tok);
+	  }
+	else
+	  throw new IllegalArgumentException(tok);
+      }
+
+    // Unspecified hours, minutes, or seconds should default to 0.
+    if (hour < 0)
+      hour = 0;
+    if (minute < 0)
+      minute = 0;
+    if (second < 0)
+      second = 0;
+
+    // Throw exception if any other fields have not been recognized and set.
+    if (year < 0 || month < 0 || day < 0)
+      throw new IllegalArgumentException("Missing field");
+
+    // Return the time in either local time or relative to GMT as parsed.
+    // If no time-zone was specified, get the local one (in minutes) and
+    // convert to milliseconds before adding to the UTC.
+    GregorianCalendar cal
+      = new GregorianCalendar(year, month, day, hour, minute, second);
+    if (!localTimezone)
+      {
+	cal.set(Calendar.ZONE_OFFSET, timezone * 60 * 1000);
+	cal.set(Calendar.DST_OFFSET, 0);
+      }
+    return cal.getTimeInMillis();
+  }
+
+  /**
+   * Returns the difference between the year represented by this
+   * <code>Date</code> object and 1900.
+   *
+   * @return the year minus 1900 represented by this date object.
+   * @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR)
+   * instead.  Note the 1900 difference in the year.
+   * @see Calendar
+   * @see #setYear(int)
+   */
+  public int getYear()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    return cal.get(Calendar.YEAR) - 1900;
+  }
+
+  /**
+   * Sets the year to the specified year, plus 1900.  The other
+   * fields are only altered as required to match the same date
+   * and time in the new year.  Usually, this will mean that
+   * the fields are not changed at all, but in the case of
+   * a leap day or leap second, the fields will change in
+   * relation to the existence of such an event in the new year.
+   * For example, if the date specifies February the 29th, 2000,
+   * then this will become March the 1st if the year is changed
+   * to 2001, as 2001 is not a leap year.  Similarly, a seconds
+   * value of 60 or 61 may result in the seconds becoming 0 and
+   * the minute increasing by 1, if the new time does not include
+   * a leap second.
+   *
+   * @param year the year minus 1900.
+   * @deprecated Use Calendar instead of Date, and use
+   * set(Calendar.YEAR, year) instead.  Note about the 1900
+   * difference in year.  
+   * @see #getYear()
+   * @see Calendar
+   */
+  public void setYear(int year)
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    cal.set(Calendar.YEAR, 1900 + year);
+    time = cal.getTimeInMillis();
+  }
+
+  /**
+   * Returns the month represented by this <code>Date</code> object,
+   * as a value between 0 (January) and 11 (December).
+   *
+   * @return the month represented by this date object (zero based).
+   * @deprecated Use Calendar instead of Date, and use get(Calendar.MONTH)
+   * instead.
+   * @see #setMonth(int)
+   * @see Calendar
+   */
+  public int getMonth()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    return cal.get(Calendar.MONTH);
+  }
+
+  /**
+   * Sets the month to the given value.  The other
+   * fields are only altered as necessary to match
+   * the same date and time in the new month.  In most
+   * cases, the other fields won't change at all.  However,
+   * in the case of a shorter month or a leap second, values
+   * may be adjusted.  For example, if the day of the month
+   * is currently 31, and the month value is changed from
+   * January (0) to September (8), the date will become
+   * October the 1st, as September only has 30 days.  Similarly,
+   * a seconds value of 60 or 61 (a leap second) may result
+   * in the seconds value being reset to 0 and the minutes
+   * value being incremented by 1, if the new time does
+   * not include a leap second.
+   * 
+   * @param month the month, with a zero-based index
+   *        from January.
+   * @deprecated Use Calendar instead of Date, and use
+   * set(Calendar.MONTH, month) instead.
+   * @see #getMonth()
+   * @see Calendar 
+   */
+  public void setMonth(int month)
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    cal.set(Calendar.MONTH, month);
+    time = cal.getTimeInMillis();
+  }
+
+  /**
+   * Returns the day of the month of this <code>Date</code>
+   * object, as a value between 0 and 31.
+   *
+   * @return the day of month represented by this date object.
+   * @deprecated Use Calendar instead of Date, and use get(Calendar.DATE)
+   * instead.
+   * @see Calendar
+   * @see #setDate(int)
+   */
+  public int getDate()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    return cal.get(Calendar.DATE);
+  }
+
+  /**
+   * Sets the date to the given value. The other
+   * fields are only altered as necessary to match
+   * the same date and time on the new day of the month.  In most
+   * cases, the other fields won't change at all.  However,
+   * in the case of a leap second or the day being out of
+   * the range of the current month, values
+   * may be adjusted.  For example, if the day of the month
+   * is currently 30 and the month is June, a new day of the
+   * month value of 31 will cause the month to change to July,
+   * as June only has 30 days .  Similarly,
+   * a seconds value of 60 or 61 (a leap second) may result
+   * in the seconds value being reset to 0 and the minutes
+   * value being incremented by 1, if the new time does
+   * not include a leap second.
+   *
+   * @param date the date.
+   * @deprecated Use Calendar instead of Date, and use
+   * set(Calendar.DATE, date) instead. 
+   * @see Calendar
+   * @see #getDate()
+   */
+  public void setDate(int date)
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    cal.set(Calendar.DATE, date);
+    time = cal.getTimeInMillis();
+  }
+
+  /**
+   * Returns the day represented by this <code>Date</code>
+   * object as an integer between 0 (Sunday) and 6 (Saturday).
+   *
+   * @return the day represented by this date object.
+   * @deprecated Use Calendar instead of Date, and use get(Calendar.DAY_OF_WEEK)
+   * instead.
+   * @see Calendar
+   */
+  public int getDay()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    // For Calendar, Sunday is 1.  For Date, Sunday is 0.
+    return cal.get(Calendar.DAY_OF_WEEK) - 1;
+  }
+
+  /**
+   * Returns the hours represented by this <code>Date</code>
+   * object as an integer between 0 and 23.
+   *
+   * @return the hours represented by this date object.
+   * @deprecated Use Calendar instead of Date, and use get(Calendar.HOUR_OF_DAY)
+   * instead.
+   * @see Calendar
+   * @see #setHours(int)
+   */
+  public int getHours()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    return cal.get(Calendar.HOUR_OF_DAY);
+  }
+
+  /**
+   * Sets the hours to the given value.  The other
+   * fields are only altered as necessary to match
+   * the same date and time in the new hour.  In most
+   * cases, the other fields won't change at all.  However,
+   * in the case of a leap second, values
+   * may be adjusted.  For example,
+   * a seconds value of 60 or 61 (a leap second) may result
+   * in the seconds value being reset to 0 and the minutes
+   * value being incremented by 1 if the new hour does
+   * not contain a leap second.
+   *
+   * @param hours the hours.
+   * @deprecated Use Calendar instead of Date, and use
+   * set(Calendar.HOUR_OF_DAY, hours) instead.
+   * @see Calendar
+   * @see #getHours() 
+   */
+  public void setHours(int hours)
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    cal.set(Calendar.HOUR_OF_DAY, hours);
+    time = cal.getTimeInMillis();
+  }
+
+  /**
+   * Returns the number of minutes represented by the <code>Date</code>
+   * object, as an integer between 0 and 59.
+   *
+   * @return the minutes represented by this date object.
+   * @deprecated Use Calendar instead of Date, and use get(Calendar.MINUTE)
+   * instead.
+   * @see Calendar
+   * @see #setMinutes(int)
+   */
+  public int getMinutes()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    return cal.get(Calendar.MINUTE);
+  }
+
+  /**
+   * Sets the minutes to the given value.  The other
+   * fields are only altered as necessary to match
+   * the same date and time in the new minute.  In most
+   * cases, the other fields won't change at all.  However,
+   * in the case of a leap second, values
+   * may be adjusted.  For example,
+   * a seconds value of 60 or 61 (a leap second) may result
+   * in the seconds value being reset to 0 and the minutes
+   * value being incremented by 1 if the new minute does
+   * not contain a leap second.
+   *
+   * @param minutes the minutes.
+   * @deprecated Use Calendar instead of Date, and use
+   * set(Calendar.MINUTE, minutes) instead. 
+   * @see Calendar
+   * @see #getMinutes()
+   */
+  public void setMinutes(int minutes)
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    cal.set(Calendar.MINUTE, minutes);
+    time = cal.getTimeInMillis();
+  }
+
+  /**
+   * Returns the number of seconds represented by the <code>Date</code>
+   * object, as an integer between 0 and 61 (60 and 61 being leap seconds).
+   *
+   * @return the seconds represented by this date object.
+   * @deprecated Use Calendar instead of Date, and use get(Calendar.SECOND)
+   * instead.
+   * @see Calendar
+   * @see #setSeconds(int)
+   */
+  public int getSeconds()
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    return cal.get(Calendar.SECOND);
+  }
+
+  /**
+   * Sets the seconds to the given value.  The other
+   * fields are only altered as necessary to match
+   * the same date and time in the new minute.  In most
+   * cases, the other fields won't change at all.  However,
+   * in the case of a leap second, values
+   * may be adjusted.  For example, setting the
+   * seconds value to 60 or 61 (a leap second) may result
+   * in the seconds value being reset to 0 and the minutes
+   * value being incremented by 1, if the current time does
+   * not contain a leap second.
+   *
+   * @param seconds the seconds.
+   * @deprecated Use Calendar instead of Date, and use
+   * set(Calendar.SECOND, seconds) instead.
+   * @see Calendar
+   * @see #getSeconds() 
+   */
+  public void setSeconds(int seconds)
+  {
+    Calendar cal = Calendar.getInstance();
+    cal.setTimeInMillis(time);
+    cal.set(Calendar.SECOND, seconds);
+    time = cal.getTimeInMillis();
+  }
+
+  /**
+   * Deserializes a <code>Date</code> object from an
+   * input stream, setting the time (in milliseconds
+   * since the epoch) to the long value read from the
+   * stream.
+   *
+   * @param input the input stream.
+   * @throws IOException if an I/O error occurs in the stream.
+   * @throws ClassNotFoundException if the class of the
+   *         serialized object could not be found.
+   */
+  private void readObject(ObjectInputStream input)
+    throws IOException, ClassNotFoundException
+  {
+    input.defaultReadObject();
+    time = input.readLong();
+  }
+
+  /**
+   * Serializes a <code>Date</code> object to an output stream,
+   * storing the time (in milliseconds since the epoch) as a long
+   * value in the stream.
+   *
+   * @serialdata A long value representing the offset from the epoch
+   * in milliseconds.  This is the same value that is returned by the
+   * method getTime().
+   * @param output the output stream.
+   * @throws IOException if an I/O error occurs in the stream.
+   */
+  private void writeObject(ObjectOutputStream output)
+    throws IOException
+  {
+    output.defaultWriteObject();
+    output.writeLong(time);
+  }
+
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Dictionary.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Dictionary.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Dictionary.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Dictionary.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,136 @@
+/* Dictionary.java -- an abstract (and essentially worthless) 
+   class which is Hashtable's superclass
+   Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A Dictionary maps keys to values; <i>how</i> it does that is
+ * implementation-specific.
+ * 
+ * This is an abstract class which has really gone by the wayside.
+ * People at Javasoft are probably embarrassed by it.  At this point,
+ * it might as well be an interface rather than a class, but it remains
+ * this poor, laughable skeleton for the sake of backwards compatibility.
+ * At any rate, this was what came before the {@link Map} interface 
+ * in the Collections framework.
+ *
+ * @author Jon Zeppieri
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Map
+ * @see Hashtable
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public abstract class Dictionary
+{
+  // WARNING: Dictionary is a CORE class in the bootstrap cycle. See the
+  // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+  /**
+   * Sole constructor (often called implicitly).
+   */
+  public Dictionary()
+  {
+  }
+
+  /**
+   * Returns an Enumeration of the values in this Dictionary.
+   *
+   * @return an Enumeration of the values
+   * @see #keys()
+   */
+  public abstract Enumeration elements();
+
+  /** 
+   * Returns the value associated with the supplied key, or null
+   * if no such value exists. Since Dictionaries are not allowed null keys
+   * or elements, a null result always means the key is not present.
+   *
+   * @param key the key to use to fetch the value
+   * @return the mapped value
+   * @throws NullPointerException if key is null
+   * @see #put(Object, Object)
+   */
+  public abstract Object get(Object key);
+
+  /**
+   * Returns true when there are no elements in this Dictionary.
+   *
+   * @return <code>size() == 0</code>
+   */
+  public abstract boolean isEmpty();
+
+  /**
+   * Returns an Enumeration of the keys in this Dictionary
+   *
+   * @return an Enumeration of the keys
+   * @see #elements()
+   */
+  public abstract Enumeration keys();
+
+  /**
+   * Inserts a new value into this Dictionary, located by the
+   * supplied key. Dictionary does not support null keys or values, so
+   * a null return can safely be interpreted as adding a new key.
+   *
+   * @param key the key which locates the value
+   * @param value the value to put into the Dictionary
+   * @return the previous value of the key, or null if there was none
+   * @throws NullPointerException if key or value is null
+   * @see #get(Object)
+   */
+  public abstract Object put(Object key, Object value);
+
+  /**
+   * Removes from the Dictionary the value located by the given key. A null
+   * return safely means that the key was not mapped in the Dictionary.
+   *
+   * @param key the key used to locate the value to be removed
+   * @return the value associated with the removed key
+   * @throws NullPointerException if key is null
+   */
+  public abstract Object remove(Object key);
+
+  /**
+   * Returns the number of values currently in this Dictionary.
+   *
+   * @return the number of keys in the Dictionary
+   */
+  public abstract int size();
+} // class Dictionary

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/DuplicateFormatFlagsException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/DuplicateFormatFlagsException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/DuplicateFormatFlagsException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/DuplicateFormatFlagsException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,88 @@
+/* DuplicateFormatFlagsException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when the flags supplied to the {@link Formatter#format()}
+ * method of a {@link Formatter} contain duplicates.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class DuplicateFormatFlagsException 
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 18890531L;
+
+  /**
+   * The flags which contain a duplicate.
+   *
+   * @serial the flags containing a duplicate.
+   */
+  // Note: name fixed by serialization.
+  private String flags;
+
+  /**
+   * Constructs a new <code>DuplicateFormatFlagsException</code>
+   * which specifies that the supplied set of flags contains a
+   * duplicate.
+   *
+   * @param flags the flags containing a duplicate.
+   * @throws NullPointerException if <code>flags</code> is null.
+   */
+  public DuplicateFormatFlagsException(String flags)
+  {
+    super("Duplicate flag passed in " + flags);
+    if (flags == null)
+      throw new
+	NullPointerException("Null flags value passed to constructor.");
+    this.flags = flags;
+  }
+
+  /**
+   * Returns the flags which contain a duplicate.
+   *
+   * @return the flags.
+   */
+  public String getFlags()
+  {
+    return flags;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/EmptyStackException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/EmptyStackException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/EmptyStackException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/EmptyStackException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,69 @@
+/* EmptyStackException.java -- Attempt to pop from an empty stack
+   Copyright (C) 1998, 1999, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ */
+
+/**
+ * This exception is thrown by the Stack class when an attempt is made to pop
+ * or otherwise access elements from an empty stack.
+ *
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Stack
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class EmptyStackException extends RuntimeException
+{
+  /**
+   * Compatible with JDK 1.0.
+   */
+  private static final long serialVersionUID = 5084686378493302095L;
+
+  /**
+   * Constructs an EmptyStackException with no detail message.
+   */
+  public EmptyStackException()
+  {
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Enumeration.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Enumeration.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Enumeration.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Enumeration.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,81 @@
+/* Enumeration.java -- Interface for enumerating lists of objects
+   Copyright (C) 1998, 1999, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1.
+ * Status:  Believed complete and correct
+ */
+
+/**
+ * Interface for lists of objects that can be returned in sequence. Successive
+ * objects are obtained by the nextElement method.
+ * <p>
+ * As of Java 1.2, the Iterator interface provides the same functionality, but
+ * with shorter method names and a new optional method to remove items from the
+ * list. If writing for 1.2, consider using Iterator instead. Enumerations over
+ * the new collections classes, for use with legacy APIs that require them, can
+ * be obtained by the enumeration method in class Collections.
+ *
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Iterator
+ * @see Hashtable
+ * @see Vector
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public interface Enumeration
+{
+  /**
+   * Tests whether there are elements remaining in the enumeration.
+   *
+   * @return true if there is at least one more element in the enumeration,
+   *         that is, if the next call to nextElement will not throw a
+   *         NoSuchElementException.
+   */
+  boolean hasMoreElements();
+
+  /**
+   * Obtain the next element in the enumeration.
+   *
+   * @return the next element in the enumeration
+   * @throws NoSuchElementException if there are no more elements
+   */
+  Object nextElement();
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventListener.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventListener.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventListener.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventListener.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,54 @@
+/* EventListener.java -- tagging interface for all event listeners
+   Copyright (C) 1998, 1999, 2001, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Empty interface that is implemented by classes that need to receive
+ * events. Subinterfaces define methods that can be called to fire an
+ * event notification. Normally the name of these subinterfaces end in
+ * <code>Listener</code> and all method described by the subinterface
+ * take as argument an subclass of <code>EventObject</code>.
+ *
+ * @author Tom Tromey (tromey at cygnus.com)
+ * @see EventObject
+ * @status updated to 1.4
+ */
+public interface EventListener
+{
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventListenerProxy.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventListenerProxy.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventListenerProxy.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventListenerProxy.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,75 @@
+/* EventListenerProxy.java -- abstract wrapper for event listeners
+   Copyright (C) 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An abstract wrapper for event listeners.  This allows subclasses to
+ * attach additional parameters to an existing event listener to create
+ * a new one.  Subclasses are expected to add methods to set and retrieve
+ * any attached properties.
+ *
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public abstract class EventListenerProxy implements EventListener
+{
+  /** The listener that this proxy wraps. */
+  private final EventListener listener;
+
+  /**
+   * Construct a proxy event listener, given an existing one to augment.
+   *
+   * @param listener the listener to wrap
+   */
+  public EventListenerProxy(EventListener listener)
+  {
+    this.listener = listener;
+  }
+
+  /**
+   * Return the wrapped event listener.
+   *
+   * @return the listener associated with this proxy
+   */
+  public EventListener getListener()
+  {
+    return listener;
+  }
+} // class EventListenerProxy

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventObject.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventObject.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventObject.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/EventObject.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,101 @@
+/* EventObject.java -- represents an event on an object
+   Copyright (C) 1999, 2000, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * Represents Events fired by Objects.
+ *
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see EventListener
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class EventObject implements Serializable
+{
+  /**
+   * Compatible with JDK 1.1+.
+   */
+  private static final long serialVersionUID = 5516075349620653480L;
+
+  /**
+   * The source object; in other words, the object which this event takes
+   * place on.
+   */
+  protected transient Object source;
+
+  /**
+   * Constructs an EventObject with the specified source.
+   *
+   * @param source the source of the event
+   * @throws IllegalArgumentException if source is null (This is not
+   *         specified, but matches the behavior of the JDK)
+   */
+  public EventObject(Object source)
+  {
+    // This check for null is stupid, if you ask me, since source is
+    // protected and non-final, so a subclass can set it to null later on.
+    if (source == null)
+      throw new IllegalArgumentException();
+    this.source = source;
+  }
+
+  /**
+   * Returns the source of the event.
+   *
+   * @return the event source
+   */
+  public Object getSource()
+  {
+    return source;
+  }
+
+  /**
+   * Converts the event to a String. The format is not specified, but by
+   * observation, the JDK uses:
+   * <code>getClass().getName() + "[source=" + source + "]";</code>.
+   *
+   * @return String representation of the Event
+   */
+  public String toString()
+  {
+    return getClass().getName() + "[source=" + source + "]";
+  }
+} // class EventObject

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormatFlagsConversionMismatchException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormatFlagsConversionMismatchException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormatFlagsConversionMismatchException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormatFlagsConversionMismatchException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,111 @@
+/* FormatFlagsConversionMismatchException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when the flags supplied to the {@link Formatter#format()}
+ * method of a {@link Formatter} contains a flag that does not match
+ * the conversion character specified for it.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class FormatFlagsConversionMismatchException
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 19120414L;
+
+  /**
+   * The mismatching flag.
+   *
+   * @serial the mismatching flag.
+   */
+  // Note: name fixed by serialization.
+  private String f;
+
+  /**
+   * The conversion character which doesn't match the
+   * appropriate flag.
+   *
+   * @serial the conversion character which doesn't match its flag.
+   */
+  // Note: name fixed by serialization.
+  private char c;
+
+  /**
+   * Constructs a new <code>FormatFlagsConversionMismatchException</code>
+   * which specifies that the flag, <code>f</code>, does
+   * not match its appropriate conversion character, <code>c</code>.
+   *
+   * @param f the mismatching flag.
+   * @param c the conversion character which doesn't match its flag.
+   * @throws NullPointerException if <code>f</code> is null.
+   */
+  public FormatFlagsConversionMismatchException(String f, char c)
+  {
+    super("Invalid flag " + f + " for conversion " + c);
+    if (f == null)
+      throw new
+	NullPointerException("Null flag value passed to constructor.");
+    this.f = f;
+    this.c = c;
+  }
+
+  /**
+   * Returns the conversion character which doesn't
+   * match the flag.
+   *
+   * @return the conversion character.
+   */
+  public char getConversion()
+  {
+    return c;
+  }
+
+  /**
+   * Returns the mismatching flag.
+   *
+   * @return the mismatching flag.
+   */
+  public String getFlags()
+  {
+    return f;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Formattable.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Formattable.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Formattable.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Formattable.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,92 @@
+/* Formattable.java -- Objects which can be passed to a Formatter
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * <p>
+ * The <code>Formattable</code> interface is used to provide customised
+ * formatting to arbitrary objects via the {@link Formatter}.  The
+ * {@link #formatTo} method is called for <code>Formattable</code>
+ * objects used with the 's' conversion operator, allowing the object
+ * to provide its own formatting of its internal data.
+ * </p>
+ * <p>
+ * Thread safety is left up to the implementing class.  Thus,
+ * {@link Formattable} objects are not guaranteed to be thread-safe,
+ * and users should make their own provisions for multiple thread access.
+ * </p>
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public interface Formattable
+{
+
+  /**
+   * Formats the object using the supplied formatter to the specification
+   * provided by the given flags, width and precision.
+   *
+   * @param formatter the formatter to use for formatting the object.
+   *                  The formatter gives access to the output stream
+   *                  and locale via {@link Formatter#out()} and
+   *                  {@link Formatter#locale()} respectively.
+   * @param flags a bit mask constructed from the flags in the
+   *              {@link FormattableFlags} class.  When no flags
+   *              are set, the implementing class should use its
+   *              defaults.
+   * @param width the minimum number of characters to include.
+   *              A value of -1 indicates no minimum.  The remaining
+   *              space is padded with ' ' either on the left
+   *              (the default) or right (if left justification is
+   *              specified by the flags).
+   * @param precision the maximum number of characters to include.
+   *              A value of -1 indicates no maximum.  This value
+   *              is applied prior to the minimum (the width).  Thus,
+   *              a value may meet the minimum width initially, but
+   *              not when the width value is applied, due to
+   *              characters being removed by the precision value.
+   * @throws IllegalFormatException if there is a problem with
+   *                                the syntax of the format
+   *                                specification or a mismatch
+   *                                between it and the arguments.
+   */
+  public void formatTo(Formatter formatter, int flags, int width,
+		       int precision);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormattableFlags.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormattableFlags.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormattableFlags.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormattableFlags.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,123 @@
+/* FormattableFlags.java --
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * This class contains a set of flags used
+ * by the {@link Formattable#formatTo()} method.
+ * They are used to modify the output of the
+ * {@link Formattable}.  The interpretation and
+ * validation of the flags is left to the
+ * particular {@link Formattable}.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class FormattableFlags
+{
+
+  /**
+   * Requires the output to be left-justified.  Any spaces
+   * required to meet the specified width will be added to
+   * the right of the output.  The default output is
+   * right-justified, where spaces are added to the left.
+   * The output is as for the format specifier
+   * '-' ('\u002d').
+   */
+  public static final int LEFT_JUSTIFY = 1;
+
+  /**
+   * Requires the output to be in uppercase.  The output
+   * should be the same as the result from calling
+   * {@link String#toUpperCase(java.util.Locale)} with
+   * the formatting locale. The output is as for the
+   * format specifier '^' ('\u005e').
+   */
+  public static final int UPPERCASE = 2;
+
+  /**
+   * Requires the use of an alternate form, as specified
+   * in the documentation of {@link Formattable}.
+   * The output is as for the format specifier
+   * '#' ('\u0023').
+   */
+  public static final int ALTERNATE = 4;
+
+  // Used internally by Formatter.
+  // Changes here must be reflected in the FLAGS string there.
+
+  /**
+   * Requires the output to always include a '+' sign.
+   * The output is as for the format specifier '+'.
+   */
+  static final int PLUS = 8;
+
+  /**
+   * Requires the output to include a leading space on
+   * positive value.  The output is as for the format
+   * specifier ' '.
+   */
+  static final int SPACE = 16;
+
+  /**
+   * Requires the output to be zero-padded.  The output
+   * is as for the format specifier '0'.
+   */
+  static final int ZERO = 32;
+
+  /**
+   * Requires the output to include locale-specific
+   * grouping operators.  The output is as for the
+   * format specifier ','.
+   */
+  static final int COMMA = 64;
+
+  /**
+   * Requires the output to include negative numbers
+   * enclosed in parentheses.  The output is as for
+   * the format specifier '('.
+   */
+  static final int PAREN = 128;
+
+  // Not instantiable.
+  private FormattableFlags()
+  {
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Formatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Formatter.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Formatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Formatter.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1294 @@
+/* Formatter.java -- printf-style formatting
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.text.DateFormatSymbols;
+import java.text.DecimalFormatSymbols;
+
+import gnu.classpath.SystemProperties;
+
+/** 
+ * <p>
+ * A Java formatter for <code>printf</code>-style format strings,
+ * as seen in the C programming language.   This differs from the
+ * C interpretation of such strings by performing much stricter
+ * checking of format specifications and their corresponding
+ * arguments.  While unknown conversions will be ignored in C,
+ * and invalid conversions will only produce compiler warnings,
+ * the Java version utilises a full range of run-time exceptions to
+ * handle these cases.  The Java version is also more customisable
+ * by virtue of the provision of the {@link Formattable} interface,
+ * which allows an arbitrary class to be formatted by the formatter.
+ * </p>
+ * <p>
+ * The formatter is accessible by more convienient static methods.
+ * For example, streams now have appropriate format methods
+ * (the equivalent of <code>fprintf</code>) as do <code>String</code>
+ * objects (the equivalent of <code>sprintf</code>).
+ * </p>
+ * <p>
+ * <strong>Note</strong>: the formatter is not thread-safe.  For
+ * multi-threaded access, external synchronization should be provided.
+ * </p>
+ *  
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public final class Formatter 
+  implements Closeable, Flushable
+{
+
+  /**
+   * The output of the formatter.
+   */
+  private StringBuilder out;
+
+  /**
+   * The locale used by the formatter.
+   */
+  private Locale locale;
+
+  /**
+   * Whether or not the formatter is closed.
+   */
+  private boolean closed;
+
+  /**
+   * The last I/O exception thrown by the output stream.
+   */
+  private IOException ioException;
+
+  // Some state used when actually formatting.
+  /**
+   * The format string.
+   */
+  private String format;
+
+  /**
+   * The current index into the string.
+   */
+  private int index;
+
+  /**
+   * The length of the format string.
+   */
+  private int length;
+
+  /**
+   * The formatting locale.
+   */
+  private Locale fmtLocale;
+
+  // Note that we include '-' twice.  The flags are ordered to
+  // correspond to the values in FormattableFlags, and there is no
+  // flag (in the sense of this field used when parsing) for
+  // UPPERCASE; the second '-' serves as a placeholder.
+  /**
+   * A string used to index into the formattable flags.
+   */
+  private static final String FLAGS = "--#+ 0,(";
+
+  /**
+   * The system line separator.
+   */
+  private static final String lineSeparator
+    = SystemProperties.getProperty("line.separator");
+
+  /**
+   * Constructs a new <code>Formatter</code> using the default
+   * locale and a {@link StringBuilder} as the output stream.
+   */
+  public Formatter()
+  {
+    this(null, Locale.getDefault());
+  }
+
+  /**
+   * Constructs a new <code>Formatter</code> using the specified
+   * locale and a {@link StringBuilder} as the output stream.
+   * If the locale is <code>null</code>, then no localization
+   * is applied.
+   *
+   * @param loc the locale to use.
+   */
+  public Formatter(Locale loc)
+  {
+    this(null, loc);
+  }
+
+  /**
+   * Constructs a new <code>Formatter</code> using the default
+   * locale and the specified output stream.
+   *
+   * @param app the output stream to use.
+   */
+  public Formatter(StringBuilder app)
+  {
+    this(app, Locale.getDefault());
+  }
+
+  /**
+   * Constructs a new <code>Formatter</code> using the specified
+   * locale and the specified output stream.  If the locale is
+   * <code>null</code>, then no localization is applied.
+   *
+   * @param app the output stream to use.
+   * @param loc the locale to use.
+   */
+  public Formatter(StringBuilder app, Locale loc)
+  {
+    this.out = app == null ? new StringBuilder() : app;
+    this.locale = loc;
+  }
+
+  /**
+   * Closes the formatter, so as to release used resources.
+   * If the underlying output stream supports the {@link Closeable}
+   * interface, then this is also closed.  Attempts to use
+   * a formatter instance, via any method other than
+   * {@link #ioException()}, after closure results in a
+   * {@link FormatterClosedException}.
+   */
+  public void close()
+  {
+    if (closed)
+      return;
+    closed = true;
+  }
+
+  /**
+   * Flushes the formatter, writing any cached data to the output
+   * stream.  If the underlying output stream supports the
+   * {@link Flushable} interface, it is also flushed.
+   *
+   * @throws FormatterClosedException if the formatter is closed.
+   */
+  public void flush()
+  {
+    if (closed)
+      throw new FormatterClosedException();
+  }
+
+  /**
+   * Return the name corresponding to a flag.
+   *
+   * @param flags the flag to return the name of.
+   * @return the name of the flag.
+   */
+  private String getName(int flags)
+  {
+    // FIXME: do we want all the flags in here?
+    // Or should we redo how this is reported?
+    int bit = Integer.numberOfTrailingZeros(flags);
+    return FLAGS.substring(bit, bit + 1);
+  }
+
+  /**
+   * Verify the flags passed to a conversion.
+   *
+   * @param flags the flags to verify.
+   * @param allowed the allowed flags mask.
+   * @param conversion the conversion character.
+   */
+  private void checkFlags(int flags, int allowed, char conversion)
+  {
+    flags &= ~allowed;
+    if (flags != 0)
+      throw new FormatFlagsConversionMismatchException(getName(flags),
+						       conversion);
+  }
+
+  /**
+   * Throw an exception if a precision was specified.
+   *
+   * @param precision the precision value (-1 indicates not specified).
+   */
+  private void noPrecision(int precision)
+  {
+    if (precision != -1)
+      throw new IllegalFormatPrecisionException(precision);
+  }
+
+  /**
+   * Apply the numeric localization algorithm to a StringBuilder.
+   *
+   * @param builder the builder to apply to.
+   * @param flags the formatting flags to use.
+   * @param width the width of the numeric value.
+   * @param isNegative true if the value is negative.
+   */
+  private void applyLocalization(StringBuilder builder, int flags, int width,
+				 boolean isNegative)
+  {
+    DecimalFormatSymbols dfsyms;
+    if (fmtLocale == null)
+      dfsyms = new DecimalFormatSymbols();
+    else
+      dfsyms = new DecimalFormatSymbols(fmtLocale);
+
+    // First replace each digit.
+    char zeroDigit = dfsyms.getZeroDigit();
+    int decimalOffset = -1;
+    for (int i = builder.length() - 1; i >= 0; --i)
+      {
+	char c = builder.charAt(i);
+	if (c >= '0' && c <= '9')
+	  builder.setCharAt(i, (char) (c - '0' + zeroDigit));
+	else if (c == '.')
+	  {
+	    assert decimalOffset == -1;
+	    decimalOffset = i;
+	  }
+      }
+
+    // Localize the decimal separator.
+    if (decimalOffset != -1)
+      {
+	builder.deleteCharAt(decimalOffset);
+	builder.insert(decimalOffset, dfsyms.getDecimalSeparator());
+      }
+	
+    // Insert the grouping separators.
+    if ((flags & FormattableFlags.COMMA) != 0)
+      {
+	char groupSeparator = dfsyms.getGroupingSeparator();
+	int groupSize = 3;	// FIXME
+	int offset = (decimalOffset == -1) ? builder.length() : decimalOffset;
+	// We use '>' because we don't want to insert a separator
+	// before the first digit.
+	for (int i = offset - groupSize; i > 0; i -= groupSize)
+	  builder.insert(i, groupSeparator);
+      }
+
+    if ((flags & FormattableFlags.ZERO) != 0)
+      {
+	// Zero fill.  Note that according to the algorithm we do not
+	// insert grouping separators here.
+	for (int i = width - builder.length(); i > 0; --i)
+	  builder.insert(0, zeroDigit);
+      }
+
+    if (isNegative)
+      {
+	if ((flags & FormattableFlags.PAREN) != 0)
+	  {
+	    builder.insert(0, '(');
+	    builder.append(')');
+	  }
+	else
+	  builder.insert(0, '-');
+      }
+    else if ((flags & FormattableFlags.PLUS) != 0)
+      builder.insert(0, '+');
+    else if ((flags & FormattableFlags.SPACE) != 0)
+      builder.insert(0, ' ');
+  }
+
+  /**
+   * A helper method that handles emitting a String after applying
+   * precision, width, justification, and upper case flags.
+   *
+   * @param arg the string to emit.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void genericFormat(String arg, int flags, int width, int precision)
+    throws IOException
+  {
+    if ((flags & FormattableFlags.UPPERCASE) != 0)
+      {
+	if (fmtLocale == null)
+	  arg = arg.toUpperCase();
+	else
+	  arg = arg.toUpperCase(fmtLocale);
+      }
+
+    if (precision >= 0 && arg.length() > precision)
+      arg = arg.substring(0, precision);
+
+    boolean leftJustify = (flags & FormattableFlags.LEFT_JUSTIFY) != 0;
+    if (leftJustify && width == -1)
+      throw new MissingFormatWidthException("fixme");
+    if (! leftJustify && arg.length() < width)
+      {
+	for (int i = width - arg.length(); i > 0; --i)
+	  out.append(' ');
+      }
+    out.append(arg);
+    if (leftJustify && arg.length() < width)
+      {
+	for (int i = width - arg.length(); i > 0; --i)
+	  out.append(' ');
+      }
+  }
+
+  /** 
+   * Emit a boolean.  
+   *
+   * @param arg the boolean to emit.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @param conversion the conversion character.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void booleanFormat(Object arg, int flags, int width, int precision,
+			     char conversion)
+    throws IOException
+  {
+    checkFlags(flags,
+	       FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
+	       conversion);
+    String result;
+    if (arg instanceof Boolean)
+      result = String.valueOf((Boolean) arg);
+    else
+      result = arg == null ? "false" : "true";
+    genericFormat(result, flags, width, precision);
+  }
+
+  /** 
+   * Emit a hash code.  
+   *
+   * @param arg the hash code to emit.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @param conversion the conversion character.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void hashCodeFormat(Object arg, int flags, int width, int precision,
+			      char conversion)
+    throws IOException
+  {
+    checkFlags(flags,
+	       FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
+	       conversion);
+    genericFormat(arg == null ? "null" : Integer.toHexString(arg.hashCode()),
+		  flags, width, precision);
+  }
+
+  /** 
+   * Emit a String or Formattable conversion.  
+   *
+   * @param arg the String or Formattable to emit.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @param conversion the conversion character.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void stringFormat(Object arg, int flags, int width, int precision,
+			    char conversion)
+    throws IOException
+  {
+    if (arg instanceof Formattable)
+      {
+	checkFlags(flags,
+		   (FormattableFlags.LEFT_JUSTIFY
+		    | FormattableFlags.UPPERCASE
+		    | FormattableFlags.ALTERNATE),
+		   conversion);
+	Formattable fmt = (Formattable) arg;
+	fmt.formatTo(this, flags, width, precision);
+      }
+    else
+      {
+	checkFlags(flags,
+		   FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
+		   conversion);
+	genericFormat(arg == null ? "null" : arg.toString(), flags, width,
+		      precision);
+      }
+  }
+
+  /** 
+   * Emit a character.  
+   *
+   * @param arg the character to emit.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @param conversion the conversion character.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void characterFormat(Object arg, int flags, int width, int precision,
+			       char conversion)
+    throws IOException
+  {
+    checkFlags(flags,
+	       FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
+	       conversion);
+    noPrecision(precision);
+
+    int theChar;
+    if (arg instanceof Character)
+      theChar = ((Character) arg).charValue();
+    else if (arg instanceof Byte)
+      theChar = (char) (((Byte) arg).byteValue ());
+    else if (arg instanceof Short)
+      theChar = (char) (((Short) arg).shortValue ());
+    else if (arg instanceof Integer)
+      {
+	theChar = ((Integer) arg).intValue();
+	if (! Character.isValidCodePoint(theChar))
+	  throw new IllegalFormatCodePointException(theChar);
+      }
+    else
+      throw new IllegalFormatConversionException(conversion, arg.getClass());
+    String result = new String(Character.toChars(theChar));
+    genericFormat(result, flags, width, precision);
+  }
+
+  /** 
+   * Emit a '%'.
+   *
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void percentFormat(int flags, int width, int precision)
+    throws IOException
+  {
+    checkFlags(flags, FormattableFlags.LEFT_JUSTIFY, '%');
+    noPrecision(precision);
+    genericFormat("%", flags, width, precision);
+  }
+
+  /** 
+   * Emit a newline.
+   *
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void newLineFormat(int flags, int width, int precision)
+    throws IOException
+  {
+    checkFlags(flags, 0, 'n');
+    noPrecision(precision);
+    if (width != -1)
+      throw new IllegalFormatWidthException(width);
+    genericFormat(lineSeparator, flags, width, precision);
+  }
+
+  /**
+   * Helper method to do initial formatting and checking for integral
+   * conversions.
+   *
+   * @param arg the formatted argument.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @param radix the radix of the number.
+   * @param conversion the conversion character.
+   * @return the result.
+   */
+  private StringBuilder basicIntegralConversion(Object arg, int flags,
+						int width, int precision,
+						int radix, char conversion)
+  {
+    assert radix == 8 || radix == 10 || radix == 16;
+    noPrecision(precision);
+
+    // Some error checking.
+    if ((flags & FormattableFlags.ZERO) != 0
+	&& (flags & FormattableFlags.LEFT_JUSTIFY) == 0)
+      throw new IllegalFormatFlagsException(getName(flags));
+    if ((flags & FormattableFlags.PLUS) != 0
+	&& (flags & FormattableFlags.SPACE) != 0)
+      throw new IllegalFormatFlagsException(getName(flags));
+
+    if ((flags & FormattableFlags.LEFT_JUSTIFY) != 0 && width == -1)
+      throw new MissingFormatWidthException("fixme");
+
+    // Do the base translation of the value to a string.
+    String result;
+    int basicFlags = (FormattableFlags.LEFT_JUSTIFY
+		      // We already handled any possible error when
+		      // parsing.
+		      | FormattableFlags.UPPERCASE
+		      | FormattableFlags.ZERO);
+    if (radix == 10)
+      basicFlags |= (FormattableFlags.PLUS
+		     | FormattableFlags.SPACE
+		     | FormattableFlags.COMMA
+		     | FormattableFlags.PAREN);
+    else
+      basicFlags |= FormattableFlags.ALTERNATE;
+
+    if (arg instanceof BigInteger)
+      {
+	checkFlags(flags,
+		   (basicFlags
+		    | FormattableFlags.PLUS
+		    | FormattableFlags.SPACE
+		    | FormattableFlags.PAREN),
+		   conversion);
+	BigInteger bi = (BigInteger) arg;
+	result = bi.toString(radix);
+      }
+    else if (arg instanceof Number
+	     && ! (arg instanceof Float)
+	     && ! (arg instanceof Double))
+      {
+	checkFlags(flags, basicFlags, conversion);
+	long value = ((Number) arg).longValue ();
+	if (radix == 8)
+	  result = Long.toOctalString(value);
+	else if (radix == 16)
+	  result = Long.toHexString(value);
+	else
+	  result = Long.toString(value);
+      }
+    else
+      throw new IllegalFormatConversionException(conversion, arg.getClass());
+
+    return new StringBuilder(result);
+  }
+
+  /** 
+   * Emit a hex or octal value.  
+   * 
+   * @param arg the hexadecimal or octal value.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @param radix the radix of the number.
+   * @param conversion the conversion character.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void hexOrOctalConversion(Object arg, int flags, int width,
+				    int precision, int radix,
+				    char conversion)
+    throws IOException
+  {
+    assert radix == 8 || radix == 16;
+
+    StringBuilder builder = basicIntegralConversion(arg, flags, width,
+						    precision, radix,
+						    conversion);
+    int insertPoint = 0;
+
+    // Insert the sign.
+    if (builder.charAt(0) == '-')
+      {
+	// Already inserted.  Note that we don't insert a sign, since
+	// the only case where it is needed it BigInteger, and it has
+	// already been inserted by toString.
+	++insertPoint;
+      }
+    else if ((flags & FormattableFlags.PLUS) != 0)
+      {
+	builder.insert(insertPoint, '+');
+	++insertPoint;
+      }
+    else if ((flags & FormattableFlags.SPACE) != 0)
+      {
+	builder.insert(insertPoint, ' ');
+	++insertPoint;
+      }
+
+    // Insert the radix prefix.
+    if ((flags & FormattableFlags.ALTERNATE) != 0)
+      {
+	builder.insert(insertPoint, radix == 8 ? "0" : "0x");
+	insertPoint += radix == 8 ? 1 : 2;
+      }
+
+    // Now justify the result.
+    int resultWidth = builder.length();
+    if (resultWidth < width)
+      {
+	char fill = ((flags & FormattableFlags.ZERO) != 0) ? '0' : ' ';
+	if ((flags & FormattableFlags.LEFT_JUSTIFY) != 0)
+	  {
+	    // Left justify.  
+	    if (fill == ' ')
+	      insertPoint = builder.length();
+	  }
+	else
+	  {
+	    // Right justify.  Insert spaces before the radix prefix
+	    // and sign.
+	    insertPoint = 0;
+	  }
+	while (resultWidth++ < width)
+	  builder.insert(insertPoint, fill);
+      }
+
+    String result = builder.toString();
+    if ((flags & FormattableFlags.UPPERCASE) != 0)
+      {
+	if (fmtLocale == null)
+	  result = result.toUpperCase();
+	else
+	  result = result.toUpperCase(fmtLocale);
+      }
+
+    out.append(result);
+  }
+
+  /** 
+   * Emit a decimal value.  
+   * 
+   * @param arg the hexadecimal or octal value.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @param conversion the conversion character.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void decimalConversion(Object arg, int flags, int width,
+				 int precision, char conversion)
+    throws IOException
+  {
+    StringBuilder builder = basicIntegralConversion(arg, flags, width,
+						    precision, 10,
+						    conversion);
+    boolean isNegative = false;
+    if (builder.charAt(0) == '-')
+      {
+	// Sign handling is done during localization.
+	builder.deleteCharAt(0);
+	isNegative = true;
+      }
+
+    applyLocalization(builder, flags, width, isNegative);
+    genericFormat(builder.toString(), flags, width, precision);
+  }
+
+  /** 
+   * Emit a single date or time conversion to a StringBuilder.  
+   *
+   * @param builder the builder to write to.
+   * @param cal the calendar to use in the conversion.
+   * @param conversion the formatting character to specify the type of data.
+   * @param syms the date formatting symbols.
+   */
+  private void singleDateTimeConversion(StringBuilder builder, Calendar cal,
+					char conversion,
+					DateFormatSymbols syms)
+  {
+    int oldLen = builder.length();
+    int digits = -1;
+    switch (conversion)
+      {
+      case 'H':
+	builder.append(cal.get(Calendar.HOUR_OF_DAY));
+	digits = 2;
+	break;
+      case 'I':
+	builder.append(cal.get(Calendar.HOUR));
+	digits = 2;
+	break;
+      case 'k':
+	builder.append(cal.get(Calendar.HOUR_OF_DAY));
+	break;
+      case 'l':
+	builder.append(cal.get(Calendar.HOUR));
+	break;
+      case 'M':
+	builder.append(cal.get(Calendar.MINUTE));
+	digits = 2;
+	break;
+      case 'S':
+	builder.append(cal.get(Calendar.SECOND));
+	digits = 2;
+	break;
+      case 'N':
+	// FIXME: nanosecond ...
+	digits = 9;
+	break;
+      case 'p':
+	{
+	  int ampm = cal.get(Calendar.AM_PM);
+	  builder.append(syms.getAmPmStrings()[ampm]);
+	}
+	break;
+      case 'z':
+	{
+	  int zone = cal.get(Calendar.ZONE_OFFSET) / (1000 * 60);
+	  builder.append(zone);
+	  digits = 4;
+	  // Skip the '-' sign.
+	  if (zone < 0)
+	    ++oldLen;
+	}
+	break;
+      case 'Z':
+	{
+	  // FIXME: DST?
+	  int zone = cal.get(Calendar.ZONE_OFFSET) / (1000 * 60 * 60);
+	  String[][] zs = syms.getZoneStrings();
+	  builder.append(zs[zone + 12][1]);
+	}
+	break;
+      case 's':
+	{
+	  long val = cal.getTime().getTime();
+	  builder.append(val / 1000);
+	}
+	break;
+      case 'Q':
+	{
+	  long val = cal.getTime().getTime();
+	  builder.append(val);
+	}
+	break;
+      case 'B':
+	{
+	  int month = cal.get(Calendar.MONTH);
+	  builder.append(syms.getMonths()[month]);
+	}
+	break;
+      case 'b':
+      case 'h':
+	{
+	  int month = cal.get(Calendar.MONTH);
+	  builder.append(syms.getShortMonths()[month]);
+	}
+	break;
+      case 'A':
+	{
+	  int day = cal.get(Calendar.DAY_OF_WEEK);
+	  builder.append(syms.getWeekdays()[day]);
+	}
+	break;
+      case 'a':
+	{
+	  int day = cal.get(Calendar.DAY_OF_WEEK);
+	  builder.append(syms.getShortWeekdays()[day]);
+	}
+	break;
+      case 'C':
+	builder.append(cal.get(Calendar.YEAR) / 100);
+	digits = 2;
+	break;
+      case 'Y':
+	builder.append(cal.get(Calendar.YEAR));
+	digits = 4;
+	break;
+      case 'y':
+	builder.append(cal.get(Calendar.YEAR) % 100);
+	digits = 2;
+	break;
+      case 'j':
+	builder.append(cal.get(Calendar.DAY_OF_YEAR));
+	digits = 3;
+	break;
+      case 'm':
+	builder.append(cal.get(Calendar.MONTH) + 1);
+	digits = 2;
+	break;
+      case 'd':
+	builder.append(cal.get(Calendar.DAY_OF_MONTH));
+	digits = 2;
+	break;
+      case 'e':
+	builder.append(cal.get(Calendar.DAY_OF_MONTH));
+	break;
+      case 'R':
+	singleDateTimeConversion(builder, cal, 'H', syms);
+	builder.append(':');
+	singleDateTimeConversion(builder, cal, 'M', syms);
+	break;
+      case 'T':
+	singleDateTimeConversion(builder, cal, 'H', syms);
+	builder.append(':');
+	singleDateTimeConversion(builder, cal, 'M', syms);
+	builder.append(':');
+	singleDateTimeConversion(builder, cal, 'S', syms);
+	break;
+      case 'r':
+	singleDateTimeConversion(builder, cal, 'I', syms);
+	builder.append(':');
+	singleDateTimeConversion(builder, cal, 'M', syms);
+	builder.append(':');
+	singleDateTimeConversion(builder, cal, 'S', syms);
+	builder.append(' ');
+	singleDateTimeConversion(builder, cal, 'p', syms);
+	break;
+      case 'D':
+	singleDateTimeConversion(builder, cal, 'm', syms);
+	builder.append('/');
+    	singleDateTimeConversion(builder, cal, 'd', syms);
+	builder.append('/');
+	singleDateTimeConversion(builder, cal, 'y', syms);
+	break;
+      case 'F':
+	singleDateTimeConversion(builder, cal, 'Y', syms);
+	builder.append('-');
+	singleDateTimeConversion(builder, cal, 'm', syms);
+	builder.append('-');
+	singleDateTimeConversion(builder, cal, 'd', syms);
+	break;
+      case 'c':
+	singleDateTimeConversion(builder, cal, 'a', syms);
+	builder.append(' ');
+	singleDateTimeConversion(builder, cal, 'b', syms);
+	builder.append(' ');
+	singleDateTimeConversion(builder, cal, 'd', syms);
+	builder.append(' ');
+	singleDateTimeConversion(builder, cal, 'T', syms);
+	builder.append(' ');
+	singleDateTimeConversion(builder, cal, 'Z', syms);
+	builder.append(' ');
+	singleDateTimeConversion(builder, cal, 'Y', syms);
+	break;
+      default:
+	throw new UnknownFormatConversionException(String.valueOf(conversion));
+      }
+
+    if (digits > 0)
+      {
+	int newLen = builder.length();
+	int delta = newLen - oldLen;
+	while (delta++ < digits)
+	  builder.insert(oldLen, '0');
+      }
+  }
+
+  /**
+   * Emit a date or time value.
+   *
+   * @param arg the date or time value.
+   * @param flags the formatting flags to use.
+   * @param width the width to use.
+   * @param precision the precision to use.
+   * @param conversion the conversion character.
+   * @param subConversion the sub conversion character.
+   * @throws IOException if the output stream throws an I/O error.
+   */
+  private void dateTimeConversion(Object arg, int flags, int width,
+				  int precision, char conversion,
+				  char subConversion)
+    throws IOException
+  {
+    noPrecision(precision);
+    checkFlags(flags,
+	       FormattableFlags.LEFT_JUSTIFY | FormattableFlags.UPPERCASE,
+	       conversion);
+
+    Calendar cal;
+    if (arg instanceof Calendar)
+      cal = (Calendar) arg;
+    else
+      {
+	Date date;
+	if (arg instanceof Date)
+	  date = (Date) arg;
+	else if (arg instanceof Long)
+	  date = new Date(((Long) arg).longValue());
+	else
+	  throw new IllegalFormatConversionException(conversion,
+						     arg.getClass());
+	if (fmtLocale == null)
+	  cal = Calendar.getInstance();
+	else
+	  cal = Calendar.getInstance(fmtLocale);
+	cal.setTime(date);
+      }
+
+    // We could try to be more efficient by computing this lazily.
+    DateFormatSymbols syms;
+    if (fmtLocale == null)
+      syms = new DateFormatSymbols();
+    else
+      syms = new DateFormatSymbols(fmtLocale);
+
+    StringBuilder result = new StringBuilder();
+    singleDateTimeConversion(result, cal, subConversion, syms);
+
+    genericFormat(result.toString(), flags, width, precision);
+  }
+
+  /**
+   * Advance the internal parsing index, and throw an exception
+   * on overrun.
+   *
+   * @throws IllegalArgumentException on overrun.
+   */
+  private void advance()
+  {
+    ++index;
+    if (index >= length)
+      {
+	// FIXME: what exception here?
+	throw new IllegalArgumentException();
+      }
+  }
+
+  /**
+   * Parse an integer appearing in the format string.  Will return -1
+   * if no integer was found.
+   *
+   * @return the parsed integer.
+   */
+  private int parseInt()
+  {
+    int start = index;
+    while (Character.isDigit(format.charAt(index)))
+      advance();
+    if (start == index)
+      return -1;
+    return Integer.decode(format.substring(start, index)).intValue();
+  }
+
+  /**
+   * Parse the argument index.  Returns -1 if there was no index, 0 if
+   * we should re-use the previous index, and a positive integer to
+   * indicate an absolute index.
+   *
+   * @return the parsed argument index.
+   */
+  private int parseArgumentIndex()
+  {
+    int result = -1;
+    int start = index;
+    if (format.charAt(index) == '<')
+      {
+	result = 0;
+	advance();
+      }
+    else if (Character.isDigit(format.charAt(index)))
+      {
+	result = parseInt();
+	if (format.charAt(index) == '$')
+	  advance();
+	else
+	  {
+	    // Reset.
+	    index = start;
+	    result = -1;
+	  }
+      }
+    return result;
+  }
+
+  /**
+   * Parse a set of flags and return a bit mask of values from
+   * FormattableFlags.  Will throw an exception if a flag is
+   * duplicated.
+   *
+   * @return the parsed flags.
+   */
+  private int parseFlags()
+  {
+    int value = 0;
+    int start = index;
+    while (true)
+      {
+	int x = FLAGS.indexOf(format.charAt(index));
+	if (x == -1)
+	  break;
+	int newValue = 1 << x;
+	if ((value & newValue) != 0)
+	  throw new DuplicateFormatFlagsException(format.substring(start,
+								   index + 1));
+	value |= newValue;
+	advance();
+      }
+    return value;
+  }
+
+  /**
+   * Parse the width part of a format string.  Returns -1 if no width
+   * was specified.
+   *
+   * @return the parsed width.
+   */
+  private int parseWidth()
+  {
+    return parseInt();
+  }
+
+  /**
+   * If the current character is '.', parses the precision part of a
+   * format string.  Returns -1 if no precision was specified.
+   *
+   * @return the parsed precision.
+   */
+  private int parsePrecision()
+  {
+    if (format.charAt(index) != '.')
+      return -1;
+    advance();
+    int precision = parseInt();
+    if (precision == -1)
+      // FIXME
+      throw new IllegalArgumentException();
+    return precision;
+  }
+
+  /**
+   * Outputs a formatted string based on the supplied specification,
+   * <code>fmt</code>, and its arguments using the specified locale.
+   * The locale of the formatter does not change as a result; the
+   * specified locale is just used for this particular formatting
+   * operation.  If the locale is <code>null</code>, then no
+   * localization is applied.
+   *
+   * @param loc the locale to use for this format.
+   * @param fmt the format specification.
+   * @param args the arguments to apply to the specification.
+   * @throws IllegalFormatException if there is a problem with
+   *                                the syntax of the format
+   *                                specification or a mismatch
+   *                                between it and the arguments.
+   * @throws FormatterClosedException if the formatter is closed.
+   */ 
+  public Formatter format(Locale loc, String fmt, Object[] args)
+  {
+    if (closed)
+      throw new FormatterClosedException();
+
+    // Note the arguments are indexed starting at 1.
+    int implicitArgumentIndex = 1;
+    int previousArgumentIndex = 0;
+
+    try
+      {
+	fmtLocale = loc;
+	format = fmt;
+	length = format.length();
+	for (index = 0; index < length; ++index)
+	  {
+	    char c = format.charAt(index);
+	    if (c != '%')
+	      {
+		out.append(c);
+		continue;
+	      }
+
+	    int start = index;
+	    advance();
+
+	    // We do the needed post-processing of this later, when we
+	    // determine whether an argument is actually needed by
+	    // this conversion.
+	    int argumentIndex = parseArgumentIndex();
+
+	    int flags = parseFlags();
+	    int width = parseWidth();
+	    int precision = parsePrecision();
+	    char origConversion = format.charAt(index);
+	    char conversion = origConversion;
+	    if (Character.isUpperCase(conversion))
+	      {
+		flags |= FormattableFlags.UPPERCASE;
+		conversion = Character.toLowerCase(conversion);
+	      }
+
+	    Object argument = null;
+	    if (conversion == '%' || conversion == 'n')
+	      {
+		if (argumentIndex != -1)
+		  {
+		    // FIXME: not sure about this.
+		    throw new UnknownFormatConversionException("FIXME");
+		  }
+	      }
+	    else
+	      {
+		if (argumentIndex == -1)
+		  argumentIndex = implicitArgumentIndex++;
+		else if (argumentIndex == 0)
+		  argumentIndex = previousArgumentIndex;
+		// Argument indices start at 1 but array indices at 0.
+		--argumentIndex;
+		if (argumentIndex < 0 || argumentIndex >= args.length)
+		  throw new MissingFormatArgumentException(format.substring(start, index));
+		argument = args[argumentIndex];
+	      }
+
+	    switch (conversion)
+	      {
+	      case 'b':
+		booleanFormat(argument, flags, width, precision,
+			      origConversion);
+		break;
+	      case 'h':
+		hashCodeFormat(argument, flags, width, precision,
+			       origConversion);
+		break;
+	      case 's':
+		stringFormat(argument, flags, width, precision,
+			     origConversion);
+		break;
+	      case 'c':
+		characterFormat(argument, flags, width, precision,
+				origConversion);
+		break;
+	      case 'd':
+		checkFlags(flags & FormattableFlags.UPPERCASE, 0, 'd');
+		decimalConversion(argument, flags, width, precision,
+				  origConversion);
+		break;
+	      case 'o':
+		checkFlags(flags & FormattableFlags.UPPERCASE, 0, 'o');
+		hexOrOctalConversion(argument, flags, width, precision, 8,
+				     origConversion);
+		break;
+	      case 'x':
+		hexOrOctalConversion(argument, flags, width, precision, 16,
+				     origConversion);
+	      case 'e':
+		// scientificNotationConversion();
+		break;
+	      case 'f':
+		// floatingDecimalConversion();
+		break;
+	      case 'g':
+		// smartFloatingConversion();
+		break;
+	      case 'a':
+		// hexFloatingConversion();
+		break;
+	      case 't':
+		advance();
+		char subConversion = format.charAt(index);
+		dateTimeConversion(argument, flags, width, precision,
+				   origConversion, subConversion);
+		break;
+	      case '%':
+		percentFormat(flags, width, precision);
+		break;
+	      case 'n':
+		newLineFormat(flags, width, precision);
+		break;
+	      default:
+		throw new UnknownFormatConversionException(String.valueOf(origConversion));
+	      }
+	  }
+      }
+    catch (IOException exc)
+      {
+	ioException = exc;
+      }
+    return this;
+  }
+
+  /**
+   * Outputs a formatted string based on the supplied specification,
+   * <code>fmt</code>, and its arguments using the formatter's locale.
+   *
+   * @param fmt the format specification.
+   * @param args the arguments to apply to the specification.
+   * @throws IllegalFormatException if there is a problem with
+   *                                the syntax of the format
+   *                                specification or a mismatch
+   *                                between it and the arguments.
+   * @throws FormatterClosedException if the formatter is closed.
+   */
+  public Formatter format(String format, Object[] args)
+  {
+    return format(locale, format, args);
+  }
+
+  /**
+   * Returns the last I/O exception thrown by the
+   * <code>append()</code> operation of the underlying
+   * output stream.
+   *
+   * @return the last I/O exception.
+   */
+  public IOException ioException()
+  {
+    return ioException;
+  }
+
+  /**
+   * Returns the locale used by this formatter.
+   *
+   * @return the formatter's locale.
+   * @throws FormatterClosedException if the formatter is closed.
+   */
+  public Locale locale()
+  {
+    if (closed)
+      throw new FormatterClosedException();
+    return locale;
+  }
+
+  /**
+   * Returns the output stream used by this formatter.
+   *
+   * @return the formatter's output stream.
+   * @throws FormatterClosedException if the formatter is closed.
+   */
+  public StringBuilder out()
+  {
+    if (closed)
+      throw new FormatterClosedException();
+    return out;
+  }
+
+  /**
+   * Returns the result of applying {@link Object#toString()}
+   * to the underlying output stream.  The results returned
+   * depend on the particular {@link Appendable} being used.
+   * For example, a {@link StringBuilder} will return the
+   * formatted output but an I/O stream will not.
+   *
+   * @throws FormatterClosedException if the formatter is closed.
+   */
+  public String toString()
+  {
+    if (closed)
+      throw new FormatterClosedException();
+    return out.toString();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormatterClosedException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormatterClosedException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormatterClosedException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/FormatterClosedException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,60 @@
+/* FormatterClosedException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when a method is called on a {@link Formatter} but
+ * it has already been closed.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class FormatterClosedException 
+  extends IllegalStateException
+{
+  private static final long serialVersionUID = 18111216L;
+
+  /**
+   * Constructs a new <code>FormatterClosedException</code>.
+   */
+  public FormatterClosedException()
+  {
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/GregorianCalendar.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/GregorianCalendar.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/GregorianCalendar.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/GregorianCalendar.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1355 @@
+/* java.util.GregorianCalendar
+   Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+
+/**
+ * <p>
+ * This class represents the Gregorian calendar, that is used in most
+ * countries all over the world.  It does also handle the Julian calendar
+ * for dates smaller than the date of the change to the Gregorian calendar.
+ * The Gregorian calendar differs from the Julian calendar by a different
+ * leap year rule (no leap year every 100 years, except if year is divisible
+ * by 400).
+ * </p>
+ * <p>
+ * This change date is different from country to country, and can be changed with
+ * <code>setGregorianChange</code>.  The first countries to adopt the Gregorian
+ * calendar did so on the 15th of October, 1582.  This date followed October
+ * the 4th, 1582 in the Julian calendar system.  The non-existant days that were
+ * omitted when the change took place are interpreted as Gregorian dates.
+ * </p>
+ * <p>
+ * Prior to the changeover date, New Year's Day occurred on the 25th of March.
+ * However, this class always takes New Year's Day as being the 1st of January.
+ * Client code should manually adapt the year value, if required, for dates
+ * between January the 1st and March the 24th in years prior to the changeover.
+ * </p>
+ * <p>
+ * Any date infinitely forwards or backwards in time can be represented by
+ * this class.  A <em>proleptic</em> calendar system is used, which allows
+ * future dates to be created via the existing rules.  This allows meaningful
+ * and consistent dates to be produced for all years.  However, dates are only
+ * historically accurate following March the 1st, 4AD when the Julian calendar
+ * system was adopted.  Prior to this, leap year rules were applied erraticly.
+ * </p>
+ * <p>
+ * There are two eras available for the Gregorian calendar, namely BC and AD.
+ * </p>
+ * <p>
+ * Weeks are defined as a period of seven days, beginning on the first day
+ * of the week, as returned by <code>getFirstDayOfWeek()</code>, and ending
+ * on the day prior to this.
+ * </p>
+ * <p>
+ * The weeks of the year are numbered from 1 to a possible 53.  The first week
+ * of the year is defined as the first week that contains at least the minimum
+ * number of days of the first week in the new year (retrieved via
+ * <code>getMinimalDaysInFirstWeek()</code>).  All weeks after this are numbered
+ * from 2 onwards.
+ * </p>
+ * <p>
+ * For example, take the year 2004.  It began on a Thursday.  The first week
+ * of 2004 depends both on where a week begins and how long it must minimally
+ * last.  Let's say that the week begins on a Monday and must have a minimum
+ * of 5 days.  In this case, the first week begins on Monday, the 5th of January.
+ * The first 4 days (Thursday to Sunday) are not eligible, as they are too few
+ * to make up the minimum number of days of the first week which must be in
+ * the new year.  If the minimum was lowered to 4 days, then the first week
+ * would instead begin on Monday, the 29th of December, 2003.  This first week
+ * has 4 of its days in the new year, and is now eligible.
+ * </p>
+ * <p>
+ * The weeks of the month are numbered from 0 to a possible 6.  The first week
+ * of the month (numbered 1) is a set of days, prior to the first day of the week,
+ * which number at least the minimum number of days in a week.  Unlike the first
+ * week of the year, the first week of the month only uses days from that particular
+ * month.  As a consequence, it may have a variable number of days (from the minimum
+ * number required up to a full week of 7) and it need not start on the first day of
+ * the week.  It must, however, be following by the first day of the week, as this
+ * marks the beginning of week 2.  Any days of the month which occur prior to the
+ * first week (because the first day of the week occurs before the minimum number
+ * of days is met) are seen as week 0.
+ * </p>
+ * <p>
+ * Again, we will take the example of the year 2004 to demonstrate this.  September
+ * 2004 begins on a Wednesday.  Taking our first day of the week as Monday, and the
+ * minimum length of the first week as 6, we find that week 1 runs from Monday,
+ * the 6th of September to Sunday the 12th.  Prior to the 6th, there are only
+ * 5 days (Wednesday through to Sunday).  This is too small a number to meet the
+ * minimum, so these are classed as being days in week 0.  Week 2 begins on the
+ * 13th, and so on.  This changes if we reduce the minimum to 5.  In this case,
+ * week 1 is a truncated week from Wednesday the 1st to Sunday the 5th, and week
+ * 0 doesn't exist.  The first seven day week is week 2, starting on the 6th.
+ * </p>
+ * <p>
+ * On using the <code>clear()</code> method, the Gregorian calendar returns
+ * to its default value of the 1st of January, 1970 AD 00:00:00 (the epoch).
+ * The day of the week is set to the correct day for that particular time.
+ * The day is also the first of the month, and the date is in week 0.
+ * </p>
+ *
+ * @see Calendar
+ * @see TimeZone
+ * @see Calendar#getFirstDayOfWeek()
+ * @see Calendar#getMinimalDaysInFirstWeek()
+ */
+public class GregorianCalendar extends Calendar
+{
+  /**
+   * Constant representing the era BC (Before Christ).
+   */
+  public static final int BC = 0;
+
+  /**
+   * Constant representing the era AD (Anno Domini).
+   */
+  public static final int AD = 1;
+
+  /**
+   * The point at which the Gregorian calendar rules were used.
+   * This may be changed by using setGregorianChange;
+   * The default is midnight (UTC) on October 5, 1582 (Julian),
+   * or October 15, 1582 (Gregorian).
+   *
+   * @serial the changeover point from the Julian calendar
+   *         system to the Gregorian.
+   */
+  private long gregorianCutover = (new Date((24 * 60 * 60 * 1000L) * (((1582 * (365 * 4
+                                            + 1)) / 4
+                                            + (java.util.Calendar.OCTOBER * (31
+                                            + 30 + 31 + 30 + 31) - 9) / 5 + 5)
+                                            - ((1970 * (365 * 4 + 1)) / 4 + 1
+                                            - 13)))).getTime();
+
+  /**
+   * For compatability with Sun's JDK.
+   */
+  static final long serialVersionUID = -8125100834729963327L;
+
+  /**
+   * Days in the epoch. Relative Jan 1, year '0' which is not a leap year.
+   * (although there is no year zero, this does not matter.)
+   * This is consistent with the formula:
+   * = (year-1)*365L + ((year-1) >> 2)
+   *
+   * Plus the gregorian correction:
+   *  Math.floor((year-1) / 400.) - Math.floor((year-1) / 100.);
+   * For a correct julian date, the correction is -2 instead.
+   *
+   * The gregorian cutover in 1582 was 10 days, so by calculating the
+   * correction from year zero, we have 15 non-leap days (even centuries)
+   * minus 3 leap days (year 400,800,1200) = 12. Subtracting two corrects
+   * this to the correct number 10.
+   */
+  private static final int EPOCH_DAYS = 719162;
+
+  /**
+   * Constructs a new GregorianCalender representing the current
+   * time, using the default time zone and the default locale.
+   */
+  public GregorianCalendar()
+  {
+    this(TimeZone.getDefault(), Locale.getDefault());
+  }
+
+  /**
+   * Constructs a new GregorianCalender representing the current
+   * time, using the specified time zone and the default locale.
+   *
+   * @param zone a time zone.
+   */
+  public GregorianCalendar(TimeZone zone)
+  {
+    this(zone, Locale.getDefault());
+  }
+
+  /**
+   * Constructs a new GregorianCalender representing the current
+   * time, using the default time zone and the specified locale.
+   *
+   * @param locale a locale.
+   */
+  public GregorianCalendar(Locale locale)
+  {
+    this(TimeZone.getDefault(), locale);
+  }
+
+  /**
+   * Constructs a new GregorianCalender representing the current
+   * time with the given time zone and the given locale.
+   *
+   * @param zone a time zone.
+   * @param locale a locale.
+   */
+  public GregorianCalendar(TimeZone zone, Locale locale)
+  {
+    this(zone, locale, false);
+    setTimeInMillis(System.currentTimeMillis());
+    complete();
+  }
+
+  /**
+   * Common constructor that all constructors should call.
+   * @param zone a time zone.
+   * @param locale a locale.
+   * @param unused unused parameter to make the signature differ from
+   * the public constructor (TimeZone, Locale).
+   */
+  private GregorianCalendar(TimeZone zone, Locale locale, boolean unused)
+  {
+    super(zone, locale);
+  }
+
+  /**
+   * Constructs a new GregorianCalendar representing midnight on the
+   * given date with the default time zone and locale.
+   *
+   * @param year corresponds to the YEAR time field.
+   * @param month corresponds to the MONTH time field.
+   * @param day corresponds to the DAY time field.
+   */
+  public GregorianCalendar(int year, int month, int day)
+  {
+    this(TimeZone.getDefault(), Locale.getDefault(), false);
+    set(year, month, day);
+  }
+
+  /**
+   * Constructs a new GregorianCalendar representing midnight on the
+   * given date with the default time zone and locale.
+   *
+   * @param year corresponds to the YEAR time field.
+   * @param month corresponds to the MONTH time field.
+   * @param day corresponds to the DAY time field.
+   * @param hour corresponds to the HOUR_OF_DAY time field.
+   * @param minute corresponds to the MINUTE time field.
+   */
+  public GregorianCalendar(int year, int month, int day, int hour, int minute)
+  {
+    this(TimeZone.getDefault(), Locale.getDefault(), false);
+    set(year, month, day, hour, minute);
+  }
+
+  /**
+   * Constructs a new GregorianCalendar representing midnight on the
+   * given date with the default time zone and locale.
+   *
+   * @param year corresponds to the YEAR time field.
+   * @param month corresponds to the MONTH time field.
+   * @param day corresponds to the DAY time field.
+   * @param hour corresponds to the HOUR_OF_DAY time field.
+   * @param minute corresponds to the MINUTE time field.
+   * @param second corresponds to the SECOND time field.
+   */
+  public GregorianCalendar(int year, int month, int day, int hour, int minute,
+                           int second)
+  {
+    this(TimeZone.getDefault(), Locale.getDefault(), false);
+    set(year, month, day, hour, minute, second);
+  }
+
+  /**
+   * Sets the date of the switch from Julian dates to Gregorian dates.
+   * You can use <code>new Date(Long.MAX_VALUE)</code> to use a pure
+   * Julian calendar, or <code>Long.MIN_VALUE</code> for a pure Gregorian
+   * calendar.
+   *
+   * @param date the date of the change.
+   */
+  public void setGregorianChange(Date date)
+  {
+    gregorianCutover = date.getTime();
+  }
+
+  /**
+   * Gets the date of the switch from Julian dates to Gregorian dates.
+   *
+   * @return the date of the change.
+   */
+  public final Date getGregorianChange()
+  {
+    return new Date(gregorianCutover);
+  }
+
+  /**
+   * <p>
+   * Determines if the given year is a leap year.  The result is
+   * undefined if the Gregorian change took place in 1800, so that
+   * the end of February is skipped, and that year is specified.
+   * (well...).
+   * </p>
+   * <p>
+   * To specify a year in the BC era, use a negative value calculated
+   * as 1 - y, where y is the required year in BC.  So, 1 BC is 0,
+   * 2 BC is -1, 3 BC is -2, etc.
+   * </p>
+   *
+   * @param year a year (use a negative value for BC).
+   * @return true, if the given year is a leap year, false otherwise.
+   */
+  public boolean isLeapYear(int year)
+  {
+    // Only years divisible by 4 can be leap years
+    if ((year & 3) != 0)
+      return false;
+
+    // Is the leap-day a Julian date? Then it's a leap year
+    if (! isGregorian(year, 31 + 29 - 1))
+      return true;
+
+    // Apply gregorian rules otherwise
+    return ((year % 100) != 0 || (year % 400) == 0);
+  }
+
+  /**
+   * Retrieves the day of the week corresponding to the specified
+   * day of the specified year.
+   *
+   * @param year the year in which the dayOfYear occurs.
+   * @param dayOfYear the day of the year (an integer between 0 and
+   *        and 366)
+   */
+  private int getWeekDay(int year, int dayOfYear)
+  {
+    boolean greg = isGregorian(year, dayOfYear);
+    int day = (int) getLinearDay(year, dayOfYear, greg);
+
+    // The epoch was a thursday.
+    int weekday = (day + THURSDAY) % 7;
+    if (weekday <= 0)
+      weekday += 7;
+    return weekday;
+  }
+
+  /**
+   * Returns the day of the week for the first day of a given month (0..11)
+   */
+  private int getFirstDayOfMonth(int year, int month)
+  {
+    int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+    if (month > 11)
+      {
+	year += (month / 12);
+	month = month % 12;
+      }
+
+    if (month < 0)
+      {
+	year += (int) month / 12;
+	month = month % 12;
+	if (month < 0)
+	  {
+	    month += 12;
+	    year--;
+	  }
+      }
+
+    int dayOfYear = dayCount[month] + 1;
+    if (month > 1)
+      if (isLeapYear(year))
+	dayOfYear++;
+
+    boolean greg = isGregorian(year, dayOfYear);
+    int day = (int) getLinearDay(year, dayOfYear, greg);
+
+    // The epoch was a thursday.
+    int weekday = (day + THURSDAY) % 7;
+    if (weekday <= 0)
+      weekday += 7;
+    return weekday;
+  }
+
+  /**
+   * Takes a year, and a (zero based) day of year and determines
+   * if it is gregorian or not.
+   */
+  private boolean isGregorian(int year, int dayOfYear)
+  {
+    int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear
+                      - EPOCH_DAYS; // gregorian days from 1 to epoch.
+    int gregFactor = (int) Math.floor((double) (year - 1) / 400.)
+                     - (int) Math.floor((double) (year - 1) / 100.);
+
+    return ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover);
+  }
+
+  /**
+   * Check set fields for validity, without leniency.
+   *
+   * @throws IllegalArgumentException if a field is invalid
+   */
+  private void nonLeniencyCheck() throws IllegalArgumentException
+  {
+    int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+    int year = fields[YEAR];
+    int month = fields[MONTH];
+    int leap = isLeapYear(year) ? 1 : 0;
+
+    if (isSet[ERA] && fields[ERA] != AD && fields[ERA] != BC)
+      throw new IllegalArgumentException("Illegal ERA.");
+    if (isSet[YEAR] && fields[YEAR] < 1)
+      throw new IllegalArgumentException("Illegal YEAR.");
+    if (isSet[MONTH] && (month < 0 || month > 11))
+      throw new IllegalArgumentException("Illegal MONTH.");
+    if (isSet[WEEK_OF_YEAR])
+      {
+	int daysInYear = 365 + leap;
+	daysInYear += (getFirstDayOfMonth(year, 0) - 1); // pad first week
+	int last = getFirstDayOfMonth(year, 11) + 4;
+	if (last > 7)
+	  last -= 7;
+	daysInYear += 7 - last;
+	int weeks = daysInYear / 7;
+	if (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > weeks)
+	  throw new IllegalArgumentException("Illegal WEEK_OF_YEAR.");
+      }
+
+    if (isSet[WEEK_OF_MONTH])
+      {
+	int weeks = (month == 1 && leap == 0) ? 5 : 6;
+	if (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > weeks)
+	  throw new IllegalArgumentException("Illegal WEEK_OF_MONTH.");
+      }
+
+    if (isSet[DAY_OF_MONTH])
+      if (fields[DAY_OF_MONTH] < 1
+          || fields[DAY_OF_MONTH] > month_days[month]
+          + ((month == 1) ? leap : 0))
+	throw new IllegalArgumentException("Illegal DAY_OF_MONTH.");
+
+    if (isSet[DAY_OF_YEAR]
+        && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > 365 + leap))
+      throw new IllegalArgumentException("Illegal DAY_OF_YEAR.");
+
+    if (isSet[DAY_OF_WEEK]
+        && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7))
+      throw new IllegalArgumentException("Illegal DAY_OF_WEEK.");
+
+    if (isSet[DAY_OF_WEEK_IN_MONTH])
+      {
+	int weeks = (month == 1 && leap == 0) ? 4 : 5;
+	if (fields[DAY_OF_WEEK_IN_MONTH] < -weeks
+	    || fields[DAY_OF_WEEK_IN_MONTH] > weeks)
+	  throw new IllegalArgumentException("Illegal DAY_OF_WEEK_IN_MONTH.");
+      }
+
+    if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM)
+      throw new IllegalArgumentException("Illegal AM_PM.");
+    if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11))
+      throw new IllegalArgumentException("Illegal HOUR.");
+    if (isSet[HOUR_OF_DAY]
+        && (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23))
+      throw new IllegalArgumentException("Illegal HOUR_OF_DAY.");
+    if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59))
+      throw new IllegalArgumentException("Illegal MINUTE.");
+    if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59))
+      throw new IllegalArgumentException("Illegal SECOND.");
+    if (isSet[MILLISECOND]
+        && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999))
+      throw new IllegalArgumentException("Illegal MILLISECOND.");
+    if (isSet[ZONE_OFFSET]
+        && (fields[ZONE_OFFSET] < -12 * 60 * 60 * 1000L
+        || fields[ZONE_OFFSET] > 12 * 60 * 60 * 1000L))
+      throw new IllegalArgumentException("Illegal ZONE_OFFSET.");
+    if (isSet[DST_OFFSET]
+        && (fields[DST_OFFSET] < -12 * 60 * 60 * 1000L
+        || fields[DST_OFFSET] > 12 * 60 * 60 * 1000L))
+      throw new IllegalArgumentException("Illegal DST_OFFSET.");
+  }
+
+  /**
+   * Converts the time field values (<code>fields</code>) to
+   * milliseconds since the epoch UTC (<code>time</code>).
+   *
+   * @throws IllegalArgumentException if any calendar fields
+   *         are invalid.
+   */
+  protected synchronized void computeTime()
+  {
+    int millisInDay = 0;
+    int era = fields[ERA];
+    int year = fields[YEAR];
+    int month = fields[MONTH];
+    int day = fields[DAY_OF_MONTH];
+
+    int minute = fields[MINUTE];
+    int second = fields[SECOND];
+    int millis = fields[MILLISECOND];
+    int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+    int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+    int hour = 0;
+
+    if (! isLenient())
+      nonLeniencyCheck();
+
+    if (! isSet[MONTH] && (! isSet[DAY_OF_WEEK] || isSet[WEEK_OF_YEAR]))
+      {
+	// 5: YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
+	if (isSet[WEEK_OF_YEAR])
+	  {
+	    int first = getFirstDayOfMonth(year, 0);
+	    int offs = 1;
+	    int daysInFirstWeek = getFirstDayOfWeek() - first;
+	    if (daysInFirstWeek <= 0)
+	      daysInFirstWeek += 7;
+
+	    if (daysInFirstWeek < getMinimalDaysInFirstWeek())
+	      offs += daysInFirstWeek;
+	    else
+	      offs -= 7 - daysInFirstWeek;
+	    month = 0;
+	    day = offs + 7 * (fields[WEEK_OF_YEAR] - 1);
+	    offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek();
+
+	    if (offs < 0)
+	      offs += 7;
+	    day += offs;
+	  }
+	else
+	  {
+	    // 4:  YEAR + DAY_OF_YEAR
+	    month = 0;
+	    day = fields[DAY_OF_YEAR];
+	  }
+      }
+    else
+      {
+	if (isSet[DAY_OF_WEEK])
+	  {
+	    int first = getFirstDayOfMonth(year, month);
+
+	    // 3: YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
+	    if (isSet[DAY_OF_WEEK_IN_MONTH])
+	      {
+		if (fields[DAY_OF_WEEK_IN_MONTH] < 0)
+		  {
+		    month++;
+		    first = getFirstDayOfMonth(year, month);
+		    day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH]);
+		  }
+		else
+		  day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH] - 1);
+
+		int offs = fields[DAY_OF_WEEK] - first;
+		if (offs < 0)
+		  offs += 7;
+		day += offs;
+	      }
+	    else
+	      { // 2: YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
+		int offs = 1;
+		int daysInFirstWeek = getFirstDayOfWeek() - first;
+		if (daysInFirstWeek <= 0)
+		  daysInFirstWeek += 7;
+
+		if (daysInFirstWeek < getMinimalDaysInFirstWeek())
+		  offs += daysInFirstWeek;
+		else
+		  offs -= 7 - daysInFirstWeek;
+
+		day = offs + 7 * (fields[WEEK_OF_MONTH] - 1);
+		offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek();
+		if (offs < 0)
+		  offs += 7;
+		day += offs;
+	      }
+	  }
+
+	// 1:  YEAR + MONTH + DAY_OF_MONTH
+      }
+    if (era == BC && year > 0)
+      year = 1 - year;
+
+    // rest of code assumes day/month/year set
+    // should negative BC years be AD?
+    // get the hour (but no check for validity)
+    if (isSet[HOUR])
+      {
+	hour = fields[HOUR];
+	if (fields[AM_PM] == PM)
+	  hour += 12;
+      }
+    else
+      hour = fields[HOUR_OF_DAY];
+
+    // Read the era,year,month,day fields and convert as appropriate.
+    // Calculate number of milliseconds into the day
+    // This takes care of both h, m, s, ms over/underflows.
+    long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L + millis;
+    day += allMillis / (24 * 60 * 60 * 1000L);
+    millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L));
+
+    if (month < 0)
+      {
+	year += (int) month / 12;
+	month = month % 12;
+	if (month < 0)
+	  {
+	    month += 12;
+	    year--;
+	  }
+      }
+    if (month > 11)
+      {
+	year += (month / 12);
+	month = month % 12;
+      }
+
+    month_days[1] = isLeapYear(year) ? 29 : 28;
+
+    while (day <= 0)
+      {
+	if (month == 0)
+	  {
+	    year--;
+	    month_days[1] = isLeapYear(year) ? 29 : 28;
+	  }
+	month = (month + 11) % 12;
+	day += month_days[month];
+      }
+    while (day > month_days[month])
+      {
+	day -= (month_days[month]);
+	month = (month + 1) % 12;
+	if (month == 0)
+	  {
+	    year++;
+	    month_days[1] = isLeapYear(year) ? 29 : 28;
+	  }
+      }
+
+    // ok, by here we have valid day,month,year,era and millisinday
+    int dayOfYear = dayCount[month] + day - 1; // (day starts on 1)
+    if (isLeapYear(year) && month > 1)
+      dayOfYear++;
+
+    int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear
+                      - EPOCH_DAYS; // gregorian days from 1 to epoch.
+    int gregFactor = (int) Math.floor((double) (year - 1) / 400.)
+                     - (int) Math.floor((double) (year - 1) / 100.);
+
+    if ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover)
+      relativeDay += gregFactor;
+    else
+      relativeDay -= 2;
+
+    time = relativeDay * (24 * 60 * 60 * 1000L) + millisInDay;
+
+    // the epoch was a Thursday.
+    int weekday = (int) (relativeDay + THURSDAY) % 7;
+    if (weekday <= 0)
+      weekday += 7;
+    fields[DAY_OF_WEEK] = weekday;
+
+    // Time zone corrections.
+    TimeZone zone = getTimeZone();
+    int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET]
+                                       : zone.getRawOffset();
+
+    int dstOffset = isSet[DST_OFFSET] ? fields[DST_OFFSET]
+                                      : (zone.getOffset((year < 0) ? BC : AD,
+                                                        (year < 0) ? 1 - year
+                                                                   : year,
+                                                        month, day, weekday,
+                                                        millisInDay)
+                                      - zone.getRawOffset());
+
+    time -= rawOffset + dstOffset;
+
+    isTimeSet = true;
+  }
+
+  /**
+   * Get the linear day in days since the epoch, using the
+   * Julian or Gregorian calendar as specified.  If you specify a
+   * nonpositive year it is interpreted as BC as following: 0 is 1
+   * BC, -1 is 2 BC and so on.
+   *
+   * @param year the year of the date.
+   * @param dayOfYear the day of year of the date; 1 based.
+   * @param gregorian <code>true</code>, if we should use the Gregorian rules.
+   * @return the days since the epoch, may be negative.
+   */
+  private long getLinearDay(int year, int dayOfYear, boolean gregorian)
+  {
+    // The 13 is the number of days, that were omitted in the Gregorian
+    // Calender until the epoch.
+    // We shift right by 2 instead of dividing by 4, to get correct
+    // results for negative years (and this is even more efficient).
+    long julianDay = (year - 1) * 365L + ((year - 1) >> 2) + (dayOfYear - 1)
+                     - EPOCH_DAYS; // gregorian days from 1 to epoch.
+
+    if (gregorian)
+      {
+	// subtract the days that are missing in gregorian calendar
+	// with respect to julian calendar.
+	//
+	// Okay, here we rely on the fact that the gregorian
+	// calendar was introduced in the AD era.  This doesn't work
+	// with negative years.
+	//
+	// The additional leap year factor accounts for the fact that
+	// a leap day is not seen on Jan 1 of the leap year.
+	int gregOffset = (int) Math.floor((double) (year - 1) / 400.)
+	                 - (int) Math.floor((double) (year - 1) / 100.);
+
+	return julianDay + gregOffset;
+      }
+    else
+      julianDay -= 2;
+    return julianDay;
+  }
+
+  /**
+   * Converts the given linear day into era, year, month,
+   * day_of_year, day_of_month, day_of_week, and writes the result
+   * into the fields array.
+   *
+   * @param day the linear day.
+   * @param gregorian true, if we should use Gregorian rules.
+   */
+  private void calculateDay(int[] fields, long day, boolean gregorian)
+  {
+    // the epoch was a Thursday.
+    int weekday = (int) (day + THURSDAY) % 7;
+    if (weekday <= 0)
+      weekday += 7;
+    fields[DAY_OF_WEEK] = weekday;
+
+    // get a first approximation of the year.  This may be one 
+    // year too big.
+    int year = 1970
+               + (int) (gregorian
+                        ? ((day - 100L) * 400L) / (365L * 400L + 100L - 4L
+                        + 1L) : ((day - 100L) * 4L) / (365L * 4L + 1L));
+    if (day >= 0)
+      year++;
+
+    long firstDayOfYear = getLinearDay(year, 1, gregorian);
+
+    // Now look in which year day really lies.
+    if (day < firstDayOfYear)
+      {
+	year--;
+	firstDayOfYear = getLinearDay(year, 1, gregorian);
+      }
+
+    day -= firstDayOfYear - 1; // day of year,  one based.
+
+    fields[DAY_OF_YEAR] = (int) day;
+    if (year <= 0)
+      {
+	fields[ERA] = BC;
+	fields[YEAR] = 1 - year;
+      }
+    else
+      {
+	fields[ERA] = AD;
+	fields[YEAR] = year;
+      }
+
+    int leapday = isLeapYear(year) ? 1 : 0;
+    if (day <= 31 + 28 + leapday)
+      {
+	fields[MONTH] = (int) day / 32; // 31->JANUARY, 32->FEBRUARY
+	fields[DAY_OF_MONTH] = (int) day - 31 * fields[MONTH];
+      }
+    else
+      {
+	// A few more magic formulas
+	int scaledDay = ((int) day - leapday) * 5 + 8;
+	fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31);
+	fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1;
+      }
+  }
+
+  /**
+   * Converts the milliseconds since the epoch UTC
+   * (<code>time</code>) to time fields
+   * (<code>fields</code>).
+   */
+  protected synchronized void computeFields()
+  {
+    boolean gregorian = (time >= gregorianCutover);
+
+    TimeZone zone = getTimeZone();
+    fields[ZONE_OFFSET] = zone.getRawOffset();
+    long localTime = time + fields[ZONE_OFFSET];
+
+    long day = localTime / (24 * 60 * 60 * 1000L);
+    int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L));
+
+    if (millisInDay < 0)
+      {
+	millisInDay += (24 * 60 * 60 * 1000);
+	day--;
+      }
+
+    calculateDay(fields, day, gregorian);
+    fields[DST_OFFSET] = zone.getOffset(fields[ERA], fields[YEAR],
+                                        fields[MONTH], fields[DAY_OF_MONTH],
+                                        fields[DAY_OF_WEEK], millisInDay)
+                         - fields[ZONE_OFFSET];
+
+    millisInDay += fields[DST_OFFSET];
+    if (millisInDay >= 24 * 60 * 60 * 1000)
+      {
+	millisInDay -= 24 * 60 * 60 * 1000;
+	calculateDay(fields, ++day, gregorian);
+      }
+
+    fields[DAY_OF_WEEK_IN_MONTH] = (fields[DAY_OF_MONTH] + 6) / 7;
+
+    // which day of the week are we (0..6), relative to getFirstDayOfWeek
+    int relativeWeekday = (7 + fields[DAY_OF_WEEK] - getFirstDayOfWeek()) % 7;
+
+    fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH] - relativeWeekday + 12) / 7;
+
+    int weekOfYear = (fields[DAY_OF_YEAR] - relativeWeekday + 6) / 7;
+
+    // Do the Correction: getMinimalDaysInFirstWeek() is always in the 
+    // first week.
+    int minDays = getMinimalDaysInFirstWeek();
+    int firstWeekday = (7 + getWeekDay(fields[YEAR], minDays)
+                       - getFirstDayOfWeek()) % 7;
+    if (minDays - firstWeekday < 1)
+      weekOfYear++;
+    fields[WEEK_OF_YEAR] = weekOfYear;
+
+    int hourOfDay = millisInDay / (60 * 60 * 1000);
+    fields[AM_PM] = (hourOfDay < 12) ? AM : PM;
+    int hour = hourOfDay % 12;
+    fields[HOUR] = hour;
+    fields[HOUR_OF_DAY] = hourOfDay;
+    millisInDay %= (60 * 60 * 1000);
+    fields[MINUTE] = millisInDay / (60 * 1000);
+    millisInDay %= (60 * 1000);
+    fields[SECOND] = millisInDay / (1000);
+    fields[MILLISECOND] = millisInDay % 1000;
+
+    areFieldsSet = isSet[ERA] = isSet[YEAR] = isSet[MONTH] = isSet[WEEK_OF_YEAR] = isSet[WEEK_OF_MONTH] = isSet[DAY_OF_MONTH] = isSet[DAY_OF_YEAR] = isSet[DAY_OF_WEEK] = isSet[DAY_OF_WEEK_IN_MONTH] = isSet[AM_PM] = isSet[HOUR] = isSet[HOUR_OF_DAY] = isSet[MINUTE] = isSet[SECOND] = isSet[MILLISECOND] = isSet[ZONE_OFFSET] = isSet[DST_OFFSET] = true;
+  }
+  
+  /**
+   * Return a hash code for this object, following the general contract
+   * specified by {@link Object#hashCode()}.
+   * @return the hash code
+   */
+  public int hashCode()
+  {
+    int val = (int) ((gregorianCutover >>> 32) ^ (gregorianCutover & 0xffffffff));
+    return super.hashCode() ^ val;
+  }
+
+  /**
+   * Compares the given calendar with this.  An object, o, is
+   * equivalent to this if it is also a <code>GregorianCalendar</code>
+   * with the same time since the epoch under the same conditions
+   * (same change date and same time zone).
+   *
+   * @param o the object to that we should compare.
+   * @return true, if the given object is a calendar, that represents
+   * the same time (but doesn't necessarily have the same fields).
+   * @throws IllegalArgumentException if one of the fields
+   *         <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+   *         specified, if an unknown field is specified or if one
+   *         of the calendar fields receives an illegal value when
+   *         leniancy is not enabled.
+   */
+  public boolean equals(Object o)
+  {
+    if (! (o instanceof GregorianCalendar))
+      return false;
+
+    GregorianCalendar cal = (GregorianCalendar) o;
+    return (cal.gregorianCutover == gregorianCutover
+            && super.equals(o));
+  }
+
+  /**
+   * Adds the specified amount of time to the given time field.  The
+   * amount may be negative to subtract the time.  If the field overflows
+   * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
+   * @param field one of the time field constants.
+   * @param amount the amount of time to add.
+   * @exception IllegalArgumentException if <code>field</code> is
+   *   <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or invalid; or
+   *   if <code>amount</code> contains an out-of-range value and the calendar
+   *   is not in lenient mode.
+   */
+  public void add(int field, int amount)
+  {
+    switch (field)
+      {
+      case YEAR:
+	complete();
+	fields[YEAR] += amount;
+	isTimeSet = false;
+	break;
+      case MONTH:
+	complete();
+	int months = fields[MONTH] + amount;
+	fields[YEAR] += months / 12;
+	fields[MONTH] = months % 12;
+	if (fields[MONTH] < 0)
+	  {
+	    fields[MONTH] += 12;
+	    fields[YEAR]--;
+	  }
+	int maxDay = getActualMaximum(DAY_OF_MONTH);
+	if (fields[DAY_OF_MONTH] > maxDay)
+	  fields[DAY_OF_MONTH] = maxDay;
+	set(YEAR, fields[YEAR]);
+	set(MONTH, fields[MONTH]);
+	break;
+      case DAY_OF_MONTH:
+      case DAY_OF_YEAR:
+      case DAY_OF_WEEK:
+	if (! isTimeSet)
+	  computeTime();
+	time += amount * (24 * 60 * 60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case WEEK_OF_YEAR:
+      case WEEK_OF_MONTH:
+      case DAY_OF_WEEK_IN_MONTH:
+	if (! isTimeSet)
+	  computeTime();
+	time += amount * (7 * 24 * 60 * 60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case AM_PM:
+	if (! isTimeSet)
+	  computeTime();
+	time += amount * (12 * 60 * 60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case HOUR:
+      case HOUR_OF_DAY:
+	if (! isTimeSet)
+	  computeTime();
+	time += amount * (60 * 60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case MINUTE:
+	if (! isTimeSet)
+	  computeTime();
+	time += amount * (60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case SECOND:
+	if (! isTimeSet)
+	  computeTime();
+	time += amount * (1000L);
+	areFieldsSet = false;
+	break;
+      case MILLISECOND:
+	if (! isTimeSet)
+	  computeTime();
+	time += amount;
+	areFieldsSet = false;
+	break;
+      case ZONE_OFFSET:
+      case DST_OFFSET:default:
+	throw new IllegalArgumentException("Invalid or unknown field");
+      }
+  }
+
+  /**
+   * Rolls the specified time field up or down.  This means add one
+   * to the specified field, but don't change the other fields.  If
+   * the maximum for this field is reached, start over with the
+   * minimum value.
+   *
+   * <strong>Note:</strong> There may be situation, where the other
+   * fields must be changed, e.g rolling the month on May, 31.
+   * The date June, 31 is automatically converted to July, 1.
+   * This requires lenient settings.
+   *
+   * @param field the time field. One of the time field constants.
+   * @param up the direction, true for up, false for down.
+   * @throws IllegalArgumentException if one of the fields
+   *         <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+   *         specified, if an unknown field is specified or if one
+   *         of the calendar fields receives an illegal value when
+   *         leniancy is not enabled.
+   */
+  public void roll(int field, boolean up)
+  {
+    roll(field, up ? 1 : -1);
+  }
+
+  /**
+   * Checks that the fields are still within their legal bounds,
+   * following use of the <code>roll()</code> method.
+   *
+   * @param field the field to check.
+   * @param delta multipler for alterations to the <code>time</code>.
+   * @see #roll(int, boolean)
+   * @see #roll(int, int)
+   */
+  private void cleanUpAfterRoll(int field, int delta)
+  {
+    switch (field)
+      {
+      case ERA:
+      case YEAR:
+      case MONTH:
+	// check that day of month is still in correct range
+	if (fields[DAY_OF_MONTH] > getActualMaximum(DAY_OF_MONTH))
+	  fields[DAY_OF_MONTH] = getActualMaximum(DAY_OF_MONTH);
+	isTimeSet = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	break;
+      case DAY_OF_MONTH:
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	time += delta * (24 * 60 * 60 * 1000L);
+	break;
+      case WEEK_OF_MONTH:
+	isSet[DAY_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	time += delta * (7 * 24 * 60 * 60 * 1000L);
+	break;
+      case DAY_OF_WEEK_IN_MONTH:
+	isSet[DAY_OF_MONTH] = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	time += delta * (7 * 24 * 60 * 60 * 1000L);
+	break;
+      case DAY_OF_YEAR:
+	isSet[MONTH] = false;
+	isSet[DAY_OF_MONTH] = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_WEEK] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	time += delta * (24 * 60 * 60 * 1000L);
+	break;
+      case WEEK_OF_YEAR:
+	isSet[MONTH] = false;
+	isSet[DAY_OF_MONTH] = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	time += delta * (7 * 24 * 60 * 60 * 1000L);
+	break;
+      case AM_PM:
+	isSet[HOUR_OF_DAY] = false;
+	time += delta * (12 * 60 * 60 * 1000L);
+	break;
+      case HOUR:
+	isSet[HOUR_OF_DAY] = false;
+	time += delta * (60 * 60 * 1000L);
+	break;
+      case HOUR_OF_DAY:
+	isSet[HOUR] = false;
+	isSet[AM_PM] = false;
+	time += delta * (60 * 60 * 1000L);
+	break;
+      case MINUTE:
+	time += delta * (60 * 1000L);
+	break;
+      case SECOND:
+	time += delta * (1000L);
+	break;
+      case MILLISECOND:
+	time += delta;
+	break;
+      }
+  }
+
+  /**
+   * Rolls the specified time field by the given amount.  This means
+   * add amount to the specified field, but don't change the other
+   * fields.  If the maximum for this field is reached, start over
+   * with the minimum value and vice versa for negative amounts.
+   *
+   * <strong>Note:</strong> There may be situation, where the other
+   * fields must be changed, e.g rolling the month on May, 31.
+   * The date June, 31 is automatically corrected to June, 30.
+   *
+   * @param field the time field. One of the time field constants.
+   * @param amount the amount by which we should roll.
+   * @throws IllegalArgumentException if one of the fields
+   *         <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+   *         specified, if an unknown field is specified or if one
+   *         of the calendar fields receives an illegal value when
+   *         leniancy is not enabled.
+   */
+  public void roll(int field, int amount)
+  {
+    switch (field)
+      {
+      case DAY_OF_WEEK:
+	// day of week is special: it rolls automatically
+	add(field, amount);
+	return;
+      case ZONE_OFFSET:
+      case DST_OFFSET:
+	throw new IllegalArgumentException("Can't roll time zone");
+      }
+    complete();
+    int min = getActualMinimum(field);
+    int range = getActualMaximum(field) - min + 1;
+    int oldval = fields[field];
+    int newval = (oldval - min + range + amount) % range + min;
+    if (newval < min)
+      newval += range;
+    fields[field] = newval;
+    cleanUpAfterRoll(field, newval - oldval);
+  }
+
+  /**
+   * The minimum values for the calendar fields.
+   */
+  private static final int[] minimums = 
+                                        {
+                                          BC, 1, 0, 0, 1, 1, 1, SUNDAY, 1, AM,
+                                          1, 0, 0, 0, 0, -(12 * 60 * 60 * 1000),
+                                          0
+                                        };
+
+  /**
+   * The maximum values for the calendar fields.
+   */
+  private static final int[] maximums = 
+                                        {
+                                          AD, 5000000, 11, 53, 6, 31, 366,
+                                          SATURDAY, 5, PM, 12, 23, 59, 59, 999,
+                                          +(12 * 60 * 60 * 1000),
+                                          (12 * 60 * 60 * 1000)
+                                        };
+
+  /**
+   * Gets the smallest value that is allowed for the specified field.
+   *
+   * @param field one of the time field constants.
+   * @return the smallest value for the specified field.
+   */
+  public int getMinimum(int field)
+  {
+    return minimums[field];
+  }
+
+  /**
+   * Gets the biggest value that is allowed for the specified field.
+   *
+   * @param field one of the time field constants.
+   * @return the biggest value.
+   */
+  public int getMaximum(int field)
+  {
+    return maximums[field];
+  }
+
+  /**
+   * Gets the greatest minimum value that is allowed for the specified field.
+   * This is the largest value returned by the <code>getActualMinimum(int)</code>
+   * method.
+   *
+   * @param field the time field. One of the time field constants.
+   * @return the greatest minimum value.
+   * @see #getActualMinimum(int)
+   */
+  public int getGreatestMinimum(int field)
+  {
+    if (field == WEEK_OF_YEAR)
+      return 1;
+    return minimums[field];
+  }
+
+  /**
+   * Gets the smallest maximum value that is allowed for the
+   * specified field.  This is the smallest value returned
+   * by the <code>getActualMaximum(int)</code>.  For example,
+   * this is 28 for DAY_OF_MONTH (as all months have at least
+   * 28 days).
+   *
+   * @param field the time field. One of the time field constants.
+   * @return the least maximum value.
+   * @see #getActualMaximum(int)
+   * @since 1.2
+   */
+  public int getLeastMaximum(int field)
+  {
+    switch (field)
+      {
+      case WEEK_OF_YEAR:
+	return 52;
+      case DAY_OF_MONTH:
+	return 28;
+      case DAY_OF_YEAR:
+	return 365;
+      case DAY_OF_WEEK_IN_MONTH:
+      case WEEK_OF_MONTH:
+	return 4;
+      default:
+	return maximums[field];
+      }
+  }
+
+  /**
+   * Gets the actual minimum value that is allowed for the specified field.
+   * This value is dependent on the values of the other fields.  Note that
+   * this calls <code>complete()</code> if not enough fields are set.  This
+   * can have ugly side effects.  The value given depends on the current
+   * time used by this instance.
+   *
+   * @param field the time field. One of the time field constants.
+   * @return the actual minimum value.
+   * @since 1.2
+   */
+  public int getActualMinimum(int field)
+  {
+    if (field == WEEK_OF_YEAR)
+      {
+	int min = getMinimalDaysInFirstWeek();
+	if (min == 0)
+	  return 1;
+	if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+	  complete();
+
+	int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+	int weekday = getWeekDay(year, min);
+	if ((7 + weekday - getFirstDayOfWeek()) % 7 >= min - 1)
+	  return 1;
+	return 0;
+      }
+    return minimums[field];
+  }
+
+  /**
+   * Gets the actual maximum value that is allowed for the specified field.
+   * This value is dependent on the values of the other fields.  Note that
+   * this calls <code>complete()</code> if not enough fields are set.  This
+   * can have ugly side effects.  The value given depends on the current time
+   * used by this instance; thus, leap years have a maximum day of month value of
+   * 29, rather than 28.
+   *
+   * @param field the time field. One of the time field constants.
+   * @return the actual maximum value.
+   */
+  public int getActualMaximum(int field)
+  {
+    switch (field)
+      {
+      case WEEK_OF_YEAR:
+        {
+	  if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+	    complete();
+
+	  // This is wrong for the year that contains the gregorian change.
+	  // I.e it gives the weeks in the julian year or in the gregorian
+	  // year in that case.
+	  int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+	  int lastDay = isLeapYear(year) ? 366 : 365;
+	  int weekday = getWeekDay(year, lastDay);
+	  int week = (lastDay + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
+
+	  int minimalDays = getMinimalDaysInFirstWeek();
+	  int firstWeekday = getWeekDay(year, minimalDays);
+	  /*
+	   * Is there a set of days at the beginning of the year, before the
+	   * first day of the week, equal to or greater than the minimum number
+	   * of days required in the first week?
+	   */
+	  if (minimalDays - (7 + firstWeekday - getFirstDayOfWeek()) % 7 < 1)
+	    return week + 1; /* Add week 1: firstWeekday through to firstDayOfWeek */
+        }
+      case DAY_OF_MONTH:
+        {
+	  if (! areFieldsSet || ! isSet[MONTH])
+	    complete();
+	  int month = fields[MONTH];
+
+	  // If you change this, you should also change 
+	  // SimpleTimeZone.getDaysInMonth();
+	  if (month == FEBRUARY)
+	    {
+	      if (! isSet[YEAR] || ! isSet[ERA])
+		complete();
+	      int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+	      return isLeapYear(year) ? 29 : 28;
+	    }
+	  else if (month < AUGUST)
+	    return 31 - (month & 1);
+	  else
+	    return 30 + (month & 1);
+        }
+      case DAY_OF_YEAR:
+        {
+	  if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+	    complete();
+	  int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+	  return isLeapYear(year) ? 366 : 365;
+        }
+      case DAY_OF_WEEK_IN_MONTH:
+        {
+	  // This is wrong for the month that contains the gregorian change.
+	  int daysInMonth = getActualMaximum(DAY_OF_MONTH);
+
+	  // That's black magic, I know
+	  return (daysInMonth - (fields[DAY_OF_MONTH] - 1) % 7 + 6) / 7;
+        }
+      case WEEK_OF_MONTH:
+        {
+	  int daysInMonth = getActualMaximum(DAY_OF_MONTH);
+	  int weekday = (daysInMonth - fields[DAY_OF_MONTH]
+	                + fields[DAY_OF_WEEK] - SUNDAY) % 7 + SUNDAY;
+	  return (daysInMonth + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
+        }
+      default:
+	return maximums[field];
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/HashMap.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/HashMap.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/HashMap.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/HashMap.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,903 @@
+/* HashMap.java -- a class providing a basic hashtable data structure,
+   mapping Object --> Object
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+// NOTE: This implementation is very similar to that of Hashtable. If you fix
+// a bug in here, chances are you should make a similar change to the Hashtable
+// code.
+
+// NOTE: This implementation has some nasty coding style in order to
+// support LinkedHashMap, which extends this.
+
+/**
+ * This class provides a hashtable-backed implementation of the
+ * Map interface.
+ * <p>
+ *
+ * It uses a hash-bucket approach; that is, hash collisions are handled
+ * by linking the new node off of the pre-existing node (or list of
+ * nodes).  In this manner, techniques such as linear probing (which
+ * can cause primary clustering) and rehashing (which does not fit very
+ * well with Java's method of precomputing hash codes) are avoided.
+ * <p>
+ *
+ * Under ideal circumstances (no collisions), HashMap offers O(1)
+ * performance on most operations (<code>containsValue()</code> is,
+ * of course, O(n)).  In the worst case (all keys map to the same
+ * hash code -- very unlikely), most operations are O(n).
+ * <p>
+ *
+ * HashMap is part of the JDK1.2 Collections API.  It differs from
+ * Hashtable in that it accepts the null key and null values, and it
+ * does not support "Enumeration views." Also, it is not synchronized;
+ * if you plan to use it in multiple threads, consider using:<br>
+ * <code>Map m = Collections.synchronizedMap(new HashMap(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * <code>ConcurrentModificationException</code> rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Jochen Hoenicke
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Object#hashCode()
+ * @see Collection
+ * @see Map
+ * @see TreeMap
+ * @see LinkedHashMap
+ * @see IdentityHashMap
+ * @see Hashtable
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class HashMap extends AbstractMap
+  implements Map, Cloneable, Serializable
+{
+  /**
+   * Default number of buckets. This is the value the JDK 1.3 uses. Some
+   * early documentation specified this value as 101. That is incorrect.
+   * Package visible for use by HashSet.
+   */
+  static final int DEFAULT_CAPACITY = 11;
+
+  /**
+   * The default load factor; this is explicitly specified by the spec.
+   * Package visible for use by HashSet.
+   */
+  static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+  /**
+   * Compatible with JDK 1.2.
+   */
+  private static final long serialVersionUID = 362498820763181265L;
+
+  /**
+   * The rounded product of the capacity and the load factor; when the number
+   * of elements exceeds the threshold, the HashMap calls
+   * <code>rehash()</code>.
+   * @serial the threshold for rehashing
+   */
+  private int threshold;
+
+  /**
+   * Load factor of this HashMap:  used in computing the threshold.
+   * Package visible for use by HashSet.
+   * @serial the load factor
+   */
+  final float loadFactor;
+
+  /**
+   * Array containing the actual key-value mappings.
+   * Package visible for use by nested and subclasses.
+   */
+  transient HashEntry[] buckets;
+
+  /**
+   * Counts the number of modifications this HashMap has undergone, used
+   * by Iterators to know when to throw ConcurrentModificationExceptions.
+   * Package visible for use by nested and subclasses.
+   */
+  transient int modCount;
+
+  /**
+   * The size of this HashMap:  denotes the number of key-value pairs.
+   * Package visible for use by nested and subclasses.
+   */
+  transient int size;
+
+  /**
+   * The cache for {@link #entrySet()}.
+   */
+  private transient Set entries;
+
+  /**
+   * Class to represent an entry in the hash table. Holds a single key-value
+   * pair. Package visible for use by subclass.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  static class HashEntry extends AbstractMap.BasicMapEntry
+  {
+    /**
+     * The next entry in the linked list. Package visible for use by subclass.
+     */
+    HashEntry next;
+
+    /**
+     * Simple constructor.
+     * @param key the key
+     * @param value the value
+     */
+    HashEntry(Object key, Object value)
+    {
+      super(key, value);
+    }
+
+    /**
+     * Called when this entry is accessed via {@link #put(Object, Object)}.
+     * This version does nothing, but in LinkedHashMap, it must do some
+     * bookkeeping for access-traversal mode.
+     */
+    void access()
+    {
+    }
+
+    /**
+     * Called when this entry is removed from the map. This version simply
+     * returns the value, but in LinkedHashMap, it must also do bookkeeping.
+     *
+     * @return the value of this key as it is removed
+     */
+    Object cleanup()
+    {
+      return value;
+    }
+  }
+
+  /**
+   * Construct a new HashMap with the default capacity (11) and the default
+   * load factor (0.75).
+   */
+  public HashMap()
+  {
+    this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
+  }
+
+  /**
+   * Construct a new HashMap from the given Map, with initial capacity
+   * the greater of the size of <code>m</code> or the default of 11.
+   * <p>
+   *
+   * Every element in Map m will be put into this new HashMap.
+   *
+   * @param m a Map whose key / value pairs will be put into the new HashMap.
+   *        <b>NOTE: key / value pairs are not cloned in this constructor.</b>
+   * @throws NullPointerException if m is null
+   */
+  public HashMap(Map m)
+  {
+    this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
+    putAll(m);
+  }
+
+  /**
+   * Construct a new HashMap with a specific inital capacity and
+   * default load factor of 0.75.
+   *
+   * @param initialCapacity the initial capacity of this HashMap (>=0)
+   * @throws IllegalArgumentException if (initialCapacity < 0)
+   */
+  public HashMap(int initialCapacity)
+  {
+    this(initialCapacity, DEFAULT_LOAD_FACTOR);
+  }
+
+  /**
+   * Construct a new HashMap with a specific inital capacity and load factor.
+   *
+   * @param initialCapacity the initial capacity (>=0)
+   * @param loadFactor the load factor (> 0, not NaN)
+   * @throws IllegalArgumentException if (initialCapacity < 0) ||
+   *                                     ! (loadFactor > 0.0)
+   */
+  public HashMap(int initialCapacity, float loadFactor)
+  {
+    if (initialCapacity < 0)
+      throw new IllegalArgumentException("Illegal Capacity: "
+                                         + initialCapacity);
+    if (! (loadFactor > 0)) // check for NaN too
+      throw new IllegalArgumentException("Illegal Load: " + loadFactor);
+
+    if (initialCapacity == 0)
+      initialCapacity = 1;
+    buckets = new HashEntry[initialCapacity];
+    this.loadFactor = loadFactor;
+    threshold = (int) (initialCapacity * loadFactor);
+  }
+
+  /**
+   * Returns the number of kay-value mappings currently in this Map.
+   *
+   * @return the size
+   */
+  public int size()
+  {
+    return size;
+  }
+
+  /**
+   * Returns true if there are no key-value mappings currently in this Map.
+   *
+   * @return <code>size() == 0</code>
+   */
+  public boolean isEmpty()
+  {
+    return size == 0;
+  }
+
+  /**
+   * Return the value in this HashMap associated with the supplied key,
+   * or <code>null</code> if the key maps to nothing.  NOTE: Since the value
+   * could also be null, you must use containsKey to see if this key
+   * actually maps to something.
+   *
+   * @param key the key for which to fetch an associated value
+   * @return what the key maps to, if present
+   * @see #put(Object, Object)
+   * @see #containsKey(Object)
+   */
+  public Object get(Object key)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    while (e != null)
+      {
+        if (equals(key, e.key))
+          return e.value;
+        e = e.next;
+      }
+    return null;
+  }
+
+  /**
+   * Returns true if the supplied object <code>equals()</code> a key
+   * in this HashMap.
+   *
+   * @param key the key to search for in this HashMap
+   * @return true if the key is in the table
+   * @see #containsValue(Object)
+   */
+  public boolean containsKey(Object key)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    while (e != null)
+      {
+        if (equals(key, e.key))
+          return true;
+        e = e.next;
+      }
+    return false;
+  }
+
+  /**
+   * Puts the supplied value into the Map, mapped by the supplied key.
+   * The value may be retrieved by any object which <code>equals()</code>
+   * this key. NOTE: Since the prior value could also be null, you must
+   * first use containsKey if you want to see if you are replacing the
+   * key's mapping.
+   *
+   * @param key the key used to locate the value
+   * @param value the value to be stored in the HashMap
+   * @return the prior mapping of the key, or null if there was none
+   * @see #get(Object)
+   * @see Object#equals(Object)
+   */
+  public Object put(Object key, Object value)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+
+    while (e != null)
+      {
+        if (equals(key, e.key))
+          {
+            e.access(); // Must call this for bookkeeping in LinkedHashMap.
+            Object r = e.value;
+            e.value = value;
+            return r;
+          }
+        else
+          e = e.next;
+      }
+
+    // At this point, we know we need to add a new entry.
+    modCount++;
+    if (++size > threshold)
+      {
+        rehash();
+        // Need a new hash value to suit the bigger table.
+        idx = hash(key);
+      }
+
+    // LinkedHashMap cannot override put(), hence this call.
+    addEntry(key, value, idx, true);
+    return null;
+  }
+
+  /**
+   * Copies all elements of the given map into this hashtable.  If this table
+   * already has a mapping for a key, the new mapping replaces the current
+   * one.
+   *
+   * @param m the map to be hashed into this
+   */
+  public void putAll(Map m)
+  {
+    Iterator itr = m.entrySet().iterator();
+    while (itr.hasNext())
+      {
+        Map.Entry e = (Map.Entry) itr.next();
+        // Optimize in case the Entry is one of our own.
+        if (e instanceof AbstractMap.BasicMapEntry)
+          {
+            AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
+            put(entry.key, entry.value);
+          }
+        else
+          put(e.getKey(), e.getValue());
+      }
+  }
+  
+  /**
+   * Removes from the HashMap and returns the value which is mapped by the
+   * supplied key. If the key maps to nothing, then the HashMap remains
+   * unchanged, and <code>null</code> is returned. NOTE: Since the value
+   * could also be null, you must use containsKey to see if you are
+   * actually removing a mapping.
+   *
+   * @param key the key used to locate the value to remove
+   * @return whatever the key mapped to, if present
+   */
+  public Object remove(Object key)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    HashEntry last = null;
+
+    while (e != null)
+      {
+        if (equals(key, e.key))
+          {
+            modCount++;
+            if (last == null)
+              buckets[idx] = e.next;
+            else
+              last.next = e.next;
+            size--;
+            // Method call necessary for LinkedHashMap to work correctly.
+            return e.cleanup();
+          }
+        last = e;
+        e = e.next;
+      }
+    return null;
+  }
+
+  /**
+   * Clears the Map so it has no keys. This is O(1).
+   */
+  public void clear()
+  {
+    if (size != 0)
+      {
+        modCount++;
+        Arrays.fill(buckets, null);
+        size = 0;
+      }
+  }
+
+  /**
+   * Returns true if this HashMap contains a value <code>o</code>, such that
+   * <code>o.equals(value)</code>.
+   *
+   * @param value the value to search for in this HashMap
+   * @return true if at least one key maps to the value
+   * @see #containsKey(Object)
+   */
+  public boolean containsValue(Object value)
+  {
+    for (int i = buckets.length - 1; i >= 0; i--)
+      {
+        HashEntry e = buckets[i];
+        while (e != null)
+          {
+            if (equals(value, e.value))
+              return true;
+            e = e.next;
+          }
+      }
+    return false;
+  }
+
+  /**
+   * Returns a shallow clone of this HashMap. The Map itself is cloned,
+   * but its contents are not.  This is O(n).
+   *
+   * @return the clone
+   */
+  public Object clone()
+  {
+    HashMap copy = null;
+    try
+      {
+        copy = (HashMap) super.clone();
+      }
+    catch (CloneNotSupportedException x)
+      {
+        // This is impossible.
+      }
+    copy.buckets = new HashEntry[buckets.length];
+    copy.putAllInternal(this);
+    // Clear the entry cache. AbstractMap.clone() does the others.
+    copy.entries = null;
+    return copy;
+  }
+
+  /**
+   * Returns a "set view" of this HashMap's keys. The set is backed by the
+   * HashMap, so changes in one show up in the other.  The set supports
+   * element removal, but not element addition.
+   *
+   * @return a set view of the keys
+   * @see #values()
+   * @see #entrySet()
+   */
+  public Set keySet()
+  {
+    if (keys == null)
+      // Create an AbstractSet with custom implementations of those methods
+      // that can be overridden easily and efficiently.
+      keys = new AbstractSet()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          // Cannot create the iterator directly, because of LinkedHashMap.
+          return HashMap.this.iterator(KEYS);
+        }
+
+        public void clear()
+        {
+          HashMap.this.clear();
+        }
+
+        public boolean contains(Object o)
+        {
+          return containsKey(o);
+        }
+
+        public boolean remove(Object o)
+        {
+          // Test against the size of the HashMap to determine if anything
+          // really got removed. This is necessary because the return value
+          // of HashMap.remove() is ambiguous in the null case.
+          int oldsize = size;
+          HashMap.this.remove(o);
+          return oldsize != size;
+        }
+      };
+    return keys;
+  }
+
+  /**
+   * Returns a "collection view" (or "bag view") of this HashMap's values.
+   * The collection is backed by the HashMap, so changes in one show up
+   * in the other.  The collection supports element removal, but not element
+   * addition.
+   *
+   * @return a bag view of the values
+   * @see #keySet()
+   * @see #entrySet()
+   */
+  public Collection values()
+  {
+    if (values == null)
+      // We don't bother overriding many of the optional methods, as doing so
+      // wouldn't provide any significant performance advantage.
+      values = new AbstractCollection()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          // Cannot create the iterator directly, because of LinkedHashMap.
+          return HashMap.this.iterator(VALUES);
+        }
+
+        public void clear()
+        {
+          HashMap.this.clear();
+        }
+      };
+    return values;
+  }
+
+  /**
+   * Returns a "set view" of this HashMap's entries. The set is backed by
+   * the HashMap, so changes in one show up in the other.  The set supports
+   * element removal, but not element addition.<p>
+   *
+   * Note that the iterators for all three views, from keySet(), entrySet(),
+   * and values(), traverse the HashMap in the same sequence.
+   *
+   * @return a set view of the entries
+   * @see #keySet()
+   * @see #values()
+   * @see Map.Entry
+   */
+  public Set entrySet()
+  {
+    if (entries == null)
+      // Create an AbstractSet with custom implementations of those methods
+      // that can be overridden easily and efficiently.
+      entries = new AbstractSet()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          // Cannot create the iterator directly, because of LinkedHashMap.
+          return HashMap.this.iterator(ENTRIES);
+        }
+
+        public void clear()
+        {
+          HashMap.this.clear();
+        }
+
+        public boolean contains(Object o)
+        {
+          return getEntry(o) != null;
+        }
+
+        public boolean remove(Object o)
+        {
+          HashEntry e = getEntry(o);
+          if (e != null)
+            {
+              HashMap.this.remove(e.key);
+              return true;
+            }
+          return false;
+        }
+      };
+    return entries;
+  }
+
+  /**
+   * Helper method for put, that creates and adds a new Entry.  This is
+   * overridden in LinkedHashMap for bookkeeping purposes.
+   *
+   * @param key the key of the new Entry
+   * @param value the value
+   * @param idx the index in buckets where the new Entry belongs
+   * @param callRemove whether to call the removeEldestEntry method
+   * @see #put(Object, Object)
+   */
+  void addEntry(Object key, Object value, int idx, boolean callRemove)
+  {
+    HashEntry e = new HashEntry(key, value);
+    e.next = buckets[idx];
+    buckets[idx] = e;
+  }
+
+  /**
+   * Helper method for entrySet(), which matches both key and value
+   * simultaneously.
+   *
+   * @param o the entry to match
+   * @return the matching entry, if found, or null
+   * @see #entrySet()
+   */
+  // Package visible, for use in nested classes.
+  final HashEntry getEntry(Object o)
+  {
+    if (! (o instanceof Map.Entry))
+      return null;
+    Map.Entry me = (Map.Entry) o;
+    Object key = me.getKey();
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    while (e != null)
+      {
+        if (equals(e.key, key))
+          return equals(e.value, me.getValue()) ? e : null;
+        e = e.next;
+      }
+    return null;
+  }
+
+  /**
+   * Helper method that returns an index in the buckets array for `key'
+   * based on its hashCode().  Package visible for use by subclasses.
+   *
+   * @param key the key
+   * @return the bucket number
+   */
+  final int hash(Object key)
+  {
+    return key == null ? 0 : Math.abs(key.hashCode() % buckets.length);
+  }
+
+  /**
+   * Generates a parameterized iterator.  Must be overrideable, since
+   * LinkedHashMap iterates in a different order.
+   *
+   * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+   * @return the appropriate iterator
+   */
+  Iterator iterator(int type)
+  {
+    return new HashIterator(type);
+  }
+
+  /**
+   * A simplified, more efficient internal implementation of putAll(). clone() 
+   * should not call putAll or put, in order to be compatible with the JDK 
+   * implementation with respect to subclasses.
+   *
+   * @param m the map to initialize this from
+   */
+  void putAllInternal(Map m)
+  {
+    Iterator itr = m.entrySet().iterator();
+    size = 0;
+    while (itr.hasNext())
+      {
+        size++;
+	Map.Entry e = (Map.Entry) itr.next();
+	Object key = e.getKey();
+	int idx = hash(key);
+	addEntry(key, e.getValue(), idx, false);
+      }
+  }
+
+  /**
+   * Increases the size of the HashMap and rehashes all keys to new
+   * array indices; this is called when the addition of a new value
+   * would cause size() > threshold. Note that the existing Entry
+   * objects are reused in the new hash table.
+   *
+   * <p>This is not specified, but the new size is twice the current size
+   * plus one; this number is not always prime, unfortunately.
+   */
+  private void rehash()
+  {
+    HashEntry[] oldBuckets = buckets;
+
+    int newcapacity = (buckets.length * 2) + 1;
+    threshold = (int) (newcapacity * loadFactor);
+    buckets = new HashEntry[newcapacity];
+
+    for (int i = oldBuckets.length - 1; i >= 0; i--)
+      {
+        HashEntry e = oldBuckets[i];
+        while (e != null)
+          {
+            int idx = hash(e.key);
+            HashEntry dest = buckets[idx];
+            HashEntry next = e.next;
+            e.next = buckets[idx];
+            buckets[idx] = e;
+            e = next;
+          }
+      }
+  }
+
+  /**
+   * Serializes this object to the given stream.
+   *
+   * @param s the stream to write to
+   * @throws IOException if the underlying stream fails
+   * @serialData the <i>capacity</i>(int) that is the length of the
+   *             bucket array, the <i>size</i>(int) of the hash map
+   *             are emitted first.  They are followed by size entries,
+   *             each consisting of a key (Object) and a value (Object).
+   */
+  private void writeObject(ObjectOutputStream s) throws IOException
+  {
+    // Write the threshold and loadFactor fields.
+    s.defaultWriteObject();
+
+    s.writeInt(buckets.length);
+    s.writeInt(size);
+    // Avoid creating a wasted Set by creating the iterator directly.
+    Iterator it = iterator(ENTRIES);
+    while (it.hasNext())
+      {
+        HashEntry entry = (HashEntry) it.next();
+        s.writeObject(entry.key);
+        s.writeObject(entry.value);
+      }
+  }
+
+  /**
+   * Deserializes this object from the given stream.
+   *
+   * @param s the stream to read from
+   * @throws ClassNotFoundException if the underlying stream fails
+   * @throws IOException if the underlying stream fails
+   * @serialData the <i>capacity</i>(int) that is the length of the
+   *             bucket array, the <i>size</i>(int) of the hash map
+   *             are emitted first.  They are followed by size entries,
+   *             each consisting of a key (Object) and a value (Object).
+   */
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException
+  {
+    // Read the threshold and loadFactor fields.
+    s.defaultReadObject();
+
+    // Read and use capacity, followed by key/value pairs.
+    buckets = new HashEntry[s.readInt()];
+    int len = s.readInt();
+    size = len;
+    while (len-- > 0)
+      {
+        Object key = s.readObject();
+        addEntry(key, s.readObject(), hash(key), false);
+      }
+  }
+
+  /**
+   * Iterate over HashMap's entries.
+   * This implementation is parameterized to give a sequential view of
+   * keys, values, or entries.
+   *
+   * @author Jon Zeppieri
+   */
+  private final class HashIterator implements Iterator
+  {
+    /**
+     * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
+     * or {@link #ENTRIES}.
+     */
+    private final int type;
+    /**
+     * The number of modifications to the backing HashMap that we know about.
+     */
+    private int knownMod = modCount;
+    /** The number of elements remaining to be returned by next(). */
+    private int count = size;
+    /** Current index in the physical hash table. */
+    private int idx = buckets.length;
+    /** The last Entry returned by a next() call. */
+    private HashEntry last;
+    /**
+     * The next entry that should be returned by next(). It is set to something
+     * if we're iterating through a bucket that contains multiple linked
+     * entries. It is null if next() needs to find a new bucket.
+     */
+    private HashEntry next;
+
+    /**
+     * Construct a new HashIterator with the supplied type.
+     * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+     */
+    HashIterator(int type)
+    {
+      this.type = type;
+    }
+
+    /**
+     * Returns true if the Iterator has more elements.
+     * @return true if there are more elements
+     */
+    public boolean hasNext()
+    {
+      return count > 0;
+    }
+
+    /**
+     * Returns the next element in the Iterator's sequential view.
+     * @return the next element
+     * @throws ConcurrentModificationException if the HashMap was modified
+     * @throws NoSuchElementException if there is none
+     */
+    public Object next()
+    {
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+      if (count == 0)
+        throw new NoSuchElementException();
+      count--;
+      HashEntry e = next;
+
+      while (e == null)
+        e = buckets[--idx];
+
+      next = e.next;
+      last = e;
+      if (type == VALUES)
+        return e.value;
+      if (type == KEYS)
+        return e.key;
+      return e;
+    }
+
+    /**
+     * Removes from the backing HashMap the last element which was fetched
+     * with the <code>next()</code> method.
+     * @throws ConcurrentModificationException if the HashMap was modified
+     * @throws IllegalStateException if called when there is no last element
+     */
+    public void remove()
+    {
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+      if (last == null)
+        throw new IllegalStateException();
+
+      HashMap.this.remove(last.key);
+      last = null;
+      knownMod++;
+    }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/HashSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/HashSet.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/HashSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/HashSet.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,293 @@
+/* HashSet.java -- a class providing a HashMap-backed Set
+   Copyright (C) 1998, 1999, 2001, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * This class provides a HashMap-backed implementation of the Set interface.
+ * <p>
+ *
+ * Most operations are O(1), assuming no hash collisions.  In the worst
+ * case (where all hashes collide), operations are O(n). Setting the
+ * initial capacity too low will force many resizing operations, but
+ * setting the initial capacity too high (or loadfactor too low) leads
+ * to wasted memory and slower iteration.
+ * <p>
+ *
+ * HashSet accepts the null key and null values.  It is not synchronized,
+ * so if you need multi-threaded access, consider using:<br>
+ * <code>Set s = Collections.synchronizedSet(new HashSet(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Collection
+ * @see Set
+ * @see TreeSet
+ * @see Collections#synchronizedSet(Set)
+ * @see HashMap
+ * @see LinkedHashSet
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class HashSet extends AbstractSet
+  implements Set, Cloneable, Serializable
+{
+  /**
+   * Compatible with JDK 1.2.
+   */
+  private static final long serialVersionUID = -5024744406713321676L;
+
+  /**
+   * The HashMap which backs this Set.
+   */
+  private transient HashMap map;
+
+  /**
+   * Construct a new, empty HashSet whose backing HashMap has the default
+   * capacity (11) and loadFacor (0.75).
+   */
+  public HashSet()
+  {
+    this(HashMap.DEFAULT_CAPACITY, HashMap.DEFAULT_LOAD_FACTOR);
+  }
+
+  /**
+   * Construct a new, empty HashSet whose backing HashMap has the supplied
+   * capacity and the default load factor (0.75).
+   *
+   * @param initialCapacity the initial capacity of the backing HashMap
+   * @throws IllegalArgumentException if the capacity is negative
+   */
+  public HashSet(int initialCapacity)
+  {
+    this(initialCapacity, HashMap.DEFAULT_LOAD_FACTOR);
+  }
+
+  /**
+   * Construct a new, empty HashSet whose backing HashMap has the supplied
+   * capacity and load factor.
+   *
+   * @param initialCapacity the initial capacity of the backing HashMap
+   * @param loadFactor the load factor of the backing HashMap
+   * @throws IllegalArgumentException if either argument is negative, or
+   *         if loadFactor is POSITIVE_INFINITY or NaN
+   */
+  public HashSet(int initialCapacity, float loadFactor)
+  {
+    map = init(initialCapacity, loadFactor);
+  }
+
+  /**
+   * Construct a new HashSet with the same elements as are in the supplied
+   * collection (eliminating any duplicates, of course). The backing storage
+   * has twice the size of the collection, or the default size of 11,
+   * whichever is greater; and the default load factor (0.75).
+   *
+   * @param c a collection of initial set elements
+   * @throws NullPointerException if c is null
+   */
+  public HashSet(Collection c)
+  {
+    this(Math.max(2 * c.size(), HashMap.DEFAULT_CAPACITY));
+    addAll(c);
+  }
+
+  /**
+   * Adds the given Object to the set if it is not already in the Set.
+   * This set permits a null element.
+   *
+   * @param o the Object to add to this Set
+   * @return true if the set did not already contain o
+   */
+  public boolean add(Object o)
+  {
+    return map.put(o, "") == null;
+  }
+
+  /**
+   * Empties this Set of all elements; this takes constant time.
+   */
+  public void clear()
+  {
+    map.clear();
+  }
+
+  /**
+   * Returns a shallow copy of this Set. The Set itself is cloned; its
+   * elements are not.
+   *
+   * @return a shallow clone of the set
+   */
+  public Object clone()
+  {
+    HashSet copy = null;
+    try
+      {
+        copy = (HashSet) super.clone();
+      }
+    catch (CloneNotSupportedException x)
+      {
+        // Impossible to get here.
+      }
+    copy.map = (HashMap) map.clone();
+    return copy;
+  }
+
+  /**
+   * Returns true if the supplied element is in this Set.
+   *
+   * @param o the Object to look for
+   * @return true if it is in the set
+   */
+  public boolean contains(Object o)
+  {
+    return map.containsKey(o);
+  }
+
+  /**
+   * Returns true if this set has no elements in it.
+   *
+   * @return <code>size() == 0</code>.
+   */
+  public boolean isEmpty()
+  {
+    return map.size == 0;
+  }
+
+  /**
+   * Returns an Iterator over the elements of this Set, which visits the
+   * elements in no particular order.  For this class, the Iterator allows
+   * removal of elements. The iterator is fail-fast, and will throw a
+   * ConcurrentModificationException if the set is modified externally.
+   *
+   * @return a set iterator
+   * @see ConcurrentModificationException
+   */
+  public Iterator iterator()
+  {
+    // Avoid creating intermediate keySet() object by using non-public API.
+    return map.iterator(HashMap.KEYS);
+  }
+
+  /**
+   * Removes the supplied Object from this Set if it is in the Set.
+   *
+   * @param o the object to remove
+   * @return true if an element was removed
+   */
+  public boolean remove(Object o)
+  {
+    return (map.remove(o) != null);
+  }
+
+  /**
+   * Returns the number of elements in this Set (its cardinality).
+   *
+   * @return the size of the set
+   */
+  public int size()
+  {
+    return map.size;
+  }
+
+  /**
+   * Helper method which initializes the backing Map. Overridden by
+   * LinkedHashSet for correct semantics.
+   *
+   * @param capacity the initial capacity
+   * @param load the initial load factor
+   * @return the backing HashMap
+   */
+  HashMap init(int capacity, float load)
+  {
+    return new HashMap(capacity, load);
+  }
+
+  /**
+   * Serializes this object to the given stream.
+   *
+   * @param s the stream to write to
+   * @throws IOException if the underlying stream fails
+   * @serialData the <i>capacity</i> (int) and <i>loadFactor</i> (float)
+   *             of the backing store, followed by the set size (int),
+   *             then a listing of its elements (Object) in no order
+   */
+  private void writeObject(ObjectOutputStream s) throws IOException
+  {
+    s.defaultWriteObject();
+    // Avoid creating intermediate keySet() object by using non-public API.
+    Iterator it = map.iterator(HashMap.KEYS);
+    s.writeInt(map.buckets.length);
+    s.writeFloat(map.loadFactor);
+    s.writeInt(map.size);
+    while (it.hasNext())
+      s.writeObject(it.next());
+  }
+
+  /**
+   * Deserializes this object from the given stream.
+   *
+   * @param s the stream to read from
+   * @throws ClassNotFoundException if the underlying stream fails
+   * @throws IOException if the underlying stream fails
+   * @serialData the <i>capacity</i> (int) and <i>loadFactor</i> (float)
+   *             of the backing store, followed by the set size (int),
+   *             then a listing of its elements (Object) in no order
+   */
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException
+  {
+    s.defaultReadObject();
+
+    map = init(s.readInt(), s.readFloat());
+    for (int size = s.readInt(); size > 0; size--)
+      map.put(s.readObject(), "");
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Hashtable.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Hashtable.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Hashtable.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Hashtable.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1248 @@
+/* Hashtable.java -- a class providing a basic hashtable data structure,
+   mapping Object --> Object
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+// NOTE: This implementation is very similar to that of HashMap. If you fix
+// a bug in here, chances are you should make a similar change to the HashMap
+// code.
+
+/**
+ * A class which implements a hashtable data structure.
+ * <p>
+ *
+ * This implementation of Hashtable uses a hash-bucket approach. That is:
+ * linear probing and rehashing is avoided; instead, each hashed value maps
+ * to a simple linked-list which, in the best case, only has one node.
+ * Assuming a large enough table, low enough load factor, and / or well
+ * implemented hashCode() methods, Hashtable should provide O(1)
+ * insertion, deletion, and searching of keys.  Hashtable is O(n) in
+ * the worst case for all of these (if all keys hash to the same bucket).
+ * <p>
+ *
+ * This is a JDK-1.2 compliant implementation of Hashtable.  As such, it
+ * belongs, partially, to the Collections framework (in that it implements
+ * Map).  For backwards compatibility, it inherits from the obsolete and
+ * utterly useless Dictionary class.
+ * <p>
+ *
+ * Being a hybrid of old and new, Hashtable has methods which provide redundant
+ * capability, but with subtle and even crucial differences.
+ * For example, one can iterate over various aspects of a Hashtable with
+ * either an Iterator (which is the JDK-1.2 way of doing things) or with an
+ * Enumeration.  The latter can end up in an undefined state if the Hashtable
+ * changes while the Enumeration is open.
+ * <p>
+ *
+ * Unlike HashMap, Hashtable does not accept `null' as a key value. Also,
+ * all accesses are synchronized: in a single thread environment, this is
+ * expensive, but in a multi-thread environment, this saves you the effort
+ * of extra synchronization. However, the old-style enumerators are not
+ * synchronized, because they can lead to unspecified behavior even if
+ * they were synchronized. You have been warned.
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * <code>ConcurrentModificationException</code> rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Warren Levy
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see HashMap
+ * @see TreeMap
+ * @see IdentityHashMap
+ * @see LinkedHashMap
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Hashtable extends Dictionary
+  implements Map, Cloneable, Serializable
+{
+  // WARNING: Hashtable is a CORE class in the bootstrap cycle. See the
+  // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+  /** Default number of buckets. This is the value the JDK 1.3 uses. Some
+   * early documentation specified this value as 101. That is incorrect.
+   */
+  private static final int DEFAULT_CAPACITY = 11;
+
+  /**
+   * The default load factor; this is explicitly specified by the spec.
+   */
+  private static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+  /**
+   * Compatible with JDK 1.0+.
+   */
+  private static final long serialVersionUID = 1421746759512286392L;
+
+  /**
+   * The rounded product of the capacity and the load factor; when the number
+   * of elements exceeds the threshold, the Hashtable calls
+   * <code>rehash()</code>.
+   * @serial
+   */
+  private int threshold;
+
+  /**
+   * Load factor of this Hashtable:  used in computing the threshold.
+   * @serial
+   */
+  private final float loadFactor;
+
+  /**
+   * Array containing the actual key-value mappings.
+   */
+  // Package visible for use by nested classes.
+  transient HashEntry[] buckets;
+
+  /**
+   * Counts the number of modifications this Hashtable has undergone, used
+   * by Iterators to know when to throw ConcurrentModificationExceptions.
+   */
+  // Package visible for use by nested classes.
+  transient int modCount;
+
+  /**
+   * The size of this Hashtable:  denotes the number of key-value pairs.
+   */
+  // Package visible for use by nested classes.
+  transient int size;
+
+  /**
+   * The cache for {@link #keySet()}.
+   */
+  private transient Set keys;
+
+  /**
+   * The cache for {@link #values()}.
+   */
+  private transient Collection values;
+
+  /**
+   * The cache for {@link #entrySet()}.
+   */
+  private transient Set entries;
+
+  /**
+   * Class to represent an entry in the hash table. Holds a single key-value
+   * pair. A Hashtable Entry is identical to a HashMap Entry, except that
+   * `null' is not allowed for keys and values.
+   */
+  private static final class HashEntry extends AbstractMap.BasicMapEntry
+  {
+    /** The next entry in the linked list. */
+    HashEntry next;
+
+    /**
+     * Simple constructor.
+     * @param key the key, already guaranteed non-null
+     * @param value the value, already guaranteed non-null
+     */
+    HashEntry(Object key, Object value)
+    {
+      super(key, value);
+    }
+
+    /**
+     * Resets the value.
+     * @param newVal the new value
+     * @return the prior value
+     * @throws NullPointerException if <code>newVal</code> is null
+     */
+    public Object setValue(Object newVal)
+    {
+      if (newVal == null)
+        throw new NullPointerException();
+      return super.setValue(newVal);
+    }
+  }
+
+  /**
+   * Construct a new Hashtable with the default capacity (11) and the default
+   * load factor (0.75).
+   */
+  public Hashtable()
+  {
+    this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
+  }
+
+  /**
+   * Construct a new Hashtable from the given Map, with initial capacity
+   * the greater of the size of <code>m</code> or the default of 11.
+   * <p>
+   *
+   * Every element in Map m will be put into this new Hashtable.
+   *
+   * @param m a Map whose key / value pairs will be put into
+   *          the new Hashtable.  <b>NOTE: key / value pairs
+   *          are not cloned in this constructor.</b>
+   * @throws NullPointerException if m is null, or if m contains a mapping
+   *         to or from `null'.
+   * @since 1.2
+   */
+  public Hashtable(Map m)
+  {
+    this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
+    putAll(m);
+  }
+
+  /**
+   * Construct a new Hashtable with a specific inital capacity and
+   * default load factor of 0.75.
+   *
+   * @param initialCapacity the initial capacity of this Hashtable (>= 0)
+   * @throws IllegalArgumentException if (initialCapacity < 0)
+   */
+  public Hashtable(int initialCapacity)
+  {
+    this(initialCapacity, DEFAULT_LOAD_FACTOR);
+  }
+
+  /**
+   * Construct a new Hashtable with a specific initial capacity and
+   * load factor.
+   *
+   * @param initialCapacity the initial capacity (>= 0)
+   * @param loadFactor the load factor (> 0, not NaN)
+   * @throws IllegalArgumentException if (initialCapacity < 0) ||
+   *                                     ! (loadFactor > 0.0)
+   */
+  public Hashtable(int initialCapacity, float loadFactor)
+  {
+    if (initialCapacity < 0)
+      throw new IllegalArgumentException("Illegal Capacity: "
+                                         + initialCapacity);
+    if (! (loadFactor > 0)) // check for NaN too
+      throw new IllegalArgumentException("Illegal Load: " + loadFactor);
+
+    if (initialCapacity == 0)
+      initialCapacity = 1;
+    buckets = new HashEntry[initialCapacity];
+    this.loadFactor = loadFactor;
+    threshold = (int) (initialCapacity * loadFactor);
+  }
+
+  /**
+   * Returns the number of key-value mappings currently in this hashtable.
+   * @return the size
+   */
+  public synchronized int size()
+  {
+    return size;
+  }
+
+  /**
+   * Returns true if there are no key-value mappings currently in this table.
+   * @return <code>size() == 0</code>
+   */
+  public synchronized boolean isEmpty()
+  {
+    return size == 0;
+  }
+
+  /**
+   * Return an enumeration of the keys of this table. There's no point
+   * in synchronizing this, as you have already been warned that the
+   * enumeration is not specified to be thread-safe.
+   *
+   * @return the keys
+   * @see #elements()
+   * @see #keySet()
+   */
+  public Enumeration keys()
+  {
+    return new KeyEnumerator();
+  }
+
+  /**
+   * Return an enumeration of the values of this table. There's no point
+   * in synchronizing this, as you have already been warned that the
+   * enumeration is not specified to be thread-safe.
+   *
+   * @return the values
+   * @see #keys()
+   * @see #values()
+   */
+  public Enumeration elements()
+  {
+    return new ValueEnumerator();
+  }
+
+  /**
+   * Returns true if this Hashtable contains a value <code>o</code>,
+   * such that <code>o.equals(value)</code>.  This is the same as
+   * <code>containsValue()</code>, and is O(n).
+   * <p>
+   *
+   * @param value the value to search for in this Hashtable
+   * @return true if at least one key maps to the value
+   * @throws NullPointerException if <code>value</code> is null
+   * @see #containsValue(Object)
+   * @see #containsKey(Object)
+   */
+  public synchronized boolean contains(Object value)
+  {
+    if (value == null)
+      throw new NullPointerException();
+
+    for (int i = buckets.length - 1; i >= 0; i--)
+      {
+        HashEntry e = buckets[i];
+        while (e != null)
+          {
+            if (e.value.equals(value))
+              return true;
+            e = e.next;
+          }
+      }
+ 
+    return false;  
+  }
+
+  /**
+   * Returns true if this Hashtable contains a value <code>o</code>, such that
+   * <code>o.equals(value)</code>. This is the new API for the old
+   * <code>contains()</code>.
+   *
+   * @param value the value to search for in this Hashtable
+   * @return true if at least one key maps to the value
+   * @see #contains(Object)
+   * @see #containsKey(Object)
+   * @throws NullPointerException if <code>value</code> is null
+   * @since 1.2
+   */
+  public boolean containsValue(Object value)
+  {
+    // Delegate to older method to make sure code overriding it continues 
+    // to work.
+    return contains(value);
+  }
+
+  /**
+   * Returns true if the supplied object <code>equals()</code> a key
+   * in this Hashtable.
+   *
+   * @param key the key to search for in this Hashtable
+   * @return true if the key is in the table
+   * @throws NullPointerException if key is null
+   * @see #containsValue(Object)
+   */
+  public synchronized boolean containsKey(Object key)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    while (e != null)
+      {
+        if (e.key.equals(key))
+          return true;
+        e = e.next;
+      }
+    return false;
+  }
+
+  /**
+   * Return the value in this Hashtable associated with the supplied key,
+   * or <code>null</code> if the key maps to nothing.
+   *
+   * @param key the key for which to fetch an associated value
+   * @return what the key maps to, if present
+   * @throws NullPointerException if key is null
+   * @see #put(Object, Object)
+   * @see #containsKey(Object)
+   */
+  public synchronized Object get(Object key)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    while (e != null)
+      {
+        if (e.key.equals(key))
+          return e.value;
+        e = e.next;
+      }
+    return null;
+  }
+
+  /**
+   * Puts the supplied value into the Map, mapped by the supplied key.
+   * Neither parameter may be null.  The value may be retrieved by any
+   * object which <code>equals()</code> this key.
+   *
+   * @param key the key used to locate the value
+   * @param value the value to be stored in the table
+   * @return the prior mapping of the key, or null if there was none
+   * @throws NullPointerException if key or value is null
+   * @see #get(Object)
+   * @see Object#equals(Object)
+   */
+  public synchronized Object put(Object key, Object value)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+
+    // Check if value is null since it is not permitted.
+    if (value == null)
+      throw new NullPointerException();
+
+    while (e != null)
+      {
+        if (e.key.equals(key))
+          {
+            // Bypass e.setValue, since we already know value is non-null.
+            Object r = e.value;
+            e.value = value;
+            return r;
+          }
+        else
+          {
+            e = e.next;
+          }
+      }
+
+    // At this point, we know we need to add a new entry.
+    modCount++;
+    if (++size > threshold)
+      {
+        rehash();
+        // Need a new hash value to suit the bigger table.
+        idx = hash(key);
+      }
+
+    e = new HashEntry(key, value);
+
+    e.next = buckets[idx];
+    buckets[idx] = e;
+
+    return null;
+  }
+
+  /**
+   * Removes from the table and returns the value which is mapped by the
+   * supplied key. If the key maps to nothing, then the table remains
+   * unchanged, and <code>null</code> is returned.
+   *
+   * @param key the key used to locate the value to remove
+   * @return whatever the key mapped to, if present
+   */
+  public synchronized Object remove(Object key)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    HashEntry last = null;
+
+    while (e != null)
+      {
+        if (e.key.equals(key))
+          {
+            modCount++;
+            if (last == null)
+              buckets[idx] = e.next;
+            else
+              last.next = e.next;
+            size--;
+            return e.value;
+          }
+        last = e;
+        e = e.next;
+      }
+    return null;
+  }
+
+  /**
+   * Copies all elements of the given map into this hashtable.  However, no
+   * mapping can contain null as key or value.  If this table already has
+   * a mapping for a key, the new mapping replaces the current one.
+   *
+   * @param m the map to be hashed into this
+   * @throws NullPointerException if m is null, or contains null keys or values
+   */
+  public synchronized void putAll(Map m)
+  {
+    Iterator itr = m.entrySet().iterator();
+
+    while (itr.hasNext())
+      {
+        Map.Entry e = (Map.Entry) itr.next();
+        // Optimize in case the Entry is one of our own.
+        if (e instanceof AbstractMap.BasicMapEntry)
+          {
+            AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
+            put(entry.key, entry.value);
+          }
+        else
+          {
+            put(e.getKey(), e.getValue());
+          }
+      }
+  }
+
+  /**
+   * Clears the hashtable so it has no keys.  This is O(1).
+   */
+  public synchronized void clear()
+  {
+    if (size > 0)
+      {
+        modCount++;
+        Arrays.fill(buckets, null);
+        size = 0;
+      }
+  }
+
+  /**
+   * Returns a shallow clone of this Hashtable. The Map itself is cloned,
+   * but its contents are not.  This is O(n).
+   *
+   * @return the clone
+   */
+  public synchronized Object clone()
+  {
+    Hashtable copy = null;
+    try
+      {
+        copy = (Hashtable) super.clone();
+      }
+    catch (CloneNotSupportedException x)
+      {
+        // This is impossible.
+      }
+    copy.buckets = new HashEntry[buckets.length];
+    copy.putAllInternal(this);
+    // Clear the caches.
+    copy.keys = null;
+    copy.values = null;
+    copy.entries = null;
+    return copy;
+  }
+
+  /**
+   * Converts this Hashtable to a String, surrounded by braces, and with
+   * key/value pairs listed with an equals sign between, separated by a
+   * comma and space. For example, <code>"{a=1, b=2}"</code>.<p>
+   *
+   * NOTE: if the <code>toString()</code> method of any key or value
+   * throws an exception, this will fail for the same reason.
+   *
+   * @return the string representation
+   */
+  public synchronized String toString()
+  {
+    // Since we are already synchronized, and entrySet().iterator()
+    // would repeatedly re-lock/release the monitor, we directly use the
+    // unsynchronized EntryIterator instead.
+    Iterator entries = new EntryIterator();
+    StringBuffer r = new StringBuffer("{");
+    for (int pos = size; pos > 0; pos--)
+      {
+        r.append(entries.next());
+        if (pos > 1)
+          r.append(", ");
+      }
+    r.append("}");
+    return r.toString();
+  }
+
+  /**
+   * Returns a "set view" of this Hashtable's keys. The set is backed by
+   * the hashtable, so changes in one show up in the other.  The set supports
+   * element removal, but not element addition.  The set is properly
+   * synchronized on the original hashtable.  Sun has not documented the
+   * proper interaction of null with this set, but has inconsistent behavior
+   * in the JDK. Therefore, in this implementation, contains, remove,
+   * containsAll, retainAll, removeAll, and equals just ignore a null key
+   * rather than throwing a {@link NullPointerException}.
+   *
+   * @return a set view of the keys
+   * @see #values()
+   * @see #entrySet()
+   * @since 1.2
+   */
+  public Set keySet()
+  {
+    if (keys == null)
+      {
+        // Create a synchronized AbstractSet with custom implementations of
+        // those methods that can be overridden easily and efficiently.
+        Set r = new AbstractSet()
+        {
+          public int size()
+          {
+            return size;
+          }
+
+          public Iterator iterator()
+          {
+            return new KeyIterator();
+          }
+
+          public void clear()
+          {
+            Hashtable.this.clear();
+          }
+
+          public boolean contains(Object o)
+          {
+            if (o == null)
+              return false;
+            return containsKey(o);
+          }
+
+          public boolean remove(Object o)
+          {
+            return Hashtable.this.remove(o) != null;
+          }
+        };
+        // We must specify the correct object to synchronize upon, hence the
+        // use of a non-public API
+        keys = new Collections.SynchronizedSet(this, r);
+      }
+    return keys;
+  }
+
+  /**
+   * Returns a "collection view" (or "bag view") of this Hashtable's values.
+   * The collection is backed by the hashtable, so changes in one show up
+   * in the other.  The collection supports element removal, but not element
+   * addition.  The collection is properly synchronized on the original
+   * hashtable.  Sun has not documented the proper interaction of null with
+   * this set, but has inconsistent behavior in the JDK. Therefore, in this
+   * implementation, contains, remove, containsAll, retainAll, removeAll, and
+   * equals just ignore a null value rather than throwing a
+   * {@link NullPointerException}.
+   *
+   * @return a bag view of the values
+   * @see #keySet()
+   * @see #entrySet()
+   * @since 1.2
+   */
+  public Collection values()
+  {
+    if (values == null)
+      {
+        // We don't bother overriding many of the optional methods, as doing so
+        // wouldn't provide any significant performance advantage.
+        Collection r = new AbstractCollection()
+        {
+          public int size()
+          {
+            return size;
+          }
+
+          public Iterator iterator()
+          {
+            return new ValueIterator();
+          }
+
+          public void clear()
+          {
+            Hashtable.this.clear();
+          }
+        };
+        // We must specify the correct object to synchronize upon, hence the
+        // use of a non-public API
+        values = new Collections.SynchronizedCollection(this, r);
+      }
+    return values;
+  }
+
+  /**
+   * Returns a "set view" of this Hashtable's entries. The set is backed by
+   * the hashtable, so changes in one show up in the other.  The set supports
+   * element removal, but not element addition.  The set is properly
+   * synchronized on the original hashtable.  Sun has not documented the
+   * proper interaction of null with this set, but has inconsistent behavior
+   * in the JDK. Therefore, in this implementation, contains, remove,
+   * containsAll, retainAll, removeAll, and equals just ignore a null entry,
+   * or an entry with a null key or value, rather than throwing a
+   * {@link NullPointerException}. However, calling entry.setValue(null)
+   * will fail.
+   * <p>
+   *
+   * Note that the iterators for all three views, from keySet(), entrySet(),
+   * and values(), traverse the hashtable in the same sequence.
+   *
+   * @return a set view of the entries
+   * @see #keySet()
+   * @see #values()
+   * @see Map.Entry
+   * @since 1.2
+   */
+  public Set entrySet()
+  {
+    if (entries == null)
+      {
+        // Create an AbstractSet with custom implementations of those methods
+        // that can be overridden easily and efficiently.
+        Set r = new AbstractSet()
+        {
+          public int size()
+          {
+            return size;
+          }
+
+          public Iterator iterator()
+          {
+            return new EntryIterator();
+          }
+
+          public void clear()
+          {
+            Hashtable.this.clear();
+          }
+
+          public boolean contains(Object o)
+          {
+            return getEntry(o) != null;
+          }
+
+          public boolean remove(Object o)
+          {
+            HashEntry e = getEntry(o);
+            if (e != null)
+              {
+                Hashtable.this.remove(e.key);
+                return true;
+              }
+            return false;
+          }
+        };
+        // We must specify the correct object to synchronize upon, hence the
+        // use of a non-public API
+        entries = new Collections.SynchronizedSet(this, r);
+      }
+    return entries;
+  }
+
+  /**
+   * Returns true if this Hashtable equals the supplied Object <code>o</code>.
+   * As specified by Map, this is:
+   * <code>
+   * (o instanceof Map) && entrySet().equals(((Map) o).entrySet());
+   * </code>
+   *
+   * @param o the object to compare to
+   * @return true if o is an equal map
+   * @since 1.2
+   */
+  public boolean equals(Object o)
+  {
+    // no need to synchronize, entrySet().equals() does that
+    if (o == this)
+      return true;
+    if (!(o instanceof Map))
+      return false;
+
+    return entrySet().equals(((Map) o).entrySet());
+  }
+
+  /**
+   * Returns the hashCode for this Hashtable.  As specified by Map, this is
+   * the sum of the hashCodes of all of its Map.Entry objects
+   *
+   * @return the sum of the hashcodes of the entries
+   * @since 1.2
+   */
+  public synchronized int hashCode()
+  {
+    // Since we are already synchronized, and entrySet().iterator()
+    // would repeatedly re-lock/release the monitor, we directly use the
+    // unsynchronized EntryIterator instead.
+    Iterator itr = new EntryIterator();
+    int hashcode = 0;
+    for (int pos = size; pos > 0; pos--)
+      hashcode += itr.next().hashCode();
+
+    return hashcode;
+  }
+
+  /**
+   * Helper method that returns an index in the buckets array for `key'
+   * based on its hashCode().
+   *
+   * @param key the key
+   * @return the bucket number
+   * @throws NullPointerException if key is null
+   */
+  private int hash(Object key)
+  {
+    // Note: Inline Math.abs here, for less method overhead, and to avoid
+    // a bootstrap dependency, since Math relies on native methods.
+    int hash = key.hashCode() % buckets.length;
+    return hash < 0 ? -hash : hash;
+  }
+
+  /**
+   * Helper method for entrySet(), which matches both key and value
+   * simultaneously. Ignores null, as mentioned in entrySet().
+   *
+   * @param o the entry to match
+   * @return the matching entry, if found, or null
+   * @see #entrySet()
+   */
+  // Package visible, for use in nested classes.
+  HashEntry getEntry(Object o)
+  {
+    if (! (o instanceof Map.Entry))
+      return null;
+    Object key = ((Map.Entry) o).getKey();
+    if (key == null)
+      return null;
+
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    while (e != null)
+      {
+        if (e.equals(o))
+          return e;
+        e = e.next;
+      }
+    return null;
+  }
+
+  /**
+   * A simplified, more efficient internal implementation of putAll(). clone() 
+   * should not call putAll or put, in order to be compatible with the JDK 
+   * implementation with respect to subclasses.
+   *
+   * @param m the map to initialize this from
+   */
+  void putAllInternal(Map m)
+  {
+    Iterator itr = m.entrySet().iterator();
+    size = 0;
+
+    while (itr.hasNext())
+      {
+        size++;
+	Map.Entry e = (Map.Entry) itr.next();
+	Object key = e.getKey();
+	int idx = hash(key);
+	HashEntry he = new HashEntry(key, e.getValue());
+	he.next = buckets[idx];
+	buckets[idx] = he;
+      }
+  }
+
+  /**
+   * Increases the size of the Hashtable and rehashes all keys to new array
+   * indices; this is called when the addition of a new value would cause
+   * size() > threshold. Note that the existing Entry objects are reused in
+   * the new hash table.
+   * <p>
+   *
+   * This is not specified, but the new size is twice the current size plus
+   * one; this number is not always prime, unfortunately. This implementation
+   * is not synchronized, as it is only invoked from synchronized methods.
+   */
+  protected void rehash()
+  {
+    HashEntry[] oldBuckets = buckets;
+
+    int newcapacity = (buckets.length * 2) + 1;
+    threshold = (int) (newcapacity * loadFactor);
+    buckets = new HashEntry[newcapacity];
+
+    for (int i = oldBuckets.length - 1; i >= 0; i--)
+      {
+        HashEntry e = oldBuckets[i];
+        while (e != null)
+          {
+            int idx = hash(e.key);
+            HashEntry dest = buckets[idx];
+
+            if (dest != null)
+              {
+                HashEntry next = dest.next;
+                while (next != null)
+                  {
+                    dest = next;
+                    next = dest.next;
+                  }
+                dest.next = e;
+              }
+            else
+              {
+                buckets[idx] = e;
+              }
+
+            HashEntry next = e.next;
+            e.next = null;
+            e = next;
+          }
+      }
+  }
+
+  /**
+   * Serializes this object to the given stream.
+   *
+   * @param s the stream to write to
+   * @throws IOException if the underlying stream fails
+   * @serialData the <i>capacity</i> (int) that is the length of the
+   *             bucket array, the <i>size</i> (int) of the hash map
+   *             are emitted first.  They are followed by size entries,
+   *             each consisting of a key (Object) and a value (Object).
+   */
+  private synchronized void writeObject(ObjectOutputStream s)
+    throws IOException
+  {
+    // Write the threshold and loadFactor fields.
+    s.defaultWriteObject();
+
+    s.writeInt(buckets.length);
+    s.writeInt(size);
+    // Since we are already synchronized, and entrySet().iterator()
+    // would repeatedly re-lock/release the monitor, we directly use the
+    // unsynchronized EntryIterator instead.
+    Iterator it = new EntryIterator();
+    while (it.hasNext())
+      {
+        HashEntry entry = (HashEntry) it.next();
+        s.writeObject(entry.key);
+        s.writeObject(entry.value);
+      }
+  }
+
+  /**
+   * Deserializes this object from the given stream.
+   *
+   * @param s the stream to read from
+   * @throws ClassNotFoundException if the underlying stream fails
+   * @throws IOException if the underlying stream fails
+   * @serialData the <i>capacity</i> (int) that is the length of the
+   *             bucket array, the <i>size</i> (int) of the hash map
+   *             are emitted first.  They are followed by size entries,
+   *             each consisting of a key (Object) and a value (Object).
+   */
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException
+  {
+    // Read the threshold and loadFactor fields.
+    s.defaultReadObject();
+
+    // Read and use capacity.
+    buckets = new HashEntry[s.readInt()];
+    int len = s.readInt();
+
+    // Read and use key/value pairs.
+    // TODO: should we be defensive programmers, and check for illegal nulls?
+    while (--len >= 0)
+      put(s.readObject(), s.readObject());
+  }
+
+  /**
+   * A class which implements the Iterator interface and is used for
+   * iterating over Hashtables.
+   * This implementation iterates entries. Subclasses are used to
+   * iterate key and values. It also allows the removal of elements,
+   * as per the Javasoft spec.  Note that it is not synchronized; this
+   * is a performance enhancer since it is never exposed externally
+   * and is only used within synchronized blocks above.
+   *
+   * @author Jon Zeppieri
+   * @author Fridjof Siebert
+   */
+  private class EntryIterator implements Iterator
+  {
+    /**
+     * The number of modifications to the backing Hashtable that we know about.
+     */
+    int knownMod = modCount;
+    /** The number of elements remaining to be returned by next(). */
+    int count = size;
+    /** Current index in the physical hash table. */
+    int idx = buckets.length;
+    /** The last Entry returned by a next() call. */
+    HashEntry last;
+    /**
+     * The next entry that should be returned by next(). It is set to something
+     * if we're iterating through a bucket that contains multiple linked
+     * entries. It is null if next() needs to find a new bucket.
+     */
+    HashEntry next;
+
+    /**
+     * Construct a new EtryIterator
+     */
+    EntryIterator()
+    {
+    }
+
+
+    /**
+     * Returns true if the Iterator has more elements.
+     * @return true if there are more elements
+     */
+    public boolean hasNext()
+    {
+      return count > 0;
+    }
+
+    /**
+     * Returns the next element in the Iterator's sequential view.
+     * @return the next element
+     * @throws ConcurrentModificationException if the hashtable was modified
+     * @throws NoSuchElementException if there is none
+     */
+    public Object next()
+    {
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+      if (count == 0)
+        throw new NoSuchElementException();
+      count--;
+      HashEntry e = next;
+
+      while (e == null)
+	if (idx <= 0)
+	  return null;
+	else
+	  e = buckets[--idx];
+
+      next = e.next;
+      last = e;
+      return e;
+    }
+
+    /**
+     * Removes from the backing Hashtable the last element which was fetched
+     * with the <code>next()</code> method.
+     * @throws ConcurrentModificationException if the hashtable was modified
+     * @throws IllegalStateException if called when there is no last element
+     */
+    public void remove()
+    {
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+      if (last == null)
+        throw new IllegalStateException();
+
+      Hashtable.this.remove(last.key);
+      last = null;
+      knownMod++;
+    }
+  } // class EntryIterator
+
+  /**
+   * A class which implements the Iterator interface and is used for
+   * iterating over keys in Hashtables.
+   *
+   * @author Fridtjof Siebert
+   */
+  private class KeyIterator extends EntryIterator
+  {
+    /**
+     * Returns the next element in the Iterator's sequential view.
+     *
+     * @return the next element
+     *
+     * @throws ConcurrentModificationException if the hashtable was modified
+     * @throws NoSuchElementException if there is none
+     */
+    public Object next()
+    {
+      return ((HashEntry)super.next()).key;
+    }
+  } // class KeyIterator
+
+
+
+  /**
+   * A class which implements the Iterator interface and is used for
+   * iterating over values in Hashtables.
+   *
+   * @author Fridtjof Siebert
+   */
+  private class ValueIterator extends EntryIterator
+  {
+    /**
+     * Returns the next element in the Iterator's sequential view.
+     *
+     * @return the next element
+     *
+     * @throws ConcurrentModificationException if the hashtable was modified
+     * @throws NoSuchElementException if there is none
+     */
+    public Object next()
+    {
+      return ((HashEntry)super.next()).value;
+    }
+  } // class ValueIterator
+
+  /**
+   * Enumeration view of the entries in this Hashtable, providing
+   * sequential access to its elements.
+   *
+   * <b>NOTE</b>: Enumeration is not safe if new elements are put in the table
+   * as this could cause a rehash and we'd completely lose our place.  Even
+   * without a rehash, it is undetermined if a new element added would
+   * appear in the enumeration.  The spec says nothing about this, but
+   * the "Java Class Libraries" book implies that modifications to the
+   * hashtable during enumeration causes indeterminate results.  Don't do it!
+   *
+   * @author Jon Zeppieri
+   * @author Fridjof Siebert
+   */
+  private class EntryEnumerator implements Enumeration
+  {
+    /** The number of elements remaining to be returned by next(). */
+    int count = size;
+    /** Current index in the physical hash table. */
+    int idx = buckets.length;
+    /**
+     * Entry which will be returned by the next nextElement() call. It is
+     * set if we are iterating through a bucket with multiple entries, or null
+     * if we must look in the next bucket.
+     */
+    HashEntry next;
+
+    /**
+     * Construct the enumeration.
+     */
+    EntryEnumerator()
+    {
+      // Nothing to do here.
+    }
+
+    /**
+     * Checks whether more elements remain in the enumeration.
+     * @return true if nextElement() will not fail.
+     */
+    public boolean hasMoreElements()
+    {
+      return count > 0;
+    }
+
+    /**
+     * Returns the next element.
+     * @return the next element
+     * @throws NoSuchElementException if there is none.
+     */
+    public Object nextElement()
+    {
+      if (count == 0)
+        throw new NoSuchElementException("Hashtable Enumerator");
+      count--;
+      HashEntry e = next;
+
+      while (e == null)
+        if (idx <= 0)
+          return null;
+        else
+          e = buckets[--idx];
+
+      next = e.next;
+      return e;
+    }
+  } // class EntryEnumerator
+
+
+  /**
+   * Enumeration view of this Hashtable, providing sequential access to its
+   * elements.
+   *
+   * <b>NOTE</b>: Enumeration is not safe if new elements are put in the table
+   * as this could cause a rehash and we'd completely lose our place.  Even
+   * without a rehash, it is undetermined if a new element added would
+   * appear in the enumeration.  The spec says nothing about this, but
+   * the "Java Class Libraries" book implies that modifications to the
+   * hashtable during enumeration causes indeterminate results.  Don't do it!
+   *
+   * @author Jon Zeppieri
+   * @author Fridjof Siebert
+   */
+  private final class KeyEnumerator extends EntryEnumerator
+  {
+    /**
+     * Returns the next element.
+     * @return the next element
+     * @throws NoSuchElementException if there is none.
+     */
+    public Object nextElement()
+    {
+      HashEntry entry = (HashEntry) super.nextElement();
+      Object retVal = null;
+      if (entry != null)
+        retVal = entry.key;
+      return retVal;
+    }
+  } // class KeyEnumerator
+
+
+  /**
+   * Enumeration view of this Hashtable, providing sequential access to its
+   * values.
+   *
+   * <b>NOTE</b>: Enumeration is not safe if new elements are put in the table
+   * as this could cause a rehash and we'd completely lose our place.  Even
+   * without a rehash, it is undetermined if a new element added would
+   * appear in the enumeration.  The spec says nothing about this, but
+   * the "Java Class Libraries" book implies that modifications to the
+   * hashtable during enumeration causes indeterminate results.  Don't do it!
+   *
+   * @author Jon Zeppieri
+   * @author Fridjof Siebert
+   */
+  private final class ValueEnumerator extends EntryEnumerator
+  {
+    /**
+     * Returns the next element.
+     * @return the next element
+     * @throws NoSuchElementException if there is none.
+     */
+    public Object nextElement()
+    {
+      HashEntry entry = (HashEntry) super.nextElement();
+      Object retVal = null;
+      if (entry != null)
+        retVal = entry.value;
+      return retVal;
+    }
+  } // class ValueEnumerator
+
+} // class Hashtable

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/IdentityHashMap.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/IdentityHashMap.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/IdentityHashMap.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/IdentityHashMap.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,932 @@
+/* IdentityHashMap.java -- a class providing a hashtable data structure,
+   mapping Object --> Object, which uses object identity for hashing.
+   Copyright (C) 2001, 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * This class provides a hashtable-backed implementation of the
+ * Map interface, but uses object identity to do its hashing.  In fact,
+ * it uses object identity for comparing values, as well. It uses a
+ * linear-probe hash table, which may have faster performance
+ * than the chaining employed by HashMap.
+ * <p>
+ *
+ * <em>WARNING: This is not a general purpose map. Because it uses
+ * System.identityHashCode and ==, instead of hashCode and equals, for
+ * comparison, it violated Map's general contract, and may cause
+ * undefined behavior when compared to other maps which are not
+ * IdentityHashMaps.  This is designed only for the rare cases when
+ * identity semantics are needed.</em> An example use is
+ * topology-preserving graph transformations, such as deep cloning,
+ * or as proxy object mapping such as in debugging.
+ * <p>
+ *
+ * This map permits <code>null</code> keys and values, and does not
+ * guarantee that elements will stay in the same order over time. The
+ * basic operations (<code>get</code> and <code>put</code>) take
+ * constant time, provided System.identityHashCode is decent. You can
+ * tune the behavior by specifying the expected maximum size. As more
+ * elements are added, the map may need to allocate a larger table,
+ * which can be expensive.
+ * <p>
+ *
+ * This implementation is unsynchronized.  If you want multi-thread
+ * access to be consistent, you must synchronize it, perhaps by using
+ * <code>Collections.synchronizedMap(new IdentityHashMap(...));</code>.
+ * The iterators are <i>fail-fast</i>, meaning that a structural modification
+ * made to the map outside of an iterator's remove method cause the
+ * iterator, and in the case of the entrySet, the Map.Entry, to
+ * fail with a {@link ConcurrentModificationException}.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see System#identityHashCode(Object)
+ * @see Collection
+ * @see Map
+ * @see HashMap
+ * @see TreeMap
+ * @see LinkedHashMap
+ * @see WeakHashMap
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class IdentityHashMap extends AbstractMap
+  implements Map, Serializable, Cloneable
+{
+  /** The default capacity. */
+  private static final int DEFAULT_CAPACITY = 21;
+
+  /**
+   * This object is used to mark deleted items. Package visible for use by
+   * nested classes.
+   */
+  static final Object tombstone = new Object();
+
+  /**
+   * This object is used to mark empty slots.  We need this because
+   * using null is ambiguous. Package visible for use by nested classes.
+   */
+  static final Object emptyslot = new Object();
+
+  /**
+   * Compatible with JDK 1.4.
+   */
+  private static final long serialVersionUID = 8188218128353913216L;
+
+  /**
+   * The number of mappings in the table. Package visible for use by nested
+   * classes.
+   * @serial
+   */
+  int size;
+
+  /**
+   * The table itself. Package visible for use by nested classes.
+   */
+  transient Object[] table;
+
+  /**
+   * The number of structural modifications made so far. Package visible for
+   * use by nested classes.
+   */
+  transient int modCount;
+
+  /**
+   * The cache for {@link #entrySet()}.
+   */
+  private transient Set entries;
+
+  /**
+   * The threshold for rehashing, which is 75% of (table.length / 2).
+   */
+  private transient int threshold;
+
+  /**
+   * Create a new IdentityHashMap with the default capacity (21 entries).
+   */
+  public IdentityHashMap()
+  {
+    this(DEFAULT_CAPACITY);
+  }
+
+  /**
+   * Create a new IdentityHashMap with the indicated number of
+   * entries.  If the number of elements added to this hash map
+   * exceeds this maximum, the map will grow itself; however, that
+   * incurs a performance penalty.
+   *
+   * @param max initial size
+   * @throws IllegalArgumentException if max is negative
+   */
+  public IdentityHashMap(int max)
+  {
+    if (max < 0)
+      throw new IllegalArgumentException();
+    // Need at least two slots, or hash() will break.
+    if (max < 2)
+      max = 2;
+    table = new Object[max << 1];
+    Arrays.fill(table, emptyslot);
+    threshold = (max >> 2) * 3;
+  }
+
+  /**
+   * Create a new IdentityHashMap whose contents are taken from the
+   * given Map.
+   *
+   * @param m The map whose elements are to be put in this map
+   * @throws NullPointerException if m is null
+   */
+  public IdentityHashMap(Map m)
+  {
+    this(Math.max(m.size() << 1, DEFAULT_CAPACITY));
+    putAll(m);
+  }
+
+  /**
+   * Remove all mappings from this map.
+   */
+  public void clear()
+  {
+    if (size != 0)
+      {
+        modCount++;
+        Arrays.fill(table, emptyslot);
+        size = 0;
+      }
+  }
+
+  /**
+   * Creates a shallow copy where keys and values are not cloned.
+   */
+  public Object clone()
+  {
+    try
+      {
+        IdentityHashMap copy = (IdentityHashMap) super.clone();
+        copy.table = (Object[]) table.clone();
+        copy.entries = null; // invalidate the cache
+        return copy;
+      }
+    catch (CloneNotSupportedException e)
+      {
+        // Can't happen.
+        return null;
+      }
+  }
+
+  /**
+   * Tests whether the specified key is in this map.  Unlike normal Maps,
+   * this test uses <code>entry == key</code> instead of
+   * <code>entry == null ? key == null : entry.equals(key)</code>.
+   *
+   * @param key the key to look for
+   * @return true if the key is contained in the map
+   * @see #containsValue(Object)
+   * @see #get(Object)
+   */
+  public boolean containsKey(Object key)
+  {
+    return key == table[hash(key)];
+  }
+
+  /**
+   * Returns true if this HashMap contains the value.  Unlike normal maps,
+   * this test uses <code>entry == value</code> instead of
+   * <code>entry == null ? value == null : entry.equals(value)</code>.
+   *
+   * @param value the value to search for in this HashMap
+   * @return true if at least one key maps to the value
+   * @see #containsKey(Object)
+   */
+  public boolean containsValue(Object value)
+  {
+    for (int i = table.length - 1; i > 0; i -= 2)
+      if (table[i] == value)
+        return true;
+    return false;
+  }
+
+  /**
+   * Returns a "set view" of this Map's entries. The set is backed by
+   * the Map, so changes in one show up in the other.  The set supports
+   * element removal, but not element addition.
+   * <p>
+   *
+   * <em>The semantics of this set, and of its contained entries, are
+   * different from the contract of Set and Map.Entry in order to make
+   * IdentityHashMap work.  This means that while you can compare these
+   * objects between IdentityHashMaps, comparing them with regular sets
+   * or entries is likely to have undefined behavior.</em>  The entries
+   * in this set are reference-based, rather than the normal object
+   * equality.  Therefore, <code>e1.equals(e2)</code> returns
+   * <code>e1.getKey() == e2.getKey() && e1.getValue() == e2.getValue()</code>,
+   * and <code>e.hashCode()</code> returns
+   * <code>System.identityHashCode(e.getKey()) ^
+   *       System.identityHashCode(e.getValue())</code>.
+   * <p>
+   *
+   * Note that the iterators for all three views, from keySet(), entrySet(),
+   * and values(), traverse the Map in the same sequence.
+   *
+   * @return a set view of the entries
+   * @see #keySet()
+   * @see #values()
+   * @see Map.Entry
+   */
+  public Set entrySet()
+  {
+    if (entries == null)
+      entries = new AbstractSet()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          return new IdentityIterator(ENTRIES);
+        }
+
+        public void clear()
+        {
+          IdentityHashMap.this.clear();
+        }
+
+        public boolean contains(Object o)
+        {
+          if (! (o instanceof Map.Entry))
+            return false;
+          Map.Entry m = (Map.Entry) o;
+          return m.getValue() == table[hash(m.getKey()) + 1];
+        }
+
+        public int hashCode()
+        {
+          return IdentityHashMap.this.hashCode();
+        }
+
+        public boolean remove(Object o)
+        {
+          if (! (o instanceof Map.Entry))
+            return false;
+          Object key = ((Map.Entry) o).getKey();
+          int h = hash(key);
+          if (table[h] == key)
+            {
+              size--;
+              modCount++;
+              table[h] = tombstone;
+              table[h + 1] = tombstone;
+              return true;
+            }
+          return false;
+        }
+      };
+    return entries;
+  }
+
+  /**
+   * Compares two maps for equality. This returns true only if both maps
+   * have the same reference-identity comparisons. While this returns
+   * <code>this.entrySet().equals(m.entrySet())</code> as specified by Map,
+   * this will not work with normal maps, since the entry set compares
+   * with == instead of .equals.
+   *
+   * @param o the object to compare to
+   * @return true if it is equal
+   */
+  public boolean equals(Object o)
+  {
+    // Why did Sun specify this one? The superclass does the right thing.
+    return super.equals(o);
+  }
+
+  /**
+   * Return the value in this Map associated with the supplied key, or
+   * <code>null</code> if the key maps to nothing.
+   *
+   * <p>NOTE: Since the value could also be null, you must use
+   * containsKey to see if this key actually maps to something.
+   * Unlike normal maps, this tests for the key with <code>entry ==
+   * key</code> instead of <code>entry == null ? key == null :
+   * entry.equals(key)</code>.
+   *
+   * @param key the key for which to fetch an associated value
+   * @return what the key maps to, if present
+   * @see #put(Object, Object)
+   * @see #containsKey(Object)
+   */
+  public Object get(Object key)
+  {
+    int h = hash(key);
+    return table[h] == key ? table[h + 1] : null;
+  }
+
+  /**
+   * Returns the hashcode of this map. This guarantees that two
+   * IdentityHashMaps that compare with equals() will have the same hash code,
+   * but may break with comparison to normal maps since it uses
+   * System.identityHashCode() instead of hashCode().
+   *
+   * @return the hash code
+   */
+  public int hashCode()
+  {
+    int hash = 0;
+    for (int i = table.length - 2; i >= 0; i -= 2)
+      {
+        Object key = table[i];
+        if (key == emptyslot || key == tombstone)
+          continue;
+        hash += (System.identityHashCode(key)
+                 ^ System.identityHashCode(table[i + 1]));
+      }
+    return hash;
+  }
+
+  /**
+   * Returns true if there are no key-value mappings currently in this Map
+   * @return <code>size() == 0</code>
+   */
+  public boolean isEmpty()
+  {
+    return size == 0;
+  }
+
+  /**
+   * Returns a "set view" of this Map's keys. The set is backed by the
+   * Map, so changes in one show up in the other.  The set supports
+   * element removal, but not element addition.
+   * <p>
+   *
+   * <em>The semantics of this set are different from the contract of Set
+   * in order to make IdentityHashMap work.  This means that while you can
+   * compare these objects between IdentityHashMaps, comparing them with
+   * regular sets is likely to have undefined behavior.</em>  The hashCode
+   * of the set is the sum of the identity hash codes, instead of the
+   * regular hashCodes, and equality is determined by reference instead
+   * of by the equals method.
+   * <p>
+   *
+   * @return a set view of the keys
+   * @see #values()
+   * @see #entrySet()
+   */
+  public Set keySet()
+  {
+    if (keys == null)
+      keys = new AbstractSet()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          return new IdentityIterator(KEYS);
+        }
+
+        public void clear()
+        {
+          IdentityHashMap.this.clear();
+        }
+
+        public boolean contains(Object o)
+        {
+          return containsKey(o);
+        }
+
+        public int hashCode()
+        {
+          int hash = 0;
+          for (int i = table.length - 2; i >= 0; i -= 2)
+            {
+              Object key = table[i];
+              if (key == emptyslot || key == tombstone)
+                continue;
+              hash += System.identityHashCode(key);
+            }
+          return hash;
+
+        }
+
+        public boolean remove(Object o)
+        {
+          int h = hash(o);
+          if (table[h] == o)
+            {
+              size--;
+              modCount++;
+              table[h] = tombstone;
+              table[h + 1] = tombstone;
+              return true;
+            }
+          return false;
+        }
+      };
+    return keys;
+  }
+
+  /**
+   * Puts the supplied value into the Map, mapped by the supplied key.
+   * The value may be retrieved by any object which <code>equals()</code>
+   * this key. NOTE: Since the prior value could also be null, you must
+   * first use containsKey if you want to see if you are replacing the
+   * key's mapping.  Unlike normal maps, this tests for the key
+   * with <code>entry == key</code> instead of
+   * <code>entry == null ? key == null : entry.equals(key)</code>.
+   *
+   * @param key the key used to locate the value
+   * @param value the value to be stored in the HashMap
+   * @return the prior mapping of the key, or null if there was none
+   * @see #get(Object)
+   */
+  public Object put(Object key, Object value)
+  {
+    // Rehash if the load factor is too high.
+    if (size > threshold)
+      {
+        Object[] old = table;
+        // This isn't necessarily prime, but it is an odd number of key/value
+        // slots, which has a higher probability of fewer collisions.
+        table = new Object[(old.length * 2) + 2];
+        Arrays.fill(table, emptyslot);
+        size = 0;
+        threshold = (table.length >>> 3) * 3;
+
+        for (int i = old.length - 2; i >= 0; i -= 2)
+          {
+            Object oldkey = old[i];
+            if (oldkey != tombstone && oldkey != emptyslot)
+              // Just use put.  This isn't very efficient, but it is ok.
+              put(oldkey, old[i + 1]);
+          }
+      }
+
+    int h = hash(key);
+    if (table[h] == key)
+      {
+        Object r = table[h + 1];
+        table[h + 1] = value;
+        return r;
+      }
+
+    // At this point, we add a new mapping.
+    modCount++;
+    size++;
+    table[h] = key;
+    table[h + 1] = value;
+    return null;
+  }
+
+  /**
+   * Copies all of the mappings from the specified map to this. If a key
+   * is already in this map, its value is replaced.
+   *
+   * @param m the map to copy
+   * @throws NullPointerException if m is null
+   */
+  public void putAll(Map m)
+  {
+    // Why did Sun specify this one? The superclass does the right thing.
+    super.putAll(m);
+  }
+
+  /**
+   * Removes from the HashMap and returns the value which is mapped by
+   * the supplied key. If the key maps to nothing, then the HashMap
+   * remains unchanged, and <code>null</code> is returned.
+   *
+   * NOTE: Since the value could also be null, you must use
+   * containsKey to see if you are actually removing a mapping.
+   * Unlike normal maps, this tests for the key with <code>entry ==
+   * key</code> instead of <code>entry == null ? key == null :
+   * entry.equals(key)</code>.
+   *
+   * @param key the key used to locate the value to remove
+   * @return whatever the key mapped to, if present
+   */
+  public Object remove(Object key)
+  {
+    int h = hash(key);
+    if (table[h] == key)
+      {
+        modCount++;
+        size--;
+        Object r = table[h + 1];
+        table[h] = tombstone;
+        table[h + 1] = tombstone;
+        return r;
+      }
+    return null;
+  }
+
+  /**
+   * Returns the number of kay-value mappings currently in this Map
+   * @return the size
+   */
+  public int size()
+  {
+    return size;
+  }
+
+  /**
+   * Returns a "collection view" (or "bag view") of this Map's values.
+   * The collection is backed by the Map, so changes in one show up
+   * in the other.  The collection supports element removal, but not element
+   * addition.
+   * <p>
+   *
+   * <em>The semantics of this set are different from the contract of
+   * Collection in order to make IdentityHashMap work.  This means that
+   * while you can compare these objects between IdentityHashMaps, comparing
+   * them with regular sets is likely to have undefined behavior.</em>
+   * Likewise, contains and remove go by == instead of equals().
+   * <p>
+   *
+   * @return a bag view of the values
+   * @see #keySet()
+   * @see #entrySet()
+   */
+  public Collection values()
+  {
+    if (values == null)
+      values = new AbstractCollection()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          return new IdentityIterator(VALUES);
+        }
+
+        public void clear()
+        {
+          IdentityHashMap.this.clear();
+        }
+
+        public boolean remove(Object o)
+        {
+          for (int i = table.length - 1; i > 0; i -= 2)
+            if (table[i] == o)
+              {
+                modCount++;
+                table[i - 1] = tombstone;
+                table[i] = tombstone;
+                size--;
+                return true;
+              }
+          return false;
+        }
+      };
+    return values;
+  }
+
+  /**
+   * Helper method which computes the hash code, then traverses the table
+   * until it finds the key, or the spot where the key would go.
+   *
+   * @param key the key to check
+   * @return the index where the key belongs
+   * @see #IdentityHashMap(int)
+   * @see #put(Object, Object)
+   */
+  // Package visible for use by nested classes.
+  int hash(Object key)
+  {
+    // Implementation note: it is feasible for the table to have no
+    // emptyslots, if it is full with entries and tombstones, so we must
+    // remember where we started. If we encounter the key or an emptyslot,
+    // we are done.  If we encounter a tombstone, the key may still be in
+    // the array.  If we don't encounter the key, we use the first emptyslot
+    // or tombstone we encountered as the location where the key would go.
+    // By requiring at least 2 key/value slots, and rehashing at 75%
+    // capacity, we guarantee that there will always be either an emptyslot
+    // or a tombstone somewhere in the table.
+    int h = Math.abs(System.identityHashCode(key) % (table.length >> 1)) << 1;
+    int del = -1;
+    int save = h;
+
+    do
+      {
+        if (table[h] == key)
+          return h;
+        if (table[h] == emptyslot)
+          break;
+        if (table[h] == tombstone && del < 0)
+          del = h;
+        h -= 2;
+        if (h < 0)
+          h = table.length - 2;
+      }
+    while (h != save);
+
+    return del < 0 ? h : del;
+  }
+
+  /**
+   * This class allows parameterized iteration over IdentityHashMaps.  Based
+   * on its construction, it returns the key or value of a mapping, or
+   * creates the appropriate Map.Entry object with the correct fail-fast
+   * semantics and identity comparisons.
+   *
+   * @author Tom Tromey (tromey at redhat.com)
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private class IdentityIterator implements Iterator
+  {
+    /**
+     * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
+     * or {@link #ENTRIES}.
+     */
+    final int type;
+    /** The number of modifications to the backing Map that we know about. */
+    int knownMod = modCount;
+    /** The number of elements remaining to be returned by next(). */
+    int count = size;
+    /** Location in the table. */
+    int loc = table.length;
+
+    /**
+     * Construct a new Iterator with the supplied type.
+     * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+     */
+    IdentityIterator(int type)
+    {
+      this.type = type;
+    }
+
+    /**
+     * Returns true if the Iterator has more elements.
+     * @return true if there are more elements
+     */
+    public boolean hasNext()
+    {
+      return count > 0;
+    }
+
+    /**
+     * Returns the next element in the Iterator's sequential view.
+     * @return the next element
+     * @throws ConcurrentModificationException if the Map was modified
+     * @throws NoSuchElementException if there is none
+     */
+    public Object next()
+    {
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+      if (count == 0)
+        throw new NoSuchElementException();
+      count--;
+
+      Object key;
+      do
+        {
+          loc -= 2;
+          key = table[loc];
+        }
+      while (key == emptyslot || key == tombstone);
+
+      return type == KEYS ? key : (type == VALUES ? table[loc + 1]
+                                   : new IdentityEntry(loc));
+    }
+
+    /**
+     * Removes from the backing Map the last element which was fetched
+     * with the <code>next()</code> method.
+     *
+     * @throws ConcurrentModificationException if the Map was modified
+     * @throws IllegalStateException if called when there is no last element
+     */
+    public void remove()
+    {
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+      if (loc == table.length || table[loc] == tombstone)
+        throw new IllegalStateException();
+      modCount++;
+      size--;
+      table[loc] = tombstone;
+      table[loc + 1] = tombstone;
+      knownMod++;
+    }
+  } // class IdentityIterator
+
+  /**
+   * This class provides Map.Entry objects for IdentityHashMaps.  The entry
+   * is fail-fast, and will throw a ConcurrentModificationException if
+   * the underlying map is modified, or if remove is called on the iterator
+   * that generated this object.  It is identity based, so it violates
+   * the general contract of Map.Entry, and is probably unsuitable for
+   * comparison to normal maps; but it works among other IdentityHashMaps.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private final class IdentityEntry implements Map.Entry
+  {
+    /** The location of this entry. */
+    final int loc;
+    /** The number of modifications to the backing Map that we know about. */
+    final int knownMod = modCount;
+
+    /**
+     * Constructs the Entry.
+     *
+     * @param loc the location of this entry in table
+     */
+    IdentityEntry(int loc)
+    {
+      this.loc = loc;
+    }
+
+    /**
+     * Compares the specified object with this entry, using identity
+     * semantics. Note that this can lead to undefined results with
+     * Entry objects created by normal maps.
+     *
+     * @param o the object to compare
+     * @return true if it is equal
+     * @throws ConcurrentModificationException if the entry was invalidated
+     *         by modifying the Map or calling Iterator.remove()
+     */
+    public boolean equals(Object o)
+    {
+      if (knownMod != modCount || table[loc] == tombstone)
+        throw new ConcurrentModificationException();
+      if (! (o instanceof Map.Entry))
+        return false;
+      Map.Entry e = (Map.Entry) o;
+      return table[loc] == e.getKey() && table[loc + 1] == e.getValue();
+    }
+
+    /**
+     * Returns the key of this entry.
+     *
+     * @return the key
+     * @throws ConcurrentModificationException if the entry was invalidated
+     *         by modifying the Map or calling Iterator.remove()
+     */
+    public Object getKey()
+    {
+      if (knownMod != modCount || table[loc] == tombstone)
+        throw new ConcurrentModificationException();
+      return table[loc];
+    }
+
+    /**
+     * Returns the value of this entry.
+     *
+     * @return the value
+     * @throws ConcurrentModificationException if the entry was invalidated
+     *         by modifying the Map or calling Iterator.remove()
+     */
+    public Object getValue()
+    {
+      if (knownMod != modCount || table[loc] == tombstone)
+        throw new ConcurrentModificationException();
+      return table[loc + 1];
+    }
+
+    /**
+     * Returns the hashcode of the entry, using identity semantics.
+     * Note that this can lead to undefined results with Entry objects
+     * created by normal maps.
+     *
+     * @return the hash code
+     * @throws ConcurrentModificationException if the entry was invalidated
+     *         by modifying the Map or calling Iterator.remove()
+     */
+    public int hashCode()
+    {
+      if (knownMod != modCount || table[loc] == tombstone)
+        throw new ConcurrentModificationException();
+      return (System.identityHashCode(table[loc])
+              ^ System.identityHashCode(table[loc + 1]));
+    }
+
+    /**
+     * Replaces the value of this mapping, and returns the old value.
+     *
+     * @param value the new value
+     * @return the old value
+     * @throws ConcurrentModificationException if the entry was invalidated
+     *         by modifying the Map or calling Iterator.remove()
+     */
+    public Object setValue(Object value)
+    {
+      if (knownMod != modCount || table[loc] == tombstone)
+        throw new ConcurrentModificationException();
+      Object r = table[loc + 1];
+      table[loc + 1] = value;
+      return r;
+    }
+
+    /**
+     * This provides a string representation of the entry. It is of the form
+     * "key=value", where string concatenation is used on key and value.
+     *
+     * @return the string representation
+     * @throws ConcurrentModificationException if the entry was invalidated
+     *         by modifying the Map or calling Iterator.remove()
+     */
+    public String toString()
+    {
+      if (knownMod != modCount || table[loc] == tombstone)
+        throw new ConcurrentModificationException();
+      return table[loc] + "=" + table[loc + 1];
+    }
+  } // class IdentityEntry
+
+  /**
+   * Reads the object from a serial stream.
+   *
+   * @param s the stream to read from
+   * @throws ClassNotFoundException if the underlying stream fails
+   * @throws IOException if the underlying stream fails
+   * @serialData expects the size (int), followed by that many key (Object)
+   *             and value (Object) pairs, with the pairs in no particular
+   *             order
+   */
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException
+  {
+    s.defaultReadObject();
+
+    int num = s.readInt();
+    table = new Object[Math.max(num << 1, DEFAULT_CAPACITY) << 1];
+    // Read key/value pairs.
+    while (--num >= 0)
+      put(s.readObject(), s.readObject());
+  }
+
+  /**
+   * Writes the object to a serial stream.
+   *
+   * @param s the stream to write to
+   * @throws IOException if the underlying stream fails
+   * @serialData outputs the size (int), followed by that many key (Object)
+   *             and value (Object) pairs, with the pairs in no particular
+   *             order
+   */
+  private void writeObject(ObjectOutputStream s)
+    throws IOException
+  {
+    s.defaultWriteObject();
+    s.writeInt(size);
+    for (int i = table.length - 2; i >= 0; i -= 2)
+      {
+        Object key = table[i];
+        if (key != tombstone && key != emptyslot)
+          {
+            s.writeObject(key);
+            s.writeObject(table[i + 1]);
+          }
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatCodePointException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatCodePointException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatCodePointException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatCodePointException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,85 @@
+/* IllegalFormatCodePointException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when a {@link Formatter} receives a character with an
+ * invalid Unicode codepoint, as defined by
+ * {@link Character#isValidCodePoint(int)}.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class IllegalFormatCodePointException 
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 19080630L;
+
+  /**
+   * The character which is an invalid Unicode code point.
+   *
+   * @serial the invalid character.
+   */
+  // Note: name fixed by serialization.
+  int c;
+
+  /**
+   * Constructs a new <code>IllegalFormatCodePointException</code>
+   * which specifies that the character, <code>c</code>, passed to
+   * a {@link Formatter} is an invalid Unicode code point.
+   *
+   * @param c the invalid character.
+   */
+  public IllegalFormatCodePointException(int c)
+  {
+    super("An invalid Unicode code point was supplied.");
+    this.c = c;
+  }
+
+  /**
+   * Returns the invalid character.
+   *
+   * @return the invalid character.
+   */
+  public int getCodePoint()
+  {
+    return c;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatConversionException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatConversionException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatConversionException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatConversionException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,110 @@
+/* IllegalFormatConversionException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when the type of an argument supplied to the
+ * {@link Formatter#format()} method of a {@link Formatter}
+ * does not match the conversion character specified for it.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class IllegalFormatConversionException 
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 17000126L;
+
+  /**
+   * The conversion character which doesn't match
+   * the type of the argument.
+   *
+   * @serial the conversion character.
+   */
+  // Note: name fixed by serialization.
+  char c;
+
+  /**
+   * The type of the mismatching argument.
+   *
+   * @serial the mismatching argument type.
+   */
+  // Note: name fixed by serialization.
+  Class arg;
+
+  /**
+   * Constructs a new <code>IllegalFormatConversionException</code>
+   * which specifies that the argument of type <code>arg</code> does
+   * not match the conversion character, <code>c</code>.
+   *
+   * @param c the conversion character.
+   * @param arg the type which doesn't match the conversion character.
+   * @throws NullPointerException if <code>arg</code> is null.
+   */
+  public IllegalFormatConversionException(char c, Class arg)
+  {
+    super("The type, " + arg + ", is invalid for the conversion character, " +
+	  c + ".");
+    if (arg == null)
+      throw new NullPointerException("The supplied type was null.");
+    this.c = c;
+    this.arg = arg;
+  }
+
+  /**
+   * Returns the conversion character.
+   *
+   * @return the conversion character.
+   */
+  public char getConversion()
+  {
+    return c;
+  }
+
+  /**
+   * Returns the type of the mismatched argument.
+   *
+   * @return the type of the mismatched argument.
+   */
+  public Class getArgumentClass()
+  {
+    return arg;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,75 @@
+/* IllegalFormatException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * A general exception thrown when a format string is supplied
+ * to a {@link Formatter} that contains either invalid syntax
+ * or a mismatch between the format specification and the
+ * supplied arguments.  This class is never instantiated;
+ * instead one of its subclasses is used to throw a more
+ * specific exception.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class IllegalFormatException 
+  extends IllegalArgumentException
+{
+  private static final long serialVersionUID = 18830826L;
+
+  /**
+   * Constructs a new <code>IllegalFormatException</code>.
+   */
+  IllegalFormatException()
+  {
+  }
+
+  /**
+   * Constructs a new <code>IllegalFormatException</code>
+   * with the specified message.
+   *
+   * @param msg the error message for this exception.
+   */
+  IllegalFormatException(String msg)
+  {
+    super(msg);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatFlagsException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatFlagsException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatFlagsException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatFlagsException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,86 @@
+/* IllegalFormatFlagsException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when the flags supplied to the {@link Formatter#format()}
+ * method of a {@link Formatter} form an illegal combination.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class IllegalFormatFlagsException 
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 790824L;
+
+  /**
+   * The set of flags which forms an illegal combination.
+   *
+   * @serial the illegal set of flags.
+   */
+  // Note: name fixed by serialization.
+  private String flags;
+
+  /**
+   * Constructs a new <code>IllegalFormatFlagsException</code>
+   * for the specified flags.
+   *
+   * @param flags the illegal set of flags.
+   * @throws NullPointerException if <code>flags</code> is null.
+   */
+  public IllegalFormatFlagsException(String flags)
+  {
+    super("An illegal set of flags, " + flags + ", was supplied.");
+    if (flags == null)
+      throw new NullPointerException("The supplied flags are null.");
+    this.flags = flags;
+  }
+
+  /**
+   * Returns the illegal flags.
+   *
+   * @return the illegal flags.
+   */
+  public String getFlags()
+  {
+    return flags;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatPrecisionException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatPrecisionException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatPrecisionException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatPrecisionException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,85 @@
+/* IllegalFormatPrecisionException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when the specified precision for a {@link Formatter}
+ * argument is illegal.  This may be because the number is
+ * a negative number (other than -1), the argument does not
+ * accept a precision or for some other reason.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class IllegalFormatPrecisionException 
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 18711008L;
+
+  /**
+   * The illegal precision value.
+   *
+   * @serial the illegal precision.
+   */
+  // Note: name fixed by serialization.
+  private int p;
+
+  /**
+   * Constructs a new <code>IllegalFormatPrecisionException</code>
+   * for the precision, <code>p</code>.
+   *
+   * @param p the illegal precision.
+   */
+  public IllegalFormatPrecisionException(int p)
+  {
+    super("The precision, " + p + ", is illegal.");
+    this.p = p;
+  }
+
+  /**
+   * Returns the illegal precision.
+   *
+   * @return the illegal precision.
+   */
+  public int getPrecision()
+  {
+    return p;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatWidthException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatWidthException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatWidthException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/IllegalFormatWidthException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,84 @@
+/* IllegalFormatWidthException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when the specified width for a {@link Formatter}
+ * argument is illegal.  This may be because the number is
+ * a negative number (other than -1) or for some other reason.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class IllegalFormatWidthException 
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 16660902L;
+
+  /**
+   * The illegal width value.
+   *
+   * @serial the illegal width.
+   */
+  // Note: name fixed by serialization.
+  private int w;
+
+  /**
+   * Constructs a new <code>IllegalFormatWidthException</code>
+   * with the specified width, <code>w</code>.
+   *
+   * @param w the illegal width.
+   */
+  public IllegalFormatWidthException(int w)
+  {
+    super("The width, " + w + ", is illegal.");
+    this.w = w;
+  }
+
+  /**
+   * Returns the illegal width.
+   *
+   * @return the illegal width.
+   */
+  public int getWidth()
+  {
+    return w;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/InputMismatchException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/InputMismatchException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/InputMismatchException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/InputMismatchException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,73 @@
+/* InputMismatchException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when a {@link Scanner} instance encounters a mismatch
+ * between the input data and the pattern it is trying to match it
+ * against.  This could be because the input data represents an
+ * out-of-range value for the type the pattern represents, or simply
+ * because the data does not fit that particular type.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class InputMismatchException 
+  extends NoSuchElementException
+{
+  /**
+   * Constructs a new <code>InputMismatchException</code>
+   * with a <code>null</code> message.
+   */
+  public InputMismatchException()
+  {
+  }
+
+  /**
+   * Constructs a new <code>InputMismatchException</code>
+   * with the supplied error message.
+   *
+   * @param s the error message to report back to the user.
+   */
+  public InputMismatchException(String s)
+  {
+    super(s);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/InvalidPropertiesFormatException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/InvalidPropertiesFormatException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/InvalidPropertiesFormatException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/InvalidPropertiesFormatException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,72 @@
+/* InvalidPropertiesFormatException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/** @since 1.5 */
+public class InvalidPropertiesFormatException extends IOException
+{
+  // This class won't serialize, but we have a UID to placate the compiler.
+  private static final long serialVersionUID = 7763056076009360219L;
+
+  public InvalidPropertiesFormatException(String message)
+  {
+    super(message);
+  }
+
+  public InvalidPropertiesFormatException(Throwable cause)
+  {
+    super();
+    initCause(cause);
+  }
+
+  private void writeObject(ObjectOutputStream out) throws IOException
+  {
+    throw new NotSerializableException("objects of this type are not serializable");
+  }
+
+  private void readObject(ObjectInputStream in) throws IOException
+  {
+    throw new NotSerializableException("objects of this type are not serializable");
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Iterator.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Iterator.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Iterator.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Iterator.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,87 @@
+/* Iterator.java -- Interface for iterating over collections
+   Copyright (C) 1998, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An object which iterates over a collection. An Iterator is used to return
+ * the items once only, in sequence, by successive calls to the next method.
+ * It is also possible to remove elements from the underlying collection by
+ * using the optional remove method. Iterator is intended as a replacement
+ * for the Enumeration interface of previous versions of Java, which did not
+ * have the remove method and had less conveniently named methods.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Collection
+ * @see ListIterator
+ * @see Enumeration
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Iterator
+{
+  /**
+   * Tests whether there are elements remaining in the collection. In other
+   * words, calling <code>next()</code> will not throw an exception.
+   *
+   * @return true if there is at least one more element in the collection
+   */
+  boolean hasNext();
+
+  /**
+   * Obtain the next element in the collection.
+   *
+   * @return the next element in the collection
+   * @throws NoSuchElementException if there are no more elements
+   */
+  Object next();
+
+  /**
+   * Remove from the underlying collection the last element returned by next
+   * (optional operation). This method can be called only once after each
+   * call to <code>next()</code>. It does not affect what will be returned
+   * by subsequent calls to next.
+   *
+   * @throws IllegalStateException if next has not yet been called or remove
+   *         has already been called since the last call to next.
+   * @throws UnsupportedOperationException if this Iterator does not support
+   *         the remove operation.
+   */
+  void remove();
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedHashMap.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedHashMap.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedHashMap.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedHashMap.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,498 @@
+/* LinkedHashMap.java -- a class providing hashtable data structure,
+   mapping Object --> Object, with linked list traversal
+   Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This class provides a hashtable-backed implementation of the
+ * Map interface, with predictable traversal order.
+ * <p>
+ *
+ * It uses a hash-bucket approach; that is, hash collisions are handled
+ * by linking the new node off of the pre-existing node (or list of
+ * nodes).  In this manner, techniques such as linear probing (which
+ * can cause primary clustering) and rehashing (which does not fit very
+ * well with Java's method of precomputing hash codes) are avoided.  In
+ * addition, this maintains a doubly-linked list which tracks either
+ * insertion or access order.
+ * <p>
+ *
+ * In insertion order, calling <code>put</code> adds the key to the end of
+ * traversal, unless the key was already in the map; changing traversal order
+ * requires removing and reinserting a key.  On the other hand, in access
+ * order, all calls to <code>put</code> and <code>get</code> cause the
+ * accessed key to move to the end of the traversal list.  Note that any
+ * accesses to the map's contents via its collection views and iterators do
+ * not affect the map's traversal order, since the collection views do not
+ * call <code>put</code> or <code>get</code>.
+ * <p>
+ *
+ * One of the nice features of tracking insertion order is that you can
+ * copy a hashtable, and regardless of the implementation of the original,
+ * produce the same results when iterating over the copy.  This is possible
+ * without needing the overhead of <code>TreeMap</code>.
+ * <p>
+ *
+ * When using this {@link #LinkedHashMap(int, float, boolean) constructor},
+ * you can build an access-order mapping.  This can be used to implement LRU
+ * caches, for example.  By overriding {@link #removeEldestEntry(Map.Entry)},
+ * you can also control the removal of the oldest entry, and thereby do
+ * things like keep the map at a fixed size.
+ * <p>
+ *
+ * Under ideal circumstances (no collisions), LinkedHashMap offers O(1) 
+ * performance on most operations (<code>containsValue()</code> is,
+ * of course, O(n)).  In the worst case (all keys map to the same 
+ * hash code -- very unlikely), most operations are O(n).  Traversal is
+ * faster than in HashMap (proportional to the map size, and not the space
+ * allocated for the map), but other operations may be slower because of the
+ * overhead of the maintaining the traversal order list.
+ * <p>
+ *
+ * LinkedHashMap accepts the null key and null values.  It is not
+ * synchronized, so if you need multi-threaded access, consider using:<br>
+ * <code>Map m = Collections.synchronizedMap(new LinkedHashMap(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Object#hashCode()
+ * @see Collection
+ * @see Map
+ * @see HashMap
+ * @see TreeMap
+ * @see Hashtable
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class LinkedHashMap extends HashMap
+{
+  /**
+   * Compatible with JDK 1.4.
+   */
+  private static final long serialVersionUID = 3801124242820219131L;
+
+  /**
+   * The oldest Entry to begin iteration at.
+   */
+  transient LinkedHashEntry root;
+
+  /**
+   * The iteration order of this linked hash map: <code>true</code> for
+   * access-order, <code>false</code> for insertion-order.
+   *
+   * @serial true for access order traversal
+   */
+  final boolean accessOrder;
+
+  /**
+   * Class to represent an entry in the hash table. Holds a single key-value
+   * pair and the doubly-linked insertion order list.
+   */
+  class LinkedHashEntry extends HashEntry
+  {
+    /**
+     * The predecessor in the iteration list. If this entry is the root
+     * (eldest), pred points to the newest entry.
+     */
+    LinkedHashEntry pred;
+
+    /** The successor in the iteration list, null if this is the newest. */
+    LinkedHashEntry succ;
+
+    /**
+     * Simple constructor.
+     *
+     * @param key the key
+     * @param value the value
+     */
+    LinkedHashEntry(Object key, Object value)
+    {
+      super(key, value);
+      if (root == null)
+        {
+          root = this;
+          pred = this;
+        }
+      else
+        {
+          pred = root.pred;
+          pred.succ = this;
+          root.pred = this;
+        }
+    }
+
+    /**
+     * Called when this entry is accessed via put or get. This version does
+     * the necessary bookkeeping to keep the doubly-linked list in order,
+     * after moving this element to the newest position in access order.
+     */
+    void access()
+    {
+      if (accessOrder && succ != null)
+        {
+          modCount++;
+          if (this == root)
+            {
+              root = succ;
+              pred.succ = this;
+              succ = null;
+            }
+          else
+            {
+              pred.succ = succ;
+              succ.pred = pred;
+              succ = null;
+              pred = root.pred;
+              pred.succ = this;
+              root.pred = this;
+            }
+        }
+    }
+
+    /**
+     * Called when this entry is removed from the map. This version does
+     * the necessary bookkeeping to keep the doubly-linked list in order.
+     *
+     * @return the value of this key as it is removed
+     */
+    Object cleanup()
+    {
+      if (this == root)
+        {
+          root = succ;
+          if (succ != null)
+            succ.pred = pred;
+        }
+      else if (succ == null)
+        {
+          pred.succ = null;
+          root.pred = pred;
+        }
+      else
+        {
+          pred.succ = succ;
+          succ.pred = pred;
+        }
+      return value;
+    }
+  } // class LinkedHashEntry
+
+  /**
+   * Construct a new insertion-ordered LinkedHashMap with the default
+   * capacity (11) and the default load factor (0.75).
+   */
+  public LinkedHashMap()
+  {
+    super();
+    accessOrder = false;
+  }
+
+  /**
+   * Construct a new insertion-ordered LinkedHashMap from the given Map,
+   * with initial capacity the greater of the size of <code>m</code> or
+   * the default of 11.
+   * <p>
+   *
+   * Every element in Map m will be put into this new HashMap, in the
+   * order of m's iterator.
+   *
+   * @param m a Map whose key / value pairs will be put into
+   *          the new HashMap.  <b>NOTE: key / value pairs
+   *          are not cloned in this constructor.</b>
+   * @throws NullPointerException if m is null
+   */
+  public LinkedHashMap(Map m)
+  {
+    super(m);
+    accessOrder = false;
+  }
+
+  /**
+   * Construct a new insertion-ordered LinkedHashMap with a specific
+   * inital capacity and default load factor of 0.75.
+   *
+   * @param initialCapacity the initial capacity of this HashMap (>= 0)
+   * @throws IllegalArgumentException if (initialCapacity < 0)
+   */
+  public LinkedHashMap(int initialCapacity)
+  {
+    super(initialCapacity);
+    accessOrder = false;
+  }
+
+  /**
+   * Construct a new insertion-orderd LinkedHashMap with a specific
+   * inital capacity and load factor.
+   *
+   * @param initialCapacity the initial capacity (>= 0)
+   * @param loadFactor the load factor (> 0, not NaN)
+   * @throws IllegalArgumentException if (initialCapacity < 0) ||
+   *                                     ! (loadFactor > 0.0)
+   */
+  public LinkedHashMap(int initialCapacity, float loadFactor)
+  {
+    super(initialCapacity, loadFactor);
+    accessOrder = false;
+  }
+
+  /**
+   * Construct a new LinkedHashMap with a specific inital capacity, load
+   * factor, and ordering mode.
+   *
+   * @param initialCapacity the initial capacity (>=0)
+   * @param loadFactor the load factor (>0, not NaN)
+   * @param accessOrder true for access-order, false for insertion-order
+   * @throws IllegalArgumentException if (initialCapacity < 0) ||
+   *                                     ! (loadFactor > 0.0)
+   */
+  public LinkedHashMap(int initialCapacity, float loadFactor,
+                       boolean accessOrder)
+  {
+    super(initialCapacity, loadFactor);
+    this.accessOrder = accessOrder;
+  }
+
+  /**
+   * Clears the Map so it has no keys. This is O(1).
+   */
+  public void clear()
+  {
+    super.clear();
+    root = null;
+  }
+
+  /**
+   * Returns <code>true</code> if this HashMap contains a value
+   * <code>o</code>, such that <code>o.equals(value)</code>.
+   *
+   * @param value the value to search for in this HashMap
+   * @return <code>true</code> if at least one key maps to the value
+   */
+  public boolean containsValue(Object value)
+  {
+    LinkedHashEntry e = root;
+    while (e != null)
+      {
+        if (equals(value, e.value))
+          return true;
+        e = e.succ;
+      }
+    return false;
+  }
+
+  /**
+   * Return the value in this Map associated with the supplied key,
+   * or <code>null</code> if the key maps to nothing.  If this is an
+   * access-ordered Map and the key is found, this performs structural
+   * modification, moving the key to the newest end of the list. NOTE:
+   * Since the value could also be null, you must use containsKey to
+   * see if this key actually maps to something.
+   *
+   * @param key the key for which to fetch an associated value
+   * @return what the key maps to, if present
+   * @see #put(Object, Object)
+   * @see #containsKey(Object)
+   */
+  public Object get(Object key)
+  {
+    int idx = hash(key);
+    HashEntry e = buckets[idx];
+    while (e != null)
+      {
+        if (equals(key, e.key))
+          {
+            e.access();
+            return e.value;
+          }
+        e = e.next;
+      }
+    return null;
+  }
+
+  /**
+   * Returns <code>true</code> if this map should remove the eldest entry.
+   * This method is invoked by all calls to <code>put</code> and
+   * <code>putAll</code> which place a new entry in the map, providing
+   * the implementer an opportunity to remove the eldest entry any time
+   * a new one is added.  This can be used to save memory usage of the
+   * hashtable, as well as emulating a cache, by deleting stale entries.
+   * <p>
+   *
+   * For example, to keep the Map limited to 100 entries, override as follows:
+   * <pre>
+   * private static final int MAX_ENTRIES = 100;
+   * protected boolean removeEldestEntry(Map.Entry eldest)
+   * {
+   *   return size() > MAX_ENTRIES;
+   * }
+   * </pre><p>
+   *
+   * Typically, this method does not modify the map, but just uses the
+   * return value as an indication to <code>put</code> whether to proceed.
+   * However, if you override it to modify the map, you must return false
+   * (indicating that <code>put</code> should leave the modified map alone),
+   * or you face unspecified behavior.  Remember that in access-order mode,
+   * even calling <code>get</code> is a structural modification, but using
+   * the collections views (such as <code>keySet</code>) is not.
+   * <p>
+   *
+   * This method is called after the eldest entry has been inserted, so
+   * if <code>put</code> was called on a previously empty map, the eldest
+   * entry is the one you just put in! The default implementation just
+   * returns <code>false</code>, so that this map always behaves like
+   * a normal one with unbounded growth.
+   *
+   * @param eldest the eldest element which would be removed if this
+   *        returns true. For an access-order map, this is the least
+   *        recently accessed; for an insertion-order map, this is the
+   *        earliest element inserted.
+   * @return true if <code>eldest</code> should be removed
+   */
+  protected boolean removeEldestEntry(Map.Entry eldest)
+  {
+    return false;
+  }
+
+  /**
+   * Helper method called by <code>put</code>, which creates and adds a
+   * new Entry, followed by performing bookkeeping (like removeEldestEntry).
+   *
+   * @param key the key of the new Entry
+   * @param value the value
+   * @param idx the index in buckets where the new Entry belongs
+   * @param callRemove whether to call the removeEldestEntry method
+   * @see #put(Object, Object)
+   * @see #removeEldestEntry(Map.Entry)
+   * @see LinkedHashEntry#LinkedHashEntry(Object, Object)
+   */
+  void addEntry(Object key, Object value, int idx, boolean callRemove)
+  {
+    LinkedHashEntry e = new LinkedHashEntry(key, value);
+    e.next = buckets[idx];
+    buckets[idx] = e;
+    if (callRemove && removeEldestEntry(root))
+      remove(root.key);
+  }
+
+  /**
+   * Helper method, called by clone() to reset the doubly-linked list.
+   *
+   * @param m the map to add entries from
+   * @see #clone()
+   */
+  void putAllInternal(Map m)
+  {
+    root = null;
+    super.putAllInternal(m);
+  }
+
+  /**
+   * Generates a parameterized iterator. This allows traversal to follow
+   * the doubly-linked list instead of the random bin order of HashMap.
+   *
+   * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+   * @return the appropriate iterator
+   */
+  Iterator iterator(final int type)
+  {
+    return new Iterator()
+    {
+      /** The current Entry. */
+      LinkedHashEntry current = root;
+
+      /** The previous Entry returned by next(). */
+      LinkedHashEntry last;
+
+      /** The number of known modifications to the backing Map. */
+      int knownMod = modCount;
+
+      /**
+       * Returns true if the Iterator has more elements.
+       *
+       * @return true if there are more elements
+       */
+      public boolean hasNext()
+      {
+        return current != null;
+      }
+
+      /**
+       * Returns the next element in the Iterator's sequential view.
+       *
+       * @return the next element
+       * @throws ConcurrentModificationException if the HashMap was modified
+       * @throws NoSuchElementException if there is none
+       */
+      public Object next()
+      {
+        if (knownMod != modCount)
+          throw new ConcurrentModificationException();
+        if (current == null)
+          throw new NoSuchElementException();
+        last = current;
+        current = current.succ;
+        return type == VALUES ? last.value : type == KEYS ? last.key : last;
+      }
+      
+      /**
+       * Removes from the backing HashMap the last element which was fetched
+       * with the <code>next()</code> method.
+       *
+       * @throws ConcurrentModificationException if the HashMap was modified
+       * @throws IllegalStateException if called when there is no last element
+       */
+      public void remove()
+      {
+        if (knownMod != modCount)
+          throw new ConcurrentModificationException();
+        if (last == null)
+          throw new IllegalStateException();
+        LinkedHashMap.this.remove(last.key);
+        last = null;
+        knownMod++;
+      }
+    };
+  }
+} // class LinkedHashMap

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedHashSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedHashSet.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedHashSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedHashSet.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,160 @@
+/* LinkedHashSet.java -- a set backed by a LinkedHashMap, for linked
+   list traversal.
+   Copyright (C) 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * This class provides a hashtable-backed implementation of the
+ * Set interface, with predictable traversal order.
+ * <p>
+ *
+ * It uses a hash-bucket approach; that is, hash collisions are handled
+ * by linking the new node off of the pre-existing node (or list of
+ * nodes).  In this manner, techniques such as linear probing (which
+ * can cause primary clustering) and rehashing (which does not fit very
+ * well with Java's method of precomputing hash codes) are avoided.  In
+ * addition, this maintains a doubly-linked list which tracks insertion
+ * order.  Note that the insertion order is not modified if an
+ * <code>add</code> simply reinserts an element in the set.
+ * <p>
+ *
+ * One of the nice features of tracking insertion order is that you can
+ * copy a set, and regardless of the implementation of the original,
+ * produce the same results when iterating over the copy.  This is possible
+ * without needing the overhead of <code>TreeSet</code>.
+ * <p>
+ *
+ * Under ideal circumstances (no collisions), LinkedHashSet offers O(1) 
+ * performance on most operations.  In the worst case (all elements map
+ * to the same hash code -- very unlikely), most operations are O(n).
+ * <p>
+ *
+ * LinkedHashSet accepts the null entry.  It is not synchronized, so if
+ * you need multi-threaded access, consider using:<br>
+ * <code>Set s = Collections.synchronizedSet(new LinkedHashSet(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Object#hashCode()
+ * @see Collection
+ * @see Set
+ * @see HashSet
+ * @see TreeSet
+ * @see Collections#synchronizedSet(Set)
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public class LinkedHashSet extends HashSet
+  implements Set, Cloneable, Serializable
+{
+  /**
+   * Compatible with JDK 1.4.
+   */
+  private static final long serialVersionUID = -2851667679971038690L;
+
+  /**
+   * Construct a new, empty HashSet whose backing HashMap has the default
+   * capacity (11) and loadFacor (0.75).
+   */
+  public LinkedHashSet()
+  {
+    super();
+  }
+
+  /**
+   * Construct a new, empty HashSet whose backing HashMap has the supplied
+   * capacity and the default load factor (0.75).
+   *
+   * @param initialCapacity the initial capacity of the backing HashMap
+   * @throws IllegalArgumentException if the capacity is negative
+   */
+  public LinkedHashSet(int initialCapacity)
+  {
+    super(initialCapacity);
+  }
+
+  /**
+   * Construct a new, empty HashSet whose backing HashMap has the supplied
+   * capacity and load factor.
+   *
+   * @param initialCapacity the initial capacity of the backing HashMap
+   * @param loadFactor the load factor of the backing HashMap
+   * @throws IllegalArgumentException if either argument is negative, or
+   *         if loadFactor is POSITIVE_INFINITY or NaN
+   */
+  public LinkedHashSet(int initialCapacity, float loadFactor)
+  {
+    super(initialCapacity, loadFactor);
+  }
+
+  /**
+   * Construct a new HashSet with the same elements as are in the supplied
+   * collection (eliminating any duplicates, of course). The backing storage
+   * has twice the size of the collection, or the default size of 11,
+   * whichever is greater; and the default load factor (0.75).
+   *
+   * @param c a collection of initial set elements
+   * @throws NullPointerException if c is null
+   */
+  public LinkedHashSet(Collection c)
+  {
+    super(c);
+  }
+
+  /**
+   * Helper method which initializes the backing Map.
+   *
+   * @param capacity the initial capacity
+   * @param load the initial load factor
+   * @return the backing HashMap
+   */
+  HashMap init(int capacity, float load)
+  {
+    return new LinkedHashMap(capacity, load);
+  }
+
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedList.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedList.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedList.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/LinkedList.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,950 @@
+/* LinkedList.java -- Linked list implementation of the List interface
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+
+/**
+ * Linked list implementation of the List interface. In addition to the
+ * methods of the List interface, this class provides access to the first
+ * and last list elements in O(1) time for easy stack, queue, or double-ended
+ * queue (deque) creation. The list is doubly-linked, with traversal to a
+ * given index starting from the end closest to the element.<p>
+ *
+ * LinkedList is not synchronized, so if you need multi-threaded access,
+ * consider using:<br>
+ * <code>List l = Collections.synchronizedList(new LinkedList(...));</code>
+ * <p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * {@link ConcurrentModificationException} rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Original author unknown
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see List
+ * @see ArrayList
+ * @see Vector
+ * @see Collections#synchronizedList(List)
+ * @since 1.2
+ * @status missing javadoc, but complete to 1.4
+ */
+public class LinkedList extends AbstractSequentialList
+  implements List, Cloneable, Serializable
+{
+  /**
+   * Compatible with JDK 1.2.
+   */
+  private static final long serialVersionUID = 876323262645176354L;
+
+  /**
+   * The first element in the list.
+   */
+  transient Entry first;
+
+  /**
+   * The last element in the list.
+   */
+  transient Entry last;
+
+  /**
+   * The current length of the list.
+   */
+  transient int size = 0;
+
+  /**
+   * Class to represent an entry in the list. Holds a single element.
+   */
+  private static final class Entry
+  {
+    /** The element in the list. */
+    Object data;
+
+    /** The next list entry, null if this is last. */
+    Entry next;
+
+    /** The previous list entry, null if this is first. */
+    Entry previous;
+
+    /**
+     * Construct an entry.
+     * @param data the list element
+     */
+    Entry(Object data)
+    {
+      this.data = data;
+    }
+  } // class Entry
+
+  /**
+   * Obtain the Entry at a given position in a list. This method of course
+   * takes linear time, but it is intelligent enough to take the shorter of the
+   * paths to get to the Entry required. This implies that the first or last
+   * entry in the list is obtained in constant time, which is a very desirable
+   * property.
+   * For speed and flexibility, range checking is not done in this method:
+   * Incorrect values will be returned if (n < 0) or (n >= size).
+   *
+   * @param n the number of the entry to get
+   * @return the entry at position n
+   */
+  // Package visible for use in nested classes.
+  Entry getEntry(int n)
+  {
+    Entry e;
+    if (n < size / 2)
+      {
+        e = first;
+        // n less than size/2, iterate from start
+        while (n-- > 0)
+          e = e.next;
+      }
+    else
+      {
+        e = last;
+        // n greater than size/2, iterate from end
+        while (++n < size)
+          e = e.previous;
+      }
+    return e;
+  }
+
+  /**
+   * Remove an entry from the list. This will adjust size and deal with
+   *  `first' and  `last' appropriatly.
+   *
+   * @param e the entry to remove
+   */
+  // Package visible for use in nested classes.
+  void removeEntry(Entry e)
+  {
+    modCount++;
+    size--;
+    if (size == 0)
+      first = last = null;
+    else
+      {
+        if (e == first)
+          {
+            first = e.next;
+            e.next.previous = null;
+          }
+        else if (e == last)
+          {
+            last = e.previous;
+            e.previous.next = null;
+          }
+        else
+          {
+            e.next.previous = e.previous;
+            e.previous.next = e.next;
+          }
+      }
+  }
+
+  /**
+   * Checks that the index is in the range of possible elements (inclusive).
+   *
+   * @param index the index to check
+   * @throws IndexOutOfBoundsException if index < 0 || index > size
+   */
+  private void checkBoundsInclusive(int index)
+  {
+    if (index < 0 || index > size)
+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+                                          + size);
+  }
+
+  /**
+   * Checks that the index is in the range of existing elements (exclusive).
+   *
+   * @param index the index to check
+   * @throws IndexOutOfBoundsException if index < 0 || index >= size
+   */
+  private void checkBoundsExclusive(int index)
+  {
+    if (index < 0 || index >= size)
+      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+                                          + size);
+  }
+
+  /**
+   * Create an empty linked list.
+   */
+  public LinkedList()
+  {
+  }
+
+  /**
+   * Create a linked list containing the elements, in order, of a given
+   * collection.
+   *
+   * @param c the collection to populate this list from
+   * @throws NullPointerException if c is null
+   */
+  public LinkedList(Collection c)
+  {
+    addAll(c);
+  }
+
+  /**
+   * Returns the first element in the list.
+   *
+   * @return the first list element
+   * @throws NoSuchElementException if the list is empty
+   */
+  public Object getFirst()
+  {
+    if (size == 0)
+      throw new NoSuchElementException();
+    return first.data;
+  }
+
+  /**
+   * Returns the last element in the list.
+   *
+   * @return the last list element
+   * @throws NoSuchElementException if the list is empty
+   */
+  public Object getLast()
+  {
+    if (size == 0)
+      throw new NoSuchElementException();
+    return last.data;
+  }
+
+  /**
+   * Remove and return the first element in the list.
+   *
+   * @return the former first element in the list
+   * @throws NoSuchElementException if the list is empty
+   */
+  public Object removeFirst()
+  {
+    if (size == 0)
+      throw new NoSuchElementException();
+    modCount++;
+    size--;
+    Object r = first.data;
+
+    if (first.next != null)
+      first.next.previous = null;
+    else
+      last = null;
+
+    first = first.next;
+
+    return r;
+  }
+
+  /**
+   * Remove and return the last element in the list.
+   *
+   * @return the former last element in the list
+   * @throws NoSuchElementException if the list is empty
+   */
+  public Object removeLast()
+  {
+    if (size == 0)
+      throw new NoSuchElementException();
+    modCount++;
+    size--;
+    Object r = last.data;
+
+    if (last.previous != null)
+      last.previous.next = null;
+    else
+      first = null;
+
+    last = last.previous;
+
+    return r;
+  }
+
+  /**
+   * Insert an element at the first of the list.
+   *
+   * @param o the element to insert
+   */
+  public void addFirst(Object o)
+  {
+    Entry e = new Entry(o);
+
+    modCount++;
+    if (size == 0)
+      first = last = e;
+    else
+      {
+        e.next = first;
+        first.previous = e;
+        first = e;
+      }
+    size++;
+  }
+
+  /**
+   * Insert an element at the last of the list.
+   *
+   * @param o the element to insert
+   */
+  public void addLast(Object o)
+  {
+    addLastEntry(new Entry(o));
+  }
+
+  /**
+   * Inserts an element at the end of the list.
+   *
+   * @param e the entry to add
+   */
+  private void addLastEntry(Entry e)
+  {
+    modCount++;
+    if (size == 0)
+      first = last = e;
+    else
+      {
+        e.previous = last;
+        last.next = e;
+        last = e;
+      }
+    size++;
+  }
+
+  /**
+   * Returns true if the list contains the given object. Comparison is done by
+   * <code>o == null ? e = null : o.equals(e)</code>.
+   *
+   * @param o the element to look for
+   * @return true if it is found
+   */
+  public boolean contains(Object o)
+  {
+    Entry e = first;
+    while (e != null)
+      {
+        if (equals(o, e.data))
+          return true;
+        e = e.next;
+      }
+    return false;
+  }
+
+  /**
+   * Returns the size of the list.
+   *
+   * @return the list size
+   */
+  public int size()
+  {
+    return size;
+  }
+
+  /**
+   * Adds an element to the end of the list.
+   *
+   * @param o the entry to add
+   * @return true, as it always succeeds
+   */
+  public boolean add(Object o)
+  {
+    addLastEntry(new Entry(o));
+    return true;
+  }
+
+  /**
+   * Removes the entry at the lowest index in the list that matches the given
+   * object, comparing by <code>o == null ? e = null : o.equals(e)</code>.
+   *
+   * @param o the object to remove
+   * @return true if an instance of the object was removed
+   */
+  public boolean remove(Object o)
+  {
+    Entry e = first;
+    while (e != null)
+      {
+        if (equals(o, e.data))
+          {
+            removeEntry(e);
+            return true;
+          }
+        e = e.next;
+      }
+    return false;
+  }
+
+  /**
+   * Append the elements of the collection in iteration order to the end of
+   * this list. If this list is modified externally (for example, if this
+   * list is the collection), behavior is unspecified.
+   *
+   * @param c the collection to append
+   * @return true if the list was modified
+   * @throws NullPointerException if c is null
+   */
+  public boolean addAll(Collection c)
+  {
+    return addAll(size, c);
+  }
+
+  /**
+   * Insert the elements of the collection in iteration order at the given
+   * index of this list. If this list is modified externally (for example,
+   * if this list is the collection), behavior is unspecified.
+   *
+   * @param c the collection to append
+   * @return true if the list was modified
+   * @throws NullPointerException if c is null
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   */
+  public boolean addAll(int index, Collection c)
+  {
+    checkBoundsInclusive(index);
+    int csize = c.size();
+
+    if (csize == 0)
+      return false;
+
+    Iterator itr = c.iterator();
+
+    // Get the entries just before and after index. If index is at the start
+    // of the list, BEFORE is null. If index is at the end of the list, AFTER
+    // is null. If the list is empty, both are null.
+    Entry after = null;
+    Entry before = null;
+    if (index != size)
+      {
+        after = getEntry(index);
+        before = after.previous;
+      }
+    else
+      before = last;
+
+    // Create the first new entry. We do not yet set the link from `before'
+    // to the first entry, in order to deal with the case where (c == this).
+    // [Actually, we don't have to handle this case to fufill the
+    // contract for addAll(), but Sun's implementation appears to.]
+    Entry e = new Entry(itr.next());
+    e.previous = before;
+    Entry prev = e;
+    Entry firstNew = e;
+
+    // Create and link all the remaining entries.
+    for (int pos = 1; pos < csize; pos++)
+      {
+        e = new Entry(itr.next());
+        e.previous = prev;
+        prev.next = e;
+        prev = e;
+      }
+
+    // Link the new chain of entries into the list.
+    modCount++;
+    size += csize;
+    prev.next = after;
+    if (after != null)
+      after.previous = e;
+    else
+      last = e;
+
+    if (before != null)
+      before.next = firstNew;
+    else
+      first = firstNew;
+    return true;
+  }
+
+  /**
+   * Remove all elements from this list.
+   */
+  public void clear()
+  {
+    if (size > 0)
+      {
+        modCount++;
+        first = null;
+        last = null;
+        size = 0;
+      }
+  }
+
+  /**
+   * Return the element at index.
+   *
+   * @param index the place to look
+   * @return the element at index
+   * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+   */
+  public Object get(int index)
+  {
+    checkBoundsExclusive(index);
+    return getEntry(index).data;
+  }
+
+  /**
+   * Replace the element at the given location in the list.
+   *
+   * @param index which index to change
+   * @param o the new element
+   * @return the prior element
+   * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+   */
+  public Object set(int index, Object o)
+  {
+    checkBoundsExclusive(index);
+    Entry e = getEntry(index);
+    Object old = e.data;
+    e.data = o;
+    return old;
+  }
+
+  /**
+   * Inserts an element in the given position in the list.
+   *
+   * @param index where to insert the element
+   * @param o the element to insert
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   */
+  public void add(int index, Object o)
+  {
+    checkBoundsInclusive(index);
+    Entry e = new Entry(o);
+
+    if (index < size)
+      {
+        modCount++;
+        Entry after = getEntry(index);
+        e.next = after;
+        e.previous = after.previous;
+        if (after.previous == null)
+          first = e;
+        else
+          after.previous.next = e;
+        after.previous = e;
+        size++;
+      }
+    else
+      addLastEntry(e);
+  }
+
+  /**
+   * Removes the element at the given position from the list.
+   *
+   * @param index the location of the element to remove
+   * @return the removed element
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   */
+  public Object remove(int index)
+  {
+    checkBoundsExclusive(index);
+    Entry e = getEntry(index);
+    removeEntry(e);
+    return e.data;
+  }
+
+  /**
+   * Returns the first index where the element is located in the list, or -1.
+   *
+   * @param o the element to look for
+   * @return its position, or -1 if not found
+   */
+  public int indexOf(Object o)
+  {
+    int index = 0;
+    Entry e = first;
+    while (e != null)
+      {
+        if (equals(o, e.data))
+          return index;
+        index++;
+        e = e.next;
+      }
+    return -1;
+  }
+
+  /**
+   * Returns the last index where the element is located in the list, or -1.
+   *
+   * @param o the element to look for
+   * @return its position, or -1 if not found
+   */
+  public int lastIndexOf(Object o)
+  {
+    int index = size - 1;
+    Entry e = last;
+    while (e != null)
+      {
+        if (equals(o, e.data))
+          return index;
+        index--;
+        e = e.previous;
+      }
+    return -1;
+  }
+
+  /**
+   * Obtain a ListIterator over this list, starting at a given index. The
+   * ListIterator returned by this method supports the add, remove and set
+   * methods.
+   *
+   * @param index the index of the element to be returned by the first call to
+   *        next(), or size() to be initially positioned at the end of the list
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   */
+  public ListIterator listIterator(int index)
+  {
+    checkBoundsInclusive(index);
+    return new LinkedListItr(index);
+  }
+
+  /**
+   * Create a shallow copy of this LinkedList (the elements are not cloned).
+   *
+   * @return an object of the same class as this object, containing the
+   *         same elements in the same order
+   */
+  public Object clone()
+  {
+    LinkedList copy = null;
+    try
+      {
+        copy = (LinkedList) super.clone();
+      }
+    catch (CloneNotSupportedException ex)
+      {
+      }
+    copy.clear();
+    copy.addAll(this);
+    return copy;
+  }
+
+  /**
+   * Returns an array which contains the elements of the list in order.
+   *
+   * @return an array containing the list elements
+   */
+  public Object[] toArray()
+  {
+    Object[] array = new Object[size];
+    Entry e = first;
+    for (int i = 0; i < size; i++)
+      {
+        array[i] = e.data;
+        e = e.next;
+      }
+    return array;
+  }
+
+  /**
+   * Returns an Array whose component type is the runtime component type of
+   * the passed-in Array.  The returned Array is populated with all of the
+   * elements in this LinkedList.  If the passed-in Array is not large enough
+   * to store all of the elements in this List, a new Array will be created 
+   * and returned; if the passed-in Array is <i>larger</i> than the size
+   * of this List, then size() index will be set to null.
+   *
+   * @param a the passed-in Array
+   * @return an array representation of this list
+   * @throws ArrayStoreException if the runtime type of a does not allow
+   *         an element in this list
+   * @throws NullPointerException if a is null
+   */
+  public Object[] toArray(Object[] a)
+  {
+    if (a.length < size)
+      a = (Object[]) Array.newInstance(a.getClass().getComponentType(), size);
+    else if (a.length > size)
+      a[size] = null;
+    Entry e = first;
+    for (int i = 0; i < size; i++)
+      {
+        a[i] = e.data;
+        e = e.next;
+      }
+    return a;
+  }
+
+  /**
+   * Serializes this object to the given stream.
+   *
+   * @param s the stream to write to
+   * @throws IOException if the underlying stream fails
+   * @serialData the size of the list (int), followed by all the elements
+   *             (Object) in proper order
+   */
+  private void writeObject(ObjectOutputStream s) throws IOException
+  {
+    s.defaultWriteObject();
+    s.writeInt(size);
+    Entry e = first;
+    while (e != null)
+      {
+        s.writeObject(e.data);
+        e = e.next;
+      }
+  }
+
+  /**
+   * Deserializes this object from the given stream.
+   *
+   * @param s the stream to read from
+   * @throws ClassNotFoundException if the underlying stream fails
+   * @throws IOException if the underlying stream fails
+   * @serialData the size of the list (int), followed by all the elements
+   *             (Object) in proper order
+   */
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException
+  {
+    s.defaultReadObject();
+    int i = s.readInt();
+    while (--i >= 0)
+      addLastEntry(new Entry(s.readObject()));
+  }
+
+  /**
+   * A ListIterator over the list. This class keeps track of its
+   * position in the list and the two list entries it is between.
+   *
+   * @author Original author unknown
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private final class LinkedListItr implements ListIterator
+  {
+    /** Number of modifications we know about. */
+    private int knownMod = modCount;
+
+    /** Entry that will be returned by next(). */
+    private Entry next;
+
+    /** Entry that will be returned by previous(). */
+    private Entry previous;
+
+    /** Entry that will be affected by remove() or set(). */
+    private Entry lastReturned;
+
+    /** Index of `next'. */
+    private int position;
+
+    /**
+     * Initialize the iterator.
+     *
+     * @param index the initial index
+     */
+    LinkedListItr(int index)
+    {
+      if (index == size)
+        {
+          next = null;
+          previous = last;
+        }
+      else
+        {
+          next = getEntry(index);
+          previous = next.previous;
+        }
+      position = index;
+    }
+
+    /**
+     * Checks for iterator consistency.
+     *
+     * @throws ConcurrentModificationException if the list was modified
+     */
+    private void checkMod()
+    {
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+    }
+
+    /**
+     * Returns the index of the next element.
+     *
+     * @return the next index
+     */
+    public int nextIndex()
+    {
+      return position;
+    }
+
+    /**
+     * Returns the index of the previous element.
+     *
+     * @return the previous index
+     */
+    public int previousIndex()
+    {
+      return position - 1;
+    }
+
+    /**
+     * Returns true if more elements exist via next.
+     *
+     * @return true if next will succeed
+     */
+    public boolean hasNext()
+    {
+      return (next != null);
+    }
+
+    /**
+     * Returns true if more elements exist via previous.
+     *
+     * @return true if previous will succeed
+     */
+    public boolean hasPrevious()
+    {
+      return (previous != null);
+    }
+
+    /**
+     * Returns the next element.
+     *
+     * @return the next element
+     * @throws ConcurrentModificationException if the list was modified
+     * @throws NoSuchElementException if there is no next
+     */
+    public Object next()
+    {
+      checkMod();
+      if (next == null)
+        throw new NoSuchElementException();
+      position++;
+      lastReturned = previous = next;
+      next = lastReturned.next;
+      return lastReturned.data;
+    }
+
+    /**
+     * Returns the previous element.
+     *
+     * @return the previous element
+     * @throws ConcurrentModificationException if the list was modified
+     * @throws NoSuchElementException if there is no previous
+     */
+    public Object previous()
+    {
+      checkMod();
+      if (previous == null)
+        throw new NoSuchElementException();
+      position--;
+      lastReturned = next = previous;
+      previous = lastReturned.previous;
+      return lastReturned.data;
+    }
+
+    /**
+     * Remove the most recently returned element from the list.
+     *
+     * @throws ConcurrentModificationException if the list was modified
+     * @throws IllegalStateException if there was no last element
+     */
+    public void remove()
+    {
+      checkMod();
+      if (lastReturned == null)
+        throw new IllegalStateException();
+
+      // Adjust the position to before the removed element, if the element
+      // being removed is behind the cursor.
+      if (lastReturned == previous)
+        position--;
+
+      next = lastReturned.next;
+      previous = lastReturned.previous;
+      removeEntry(lastReturned);
+      knownMod++;
+
+      lastReturned = null;
+    }
+
+    /**
+     * Adds an element between the previous and next, and advance to the next.
+     *
+     * @param o the element to add
+     * @throws ConcurrentModificationException if the list was modified
+     */
+    public void add(Object o)
+    {
+      checkMod();
+      modCount++;
+      knownMod++;
+      size++;
+      position++;
+      Entry e = new Entry(o);
+      e.previous = previous;
+      e.next = next;
+
+      if (previous != null)
+        previous.next = e;
+      else
+        first = e;
+
+      if (next != null)
+        next.previous = e;
+      else
+        last = e;
+
+      previous = e;
+      lastReturned = null;
+    }
+
+    /**
+     * Changes the contents of the element most recently returned.
+     *
+     * @param o the new element
+     * @throws ConcurrentModificationException if the list was modified
+     * @throws IllegalStateException if there was no last element
+     */
+    public void set(Object o)
+    {
+      checkMod();
+      if (lastReturned == null)
+        throw new IllegalStateException();
+      lastReturned.data = o;
+    }
+  } // class LinkedListItr
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/List.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/List.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/List.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/List.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,451 @@
+/* List.java -- An ordered collection which allows indexed access
+   Copyright (C) 1998, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An ordered collection (also known as a list). This collection allows
+ * access to elements by position, as well as control on where elements
+ * are inserted. Unlike sets, duplicate elements are permitted by this
+ * general contract (if a subclass forbids duplicates, this should be
+ * documented).
+ * <p>
+ *
+ * List places additional requirements on <code>iterator</code>,
+ * <code>add</code>, <code>remove</code>, <code>equals</code>, and
+ * <code>hashCode</code>, in addition to requiring more methods. List
+ * indexing is 0-based (like arrays), although some implementations may
+ * require time proportional to the index to obtain an arbitrary element.
+ * The List interface is incompatible with Set; you cannot implement both
+ * simultaneously.
+ * <p>
+ *
+ * Lists also provide a <code>ListIterator</code> which allows bidirectional
+ * traversal and other features atop regular iterators. Lists can be
+ * searched for arbitrary elements, and allow easy insertion and removal
+ * of multiple elements in one method call.
+ * <p>
+ *
+ * Note: While lists may contain themselves as elements, this leads to
+ * undefined (usually infinite recursive) behavior for some methods like
+ * hashCode or equals.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Collection
+ * @see Set
+ * @see ArrayList
+ * @see LinkedList
+ * @see Vector
+ * @see Arrays#asList(Object[])
+ * @see Collections#nCopies(int, Object)
+ * @see Collections#EMPTY_LIST
+ * @see AbstractList
+ * @see AbstractSequentialList
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface List extends Collection
+{
+  /**
+   * Insert an element into the list at a given position (optional operation).
+   * This shifts all existing elements from that position to the end one
+   * index to the right. This version of add has no return, since it is
+   * assumed to always succeed if there is no exception.
+   *
+   * @param index the location to insert the item
+   * @param o the object to insert
+   * @throws UnsupportedOperationException if this list does not support the
+   *         add operation
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   * @throws ClassCastException if o cannot be added to this list due to its
+   *         type
+   * @throws IllegalArgumentException if o cannot be added to this list for
+   *         some other reason
+   * @throws NullPointerException if o is null and this list doesn't support
+   *         the addition of null values.
+   */
+  void add(int index, Object o);
+
+  /**
+   * Add an element to the end of the list (optional operation). If the list
+   * imposes restraints on what can be inserted, such as no null elements,
+   * this should be documented.
+   *
+   * @param o the object to add
+   * @return true, as defined by Collection for a modified list
+   * @throws UnsupportedOperationException if this list does not support the
+   *         add operation
+   * @throws ClassCastException if o cannot be added to this list due to its
+   *         type
+   * @throws IllegalArgumentException if o cannot be added to this list for
+   *         some other reason
+   * @throws NullPointerException if o is null and this list doesn't support
+   *         the addition of null values.
+   */
+  boolean add(Object o);
+
+  /**
+   * Insert the contents of a collection into the list at a given position
+   * (optional operation). Shift all elements at that position to the right
+   * by the number of elements inserted. This operation is undefined if
+   * this list is modified during the operation (for example, if you try
+   * to insert a list into itself).
+   *
+   * @param index the location to insert the collection
+   * @param c the collection to insert
+   * @return true if the list was modified by this action, that is, if c is
+   *         non-empty
+   * @throws UnsupportedOperationException if this list does not support the
+   *         addAll operation
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   * @throws ClassCastException if some element of c cannot be added to this
+   *         list due to its type
+   * @throws IllegalArgumentException if some element of c cannot be added
+   *         to this list for some other reason
+   * @throws NullPointerException if some element of c is null and this list
+   *         doesn't support the addition of null values.
+   * @throws NullPointerException if the specified collection is null
+   * @see #add(int, Object)
+   */
+  boolean addAll(int index, Collection c);
+
+  /**
+   * Add the contents of a collection to the end of the list (optional
+   * operation).  This operation is undefined if this list is modified
+   * during the operation (for example, if you try to insert a list into
+   * itself).
+   *
+   * @param c the collection to add
+   * @return true if the list was modified by this action, that is, if c is
+   *         non-empty
+   * @throws UnsupportedOperationException if this list does not support the
+   *         addAll operation
+   * @throws ClassCastException if some element of c cannot be added to this
+   *         list due to its type
+   * @throws IllegalArgumentException if some element of c cannot be added
+   *         to this list for some other reason
+   * @throws NullPointerException if the specified collection is null
+   * @throws NullPointerException if some element of c is null and this list
+   *         doesn't support the addition of null values.
+   * @see #add(Object)
+   */
+  boolean addAll(Collection c);
+
+  /**
+   * Clear the list, such that a subsequent call to isEmpty() would return
+   * true (optional operation).
+   *
+   * @throws UnsupportedOperationException if this list does not support the
+   *         clear operation
+   */
+  void clear();
+
+  /**
+   * Test whether this list contains a given object as one of its elements.
+   * This is defined as the existence of an element e such that
+   * <code>o == null ? e == null : o.equals(e)</code>.
+   *
+   * @param o the element to look for
+   * @return true if this list contains the element
+   * @throws ClassCastException if the type of o is not a valid type
+   *         for this list.
+   * @throws NullPointerException if o is null and the list doesn't
+   *         support null values.
+   */
+  boolean contains(Object o);
+
+  /**
+   * Test whether this list contains every element in a given collection.
+   *
+   * @param c the collection to test for
+   * @return true if for every element o in c, contains(o) would return true
+   * @throws NullPointerException if the collection is null
+   * @throws ClassCastException if the type of any element in c is not a valid
+   *         type for this list.
+   * @throws NullPointerException if some element of c is null and this
+   *         list does not support null values.
+   * @see #contains(Object)
+   */
+  boolean containsAll(Collection c);
+
+  /**
+   * Test whether this list is equal to another object. A List is defined to be
+   * equal to an object if and only if that object is also a List, and the two
+   * lists have the same sequence. Two lists l1 and l2 are equal if and only
+   * if <code>l1.size() == l2.size()</code>, and for every integer n between 0
+   * and <code>l1.size() - 1</code> inclusive, <code>l1.get(n) == null ?
+   * l2.get(n) == null : l1.get(n).equals(l2.get(n))</code>.
+   *
+   * @param o the object to test for equality with this list
+   * @return true if o is equal to this list
+   * @see Object#equals(Object)
+   * @see #hashCode()
+   */
+  boolean equals(Object o);
+
+  /**
+   * Get the element at a given index in this list.
+   *
+   * @param index the index of the element to be returned
+   * @return the element at index index in this list
+   * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+   */
+  Object get(int index);
+
+  /**
+   * Obtains a hash code for this list. In order to obey the general
+   * contract of the hashCode method of class Object, this value is
+   * calculated as follows:
+   * 
+<p><pre>hashCode = 1;
+Iterator i = list.iterator();
+while (i.hasNext())
+{
+  Object obj = i.next();
+  hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
+}</pre>
+   *
+   * <p>This ensures that the general contract of Object.hashCode()
+   * is adhered to.
+   *
+   * @return the hash code of this list
+   * @see Object#hashCode()
+   * @see #equals(Object)
+   */
+  int hashCode();
+
+  /**
+   * Obtain the first index at which a given object is to be found in this
+   * list.
+   *
+   * @param o the object to search for
+   * @return the least integer n such that <code>o == null ? get(n) == null :
+   *         o.equals(get(n))</code>, or -1 if there is no such index.
+   * @throws ClassCastException if the type of o is not a valid
+   *         type for this list.
+   * @throws NullPointerException if o is null and this
+   *         list does not support null values.
+   */
+  int indexOf(Object o);
+
+  /**
+   * Test whether this list is empty, that is, if size() == 0.
+   *
+   * @return true if this list contains no elements
+   */
+  boolean isEmpty();
+
+  /**
+   * Obtain an Iterator over this list, whose sequence is the list order.
+   *
+   * @return an Iterator over the elements of this list, in order
+   */
+  Iterator iterator();
+
+  /**
+   * Obtain the last index at which a given object is to be found in this
+   * list.
+   *
+   * @return the greatest integer n such that <code>o == null ? get(n) == null
+   *         : o.equals(get(n))</code>, or -1 if there is no such index.
+   * @throws ClassCastException if the type of o is not a valid
+   *         type for this list.
+   * @throws NullPointerException if o is null and this
+   *         list does not support null values.
+   */
+  int lastIndexOf(Object o);
+
+  /**
+   * Obtain a ListIterator over this list, starting at the beginning.
+   *
+   * @return a ListIterator over the elements of this list, in order, starting
+   *         at the beginning
+   */
+  ListIterator listIterator();
+
+  /**
+   * Obtain a ListIterator over this list, starting at a given position.
+   * A first call to next() would return the same as get(index), and a
+   * first call to previous() would return the same as get(index - 1).
+   *
+   * @param index the position, between 0 and size() inclusive, to begin the
+   *        iteration from
+   * @return a ListIterator over the elements of this list, in order, starting
+   *         at index
+   * @throws IndexOutOfBoundsException if index < 0 || index > size()
+   */
+  ListIterator listIterator(int index);
+
+  /**
+   * Remove the element at a given position in this list (optional operation).
+   * Shifts all remaining elements to the left to fill the gap.
+   *
+   * @param index the position within the list of the object to remove
+   * @return the object that was removed
+   * @throws UnsupportedOperationException if this list does not support the
+   *         remove operation
+   * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+   */
+  Object remove(int index);
+
+  /**
+   * Remove the first occurence of an object from this list (optional
+   * operation). That is, remove the first element e such that
+   * <code>o == null ? e == null : o.equals(e)</code>.
+   *
+   * @param o the object to remove
+   * @return true if the list changed as a result of this call, that is, if
+   *         the list contained at least one occurrence of o
+   * @throws UnsupportedOperationException if this list does not support the
+   *         remove operation
+   * @throws ClassCastException if the type of o is not a valid
+   *         type for this list.
+   * @throws NullPointerException if o is null and this
+   *         list does not support removing null values.
+   */
+  boolean remove(Object o);
+
+  /**
+   * Remove all elements of a given collection from this list (optional
+   * operation). That is, remove every element e such that c.contains(e).
+   *
+   * @param c the collection to filter out
+   * @return true if this list was modified as a result of this call
+   * @throws UnsupportedOperationException if this list does not support the
+   *         removeAll operation
+   * @throws NullPointerException if the collection is null
+   * @throws ClassCastException if the type of any element in c is not a valid
+   *         type for this list.
+   * @throws NullPointerException if some element of c is null and this
+   *         list does not support removing null values.
+   * @see #remove(Object)
+   * @see #contains(Object)
+   */
+  boolean removeAll(Collection c);
+
+  /**
+   * Remove all elements of this list that are not contained in a given
+   * collection (optional operation). That is, remove every element e such
+   * that !c.contains(e).
+   *
+   * @param c the collection to retain
+   * @return true if this list was modified as a result of this call
+   * @throws UnsupportedOperationException if this list does not support the
+   *         retainAll operation
+   * @throws NullPointerException if the collection is null
+   * @throws ClassCastException if the type of any element in c is not a valid
+   *         type for this list.
+   * @throws NullPointerException if some element of c is null and this
+   *         list does not support retaining null values.
+   * @see #remove(Object)
+   * @see #contains(Object)
+   */
+  boolean retainAll(Collection c);
+
+  /**
+   * Replace an element of this list with another object (optional operation).
+   *
+   * @param index the position within this list of the element to be replaced
+   * @param o the object to replace it with
+   * @return the object that was replaced
+   * @throws UnsupportedOperationException if this list does not support the
+   *         set operation
+   * @throws IndexOutOfBoundsException if index < 0 || index >= size()
+   * @throws ClassCastException if o cannot be added to this list due to its
+   *         type
+   * @throws IllegalArgumentException if o cannot be added to this list for
+   *         some other reason
+   * @throws NullPointerException if o is null and this
+   *         list does not support null values.
+   */
+  Object set(int index, Object o);
+
+  /**
+   * Get the number of elements in this list. If the list contains more
+   * than Integer.MAX_VALUE elements, return Integer.MAX_VALUE.
+   *
+   * @return the number of elements in the list
+   */
+  int size();
+
+  /**
+   * Obtain a List view of a subsection of this list, from fromIndex
+   * (inclusive) to toIndex (exclusive). If the two indices are equal, the
+   * sublist is empty. The returned list should be modifiable if and only
+   * if this list is modifiable. Changes to the returned list should be
+   * reflected in this list. If this list is structurally modified in
+   * any way other than through the returned list, the result of any subsequent
+   * operations on the returned list is undefined.
+   *
+   * @param fromIndex the index that the returned list should start from
+   *        (inclusive)
+   * @param toIndex the index that the returned list should go to (exclusive)
+   * @return a List backed by a subsection of this list
+   * @throws IndexOutOfBoundsException if fromIndex < 0
+   *         || toIndex > size() || fromIndex > toIndex
+   */
+  List subList(int fromIndex, int toIndex);
+
+  /**
+   * Copy the current contents of this list into an array.
+   *
+   * @return an array of type Object[] and length equal to the length of this
+   *         list, containing the elements currently in this list, in order
+   */
+  Object[] toArray();
+
+  /**
+   * Copy the current contents of this list into an array. If the array passed
+   * as an argument has length less than that of this list, an array of the
+   * same run-time type as a, and length equal to the length of this list, is
+   * allocated using Reflection. Otherwise, a itself is used. The elements of
+   * this list are copied into it, and if there is space in the array, the
+   * following element is set to null. The resultant array is returned.
+   * Note: The fact that the following element is set to null is only useful
+   * if it is known that this list does not contain any null elements.
+   *
+   * @param a the array to copy this list into
+   * @return an array containing the elements currently in this list, in
+   *         order
+   * @throws ArrayStoreException if the type of any element of the
+   *         collection is not a subtype of the element type of a
+   * @throws NullPointerException if the specified array is null
+   */
+  Object[] toArray(Object[] a);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/ListIterator.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/ListIterator.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/ListIterator.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/ListIterator.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,170 @@
+/* ListIterator.java -- Extended Iterator for iterating over ordered lists
+   Copyright (C) 1998, 1999, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An extended version of Iterator to support the extra features of Lists. The
+ * elements may be accessed in forward or reverse order, elements may be
+ * replaced as well as removed, and new elements may be inserted, during the
+ * traversal of the list.
+ * <p>
+ *
+ * A list with n elements provides n+1 iterator positions (the front, the end,
+ * or between two elements). Note that <code>remove</code> and <code>set</code>
+ * operate on the last element returned, whether it was by <code>next</code>
+ * or <code>previous</code>.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Collection
+ * @see List
+ * @see Iterator
+ * @see Enumeration
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface ListIterator extends Iterator
+{
+  /**
+   * Tests whether there are elements remaining in the list in the forward
+   * direction. In other words, next() will not fail with a
+   * NoSuchElementException.
+   *
+   * @return true if the list continues in the forward direction
+   */
+  boolean hasNext();
+
+  /**
+   * Tests whether there are elements remaining in the list in the reverse
+   * direction. In other words, previous() will not fail with a
+   * NoSuchElementException.
+   *
+   * @return true if the list continues in the reverse direction
+   */
+  boolean hasPrevious();
+
+  /**
+   * Obtain the next element in the list in the forward direction. Repeated
+   * calls to next may be used to iterate over the entire list, or calls to
+   * next and previous may be used together to go forwards and backwards.
+   * Alternating calls to next and previous will return the same element.
+   *
+   * @return the next element in the list in the forward direction
+   * @throws NoSuchElementException if there are no more elements
+   */
+  Object next();
+
+  /**
+   * Obtain the next element in the list in the reverse direction. Repeated
+   * calls to previous may be used to iterate backwards over the entire list,
+   * or calls to next and previous may be used together to go forwards and
+   * backwards. Alternating calls to next and previous will return the same
+   * element.
+   *
+   * @return the next element in the list in the reverse direction
+   * @throws NoSuchElementException if there are no more elements
+   */
+  Object previous();
+
+  /**
+   * Find the index of the element that would be returned by a call to next.
+   * If hasNext() returns false, this returns the list size.
+   *
+   * @return the index of the element that would be returned by next()
+   */
+  int nextIndex();
+
+  /**
+   * Find the index of the element that would be returned by a call to
+   * previous. If hasPrevious() returns false, this returns -1.
+   *
+   * @return the index of the element that would be returned by previous()
+   */
+  int previousIndex();
+
+  /**
+   * Insert an element into the list at the current position of the iterator
+   * (optional operation). The element is inserted in between the element that
+   * would be returned by previous and the element that would be returned by
+   * next. After the insertion, a subsequent call to next is unaffected, but
+   * a call to previous returns the item that was added. The values returned
+   * by nextIndex() and previousIndex() are incremented.
+   *
+   * @param o the object to insert into the list
+   * @throws ClassCastException if the object is of a type which cannot be added
+   *         to this list.
+   * @throws IllegalArgumentException if some other aspect of the object stops
+   *         it being added to this list.
+   * @throws UnsupportedOperationException if this ListIterator does not
+   *         support the add operation.
+   */
+  void add(Object o);
+
+  /**
+   * Remove from the list the element last returned by a call to next or
+   * previous (optional operation). This method may only be called if neither
+   * add nor remove have been called since the last call to next or previous.
+   *
+   * @throws IllegalStateException if neither next or previous have been
+   *         called, or if add or remove has been called since the last call
+   *         to next or previous
+   * @throws UnsupportedOperationException if this ListIterator does not
+   *         support the remove operation
+   */
+  void remove();
+
+  /**
+   * Replace the element last returned by a call to next or previous with a
+   * given object (optional operation). This method may only be called if
+   * neither add nor remove have been called since the last call to next or
+   * previous.
+   *
+   * @param o the object to replace the element with
+   * @throws ClassCastException the object is of a type which cannot be added
+   *         to this list
+   * @throws IllegalArgumentException some other aspect of the object stops
+   *         it being added to this list
+   * @throws IllegalStateException if neither next or previous have been
+   *         called, or if add or remove has been called since the last call
+   *         to next or previous
+   * @throws UnsupportedOperationException if this ListIterator does not
+   *         support the set operation
+   */
+  void set(Object o);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/ListResourceBundle.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/ListResourceBundle.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/ListResourceBundle.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/ListResourceBundle.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,140 @@
+/* ListResourceBundle -- a resource bundle build around a list
+   Copyright (C) 1998, 1999, 2001, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A <code>ListResouceBundle</code> provides an easy way, to create your own
+ * resource bundle. It is an abstract class that you can subclass. You should
+ * then overwrite the getContents method, that provides a key/value list.
+ *
+ * <p>The key/value list is a two dimensional list of Object.  The first
+ * dimension ranges over the resources. The second dimension ranges from
+ * zero (key) to one (value). The keys must be of type String, and they are
+ * case-sensitive. For example:
+ *
+<br><pre>public class MyResources
+  extends ListResourceBundle
+{
+  public Object[][] getContents()
+  {
+    return contents;
+  }
+
+  static final Object[][] contents =
+  {
+    // LOCALIZED STRINGS
+    {"s1", "The disk \"{1}\" contains {0}."},  // MessageFormat pattern
+    {"s2", "1"},                       // location of {0} in pattern
+    {"s3", "My Disk"},                 // sample disk name
+    {"s4", "no files"},                // first ChoiceFormat choice
+    {"s5", "one file"},                // second ChoiceFormat choice
+    {"s6", "{0,number} files"}         // third ChoiceFormat choice
+    {"s7", "3 Mar 96"},                // sample date
+    {"s8", new Dimension(1,5)}         // real object, not just string
+    // END OF LOCALIZED MATERIAL
+  };
+}</pre>
+ *
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Locale
+ * @see PropertyResourceBundle
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ListResourceBundle extends ResourceBundle
+{
+  /**
+   * The constructor. It does nothing special.
+   */
+  public ListResourceBundle()
+  {
+  }
+
+  /**
+   * Gets a resource for a given key. This is called by <code>getObject</code>.
+   *
+   * @param key the key of the resource
+   * @return the resource for the key, or null if it doesn't exist
+   */
+  public final Object handleGetObject(String key)
+  {
+    Object[][] contents = getContents();
+    int i = contents.length;
+    while (--i >= 0)
+      if (key.equals(contents[i][0]))
+        return contents[i][1];
+    return null;
+  }
+
+  /**
+   * This method should return all keys for which a resource exists.
+   *
+   * @return an enumeration of the keys
+   */
+  public Enumeration getKeys()
+  {
+    // We make a new Set that holds all the keys, then return an enumeration
+    // for that. This prevents modifications from ruining the enumeration,
+    // as well as ignoring duplicates.
+    final Object[][] contents = getContents();
+    Set s = new HashSet();
+    int i = contents.length;
+    while (--i >= 0)
+      s.add(contents[i][0]);
+    ResourceBundle bundle = parent;
+    // Eliminate tail recursion.
+    while (bundle != null)
+      {
+        Enumeration e = bundle.getKeys();
+        while (e.hasMoreElements())
+          s.add(e.nextElement());
+        bundle = bundle.parent;
+      }
+    return Collections.enumeration(s);
+  }
+
+  /**
+   * Gets the key/value list. You must override this method, and should not
+   * provide duplicate keys or null entries.
+   *
+   * @return a two dimensional list of String key / Object resouce pairs
+   */
+  protected abstract Object[][] getContents();
+} // class ListResourceBundle

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Locale.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Locale.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Locale.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Locale.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,962 @@
+/* Locale.java -- i18n locales
+   Copyright (C) 1998, 1999, 2001, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.classpath.SystemProperties;
+import gnu.java.locale.LocaleHelper;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * Locales represent a specific country and culture. Classes which can be
+ * passed a Locale object tailor their information for a given locale. For
+ * instance, currency number formatting is handled differently for the USA
+ * and France.
+ *
+ * <p>Locales are made up of a language code, a country code, and an optional
+ * set of variant strings. Language codes are represented by
+ * <a href="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
+ * ISO 639:1988</a> w/ additions from ISO 639/RA Newsletter No. 1/1989
+ * and a decision of the Advisory Committee of ISO/TC39 on August 8, 1997.
+ *
+ * <p>Country codes are represented by
+ * <a href="http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html">
+ * ISO 3166</a>. Variant strings are vendor and browser specific. Standard
+ * variant strings include "POSIX" for POSIX, "WIN" for MS-Windows, and
+ * "MAC" for Macintosh. When there is more than one variant string, they must
+ * be separated by an underscore (U+005F).
+ *
+ * <p>The default locale is determined by the values of the system properties
+ * user.language, user.country (or user.region), and user.variant, defaulting
+ * to "en_US". Note that the locale does NOT contain the conversion and
+ * formatting capabilities (for that, use ResourceBundle and java.text).
+ * Rather, it is an immutable tag object for identifying a given locale, which
+ * is referenced by these other classes when they must make locale-dependent
+ * decisions.
+ *
+ * @see ResourceBundle
+ * @see java.text.Format
+ * @see java.text.NumberFormat
+ * @see java.text.Collator
+ * @author Jochen Hoenicke
+ * @author Paul Fisher
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Locale implements Serializable, Cloneable
+{
+  /** Locale which represents the English language. */
+  public static final Locale ENGLISH = getLocale("en");
+
+  /** Locale which represents the French language. */
+  public static final Locale FRENCH = getLocale("fr");
+
+  /** Locale which represents the German language. */
+  public static final Locale GERMAN = getLocale("de");
+
+  /** Locale which represents the Italian language. */
+  public static final Locale ITALIAN = getLocale("it");
+
+  /** Locale which represents the Japanese language. */
+  public static final Locale JAPANESE = getLocale("ja");
+
+  /** Locale which represents the Korean language. */
+  public static final Locale KOREAN = getLocale("ko");
+
+  /** Locale which represents the Chinese language. */
+  public static final Locale CHINESE = getLocale("zh");
+
+  /** Locale which represents the Chinese language as used in China. */
+  public static final Locale SIMPLIFIED_CHINESE = getLocale("zh", "CN");
+
+  /**
+   * Locale which represents the Chinese language as used in Taiwan.
+   * Same as TAIWAN Locale.
+   */
+  public static final Locale TRADITIONAL_CHINESE = getLocale("zh", "TW");
+
+  /** Locale which represents France. */
+  public static final Locale FRANCE = getLocale("fr", "FR");
+
+  /** Locale which represents Germany. */
+  public static final Locale GERMANY = getLocale("de", "DE");
+
+  /** Locale which represents Italy. */
+  public static final Locale ITALY = getLocale("it", "IT");
+
+  /** Locale which represents Japan. */
+  public static final Locale JAPAN = getLocale("ja", "JP");
+
+  /** Locale which represents Korea. */
+  public static final Locale KOREA = getLocale("ko", "KR");
+
+  /**
+   * Locale which represents China.
+   * Same as SIMPLIFIED_CHINESE Locale.
+   */
+  public static final Locale CHINA = SIMPLIFIED_CHINESE;
+
+  /**
+   * Locale which represents the People's Republic of China.
+   * Same as CHINA Locale.
+   */
+  public static final Locale PRC = CHINA;
+
+  /**
+   * Locale which represents Taiwan.
+   * Same as TRADITIONAL_CHINESE Locale.
+   */
+  public static final Locale TAIWAN = TRADITIONAL_CHINESE;
+
+  /** Locale which represents the United Kingdom. */
+  public static final Locale UK = getLocale("en", "GB");
+
+  /** Locale which represents the United States. */
+  public static final Locale US = getLocale("en", "US");
+
+  /** Locale which represents the English speaking portion of Canada. */
+  public static final Locale CANADA = getLocale("en", "CA");
+
+  /** Locale which represents the French speaking portion of Canada. */
+  public static final Locale CANADA_FRENCH = getLocale("fr", "CA");
+
+  /**
+   * Compatible with JDK 1.1+.
+   */
+  private static final long serialVersionUID = 9149081749638150636L;
+
+  /**
+   * The language code, as returned by getLanguage().
+   *
+   * @serial the languange, possibly ""
+   */
+  private String language;
+
+  /**
+   * The country code, as returned by getCountry().
+   *
+   * @serial the country, possibly ""
+   */
+  private String country;
+
+  /**
+   * The variant code, as returned by getVariant().
+   *
+   * @serial the variant, possibly ""
+   */
+  private String variant;
+
+  /**
+   * This is the cached hashcode. When writing to stream, we write -1.
+   *
+   * @serial should be -1 in serial streams
+   */
+  private transient int hashcode;
+
+  /**
+   * Array storing all available locales.
+   */
+  private static transient Locale[] availableLocales;
+
+  /**
+   * Locale cache. Only created locale objects are stored.
+   * Contains all supported locales when getAvailableLocales()
+   * got called.
+   */
+  private static transient HashMap localeMap;
+  
+  /**
+   * The default locale. Except for during bootstrapping, this should never be
+   * null. Note the logic in the main constructor, to detect when
+   * bootstrapping has completed.
+   */
+  private static Locale defaultLocale;
+
+  static {
+    String language = SystemProperties.getProperty("user.language", "en");
+    String country  = SystemProperties.getProperty("user.country", "US");
+    String region   = SystemProperties.getProperty("user.region", null);
+    String variant  = SystemProperties.getProperty("user.variant", "");
+
+    defaultLocale = getLocale(language,
+                              (region != null) ? region : country,
+                              variant);
+  }
+
+  /**
+   * Array storing all the available two-letter ISO639 languages.
+   */
+  private static transient String[] languageCache;
+
+  /**
+   * Array storing all the available two-letter ISO3166 country codes.
+   */
+  private static transient String[] countryCache;
+
+  /**
+   * Retrieves the locale with the specified language from the cache.
+   *
+   * @param language the language of the locale to retrieve.
+   * @return the locale.
+   */ 
+  private static Locale getLocale(String language)
+  {
+    return getLocale(language, "", "");
+  }
+  
+  /**
+   * Retrieves the locale with the specified language and country
+   * from the cache.
+   *
+   * @param language the language of the locale to retrieve.
+   * @param country the country of the locale to retrieve.
+   * @return the locale.
+   */ 
+  private static Locale getLocale(String language, String country)
+  {
+    return getLocale(language, country, "");
+  }
+  
+  /**
+   * Retrieves the locale with the specified language, country
+   * and variant from the cache.
+   *
+   * @param language the language of the locale to retrieve.
+   * @param country the country of the locale to retrieve.
+   * @param variant the variant of the locale to retrieve.
+   * @return the locale.
+   */ 
+  private static Locale getLocale(String language, String country, String variant)
+  {
+    if (localeMap == null)
+      localeMap = new HashMap(256);
+
+    String name = language + "_" + country + "_" + variant;
+    Locale locale = (Locale) localeMap.get(name);
+
+    if (locale == null)
+      {
+	locale = new Locale(language, country, variant);
+	localeMap.put(name, locale);
+      }
+
+    return locale;
+  }
+  
+  /**
+   * Convert new iso639 codes to the old ones.
+   *
+   * @param language the language to check
+   * @return the appropriate code
+   */
+  private String convertLanguage(String language)
+  {
+    if (language.equals(""))
+      return language;
+    language = language.toLowerCase();
+    int index = "he,id,yi".indexOf(language);
+    if (index != -1)
+      return "iw,in,ji".substring(index, index + 2);
+    return language;
+  }
+
+  /**
+   * Creates a new locale for the given language and country.
+   *
+   * @param language lowercase two-letter ISO-639 A2 language code
+   * @param country uppercase two-letter ISO-3166 A2 contry code
+   * @param variant vendor and browser specific
+   * @throws NullPointerException if any argument is null
+   */
+  public Locale(String language, String country, String variant)
+  {
+    // During bootstrap, we already know the strings being passed in are
+    // the correct capitalization, and not null. We can't call
+    // String.toUpperCase during this time, since that depends on the
+    // default locale.
+    if (defaultLocale != null)
+      {
+        language = convertLanguage(language).intern();
+        country = country.toUpperCase().intern();
+        variant = variant.intern();
+      }
+    this.language = language;
+    this.country = country;
+    this.variant = variant;
+    hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
+  }
+
+  /**
+   * Creates a new locale for the given language and country.
+   *
+   * @param language lowercase two-letter ISO-639 A2 language code
+   * @param country uppercase two-letter ISO-3166 A2 country code
+   * @throws NullPointerException if either argument is null
+   */
+  public Locale(String language, String country)
+  {
+    this(language, country, "");
+  }
+
+  /**
+   * Creates a new locale for a language.
+   *
+   * @param language lowercase two-letter ISO-639 A2 language code
+   * @throws NullPointerException if either argument is null
+   * @since 1.4
+   */
+  public Locale(String language)
+  {
+    this(language, "", "");
+  }
+
+  /**
+   * Returns the default Locale. The default locale is generally once set
+   * on start up and then never changed. Normally you should use this locale
+   * for everywhere you need a locale. The initial setting matches the
+   * default locale, the user has chosen.
+   *
+   * @return the default locale for this virtual machine
+   */
+  public static Locale getDefault()
+  {
+    return defaultLocale;
+  }
+
+  /**
+   * Changes the default locale. Normally only called on program start up.
+   * Note that this doesn't change the locale for other programs. This has
+   * a security check,
+   * <code>PropertyPermission("user.language", "write")</code>, because of
+   * its potential impact to running code.
+   *
+   * @param newLocale the new default locale
+   * @throws NullPointerException if newLocale is null
+   * @throws SecurityException if permission is denied
+   */
+  public static void setDefault(Locale newLocale)
+  {
+    if (newLocale == null)
+      throw new NullPointerException();
+    SecurityManager sm = System.getSecurityManager();
+    if (sm != null)
+      sm.checkPermission(new PropertyPermission("user.language", "write"));
+    defaultLocale = newLocale;
+  }
+
+  /**
+   * Returns the list of available locales.
+   *
+   * @return the installed locales
+   */
+  public static synchronized Locale[] getAvailableLocales()
+  {
+    if (availableLocales == null)
+      {
+        int len = LocaleHelper.getLocaleCount();
+        availableLocales = new Locale[len];
+
+        for (int i = 0; i < len; i++)
+          {
+            String language;
+            String country = "";
+            String variant = "";
+            String name = LocaleHelper.getLocaleName(i);
+
+            language = name.substring(0, 2);
+
+            if (name.length() > 2)
+              country = name.substring(3);
+
+	    int index = country.indexOf("_");
+	    if (index > 0)
+	      {
+		variant = country.substring(index + 1);
+		country = country.substring(0, index - 1);
+	      }
+
+            availableLocales[i] = getLocale(language, country, variant);
+          }
+      }
+    
+    return (Locale[]) availableLocales.clone();
+  }
+
+  /**
+   * Returns a list of all 2-letter uppercase country codes as defined
+   * in ISO 3166.
+   *
+   * @return a list of acceptable country codes
+   */
+  public static String[] getISOCountries()
+  {
+    if (countryCache == null)
+      {
+	countryCache = getISOStrings("territories");
+      }
+
+    return (String[]) countryCache.clone();
+  }
+
+  /**
+   * Returns a list of all 2-letter lowercase language codes as defined
+   * in ISO 639 (both old and new variant).
+   *
+   * @return a list of acceptable language codes
+   */
+  public static String[] getISOLanguages()
+  {
+    if (languageCache == null)
+      {
+	languageCache = getISOStrings("languages");
+      }
+    return (String[]) languageCache.clone();
+  }
+
+  /**
+   * Returns the set of keys from the specified resource hashtable, filtered
+   * so that only two letter strings are returned.
+   *
+   * @param tableName the name of the table from which to retrieve the keys.
+   * @return an array of two-letter strings.
+   */
+  private static String[] getISOStrings(String tableName)
+  {
+    int count = 0;
+    ResourceBundle bundle =
+      ResourceBundle.getBundle("gnu.java.locale.LocaleInformation");
+    Enumeration e = bundle.getKeys();
+    ArrayList tempList = new ArrayList();
+
+    while (e.hasMoreElements())
+      {
+	String key = (String) e.nextElement();
+	
+	if (key.startsWith(tableName + "."))
+	  {
+	    String str = key.substring(tableName.length() + 1);
+
+	    if (str.length() == 2
+		&& Character.isLetter(str.charAt(0))
+		&& Character.isLetter(str.charAt(1)))
+	      {
+		tempList.add(str);
+		++count;
+	      }
+	  }
+      }
+
+    String[] strings = new String[count];
+    
+    for (int a = 0; a < count; ++a)
+      strings[a] = (String) tempList.get(a);
+    
+    return strings;
+  }
+
+  /**
+   * Returns the language code of this locale. Some language codes have changed
+   * as ISO 639 has evolved; this returns the old name, even if you built
+   * the locale with the new one.
+   *
+   * @return language code portion of this locale, or an empty String
+   */
+  public String getLanguage()
+  {
+    return language;
+  }
+
+  /**
+   * Returns the country code of this locale.
+   *
+   * @return country code portion of this locale, or an empty String
+   */
+  public String getCountry()
+  {
+    return country;
+  }
+
+  /**
+   * Returns the variant code of this locale.
+   *
+   * @return the variant code portion of this locale, or an empty String
+   */
+  public String getVariant()
+  {
+    return variant;
+  }
+
+  /**
+   * Gets the string representation of the current locale. This consists of
+   * the language, the country, and the variant, separated by an underscore.
+   * The variant is listed only if there is a language or country. Examples:
+   * "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC".
+   *
+   * @return the string representation of this Locale
+   * @see #getDisplayName()
+   */
+  public String toString()
+  {
+    if (language.length() == 0 && country.length() == 0)
+      return "";
+    else if (country.length() == 0 && variant.length() == 0)
+      return language;
+    StringBuffer result = new StringBuffer(language);
+    result.append('_').append(country);
+    if (variant.length() != 0)
+      result.append('_').append(variant);
+    return result.toString();
+  }
+
+  /**
+   * Returns the three-letter ISO language abbrevation of this locale.
+   *
+   * @throws MissingResourceException if the three-letter code is not known
+   */
+  public String getISO3Language()
+  {
+    // We know all strings are interned so we can use '==' for better performance.
+    if (language == "")
+      return "";
+    int index
+      = ("aa,ab,af,am,ar,as,ay,az,ba,be,bg,bh,bi,bn,bo,br,ca,co,cs,cy,da,"
+         + "de,dz,el,en,eo,es,et,eu,fa,fi,fj,fo,fr,fy,ga,gd,gl,gn,gu,ha,iw,"
+         + "hi,hr,hu,hy,ia,in,ie,ik,in,is,it,iu,iw,ja,ji,jw,ka,kk,kl,km,kn,"
+         + "ko,ks,ku,ky,la,ln,lo,lt,lv,mg,mi,mk,ml,mn,mo,mr,ms,mt,my,na,ne,"
+         + "nl,no,oc,om,or,pa,pl,ps,pt,qu,rm,rn,ro,ru,rw,sa,sd,sg,sh,si,sk,"
+         + "sl,sm,sn,so,sq,sr,ss,st,su,sv,sw,ta,te,tg,th,ti,tk,tl,tn,to,tr,"
+         + "ts,tt,tw,ug,uk,ur,uz,vi,vo,wo,xh,ji,yo,za,zh,zu")
+      .indexOf(language);
+
+    if (index % 3 != 0 || language.length() != 2)
+      throw new MissingResourceException
+        ("Can't find ISO3 language for " + language,
+         "java.util.Locale", language);
+
+    // Don't read this aloud. These are the three letter language codes.
+    return
+      ("aarabkaframharaasmaymazebakbelbulbihbisbenbodbrecatcoscescymdandeu"
+       + "dzoellengepospaesteusfasfinfijfaofrafrygaigdhglggrngujhauhebhinhrv"
+       + "hunhyeinaindileipkindislitaikuhebjpnyidjawkatkazkalkhmkankorkaskur"
+       + "kirlatlinlaolitlavmlgmrimkdmalmonmolmarmsamltmyanaunepnldnorociorm"
+       + "oripanpolpusporquerohrunronruskinsansndsagsrpsinslkslvsmosnasomsqi"
+       + "srpsswsotsunsweswatamteltgkthatirtuktgltsntonturtsotattwiuigukrurd"
+       + "uzbvievolwolxhoyidyorzhazhozul")
+      .substring(index, index + 3);
+  }
+
+  /**
+   * Returns the three-letter ISO country abbrevation of the locale.
+   *
+   * @throws MissingResourceException if the three-letter code is not known
+   */
+  public String getISO3Country()
+  {
+    // We know all strings are interned so we can use '==' for better performance.
+    if (country == "")
+      return "";
+    int index
+      = ("AD,AE,AF,AG,AI,AL,AM,AN,AO,AQ,AR,AS,AT,AU,AW,AZ,BA,BB,BD,BE,BF,"
+         + "BG,BH,BI,BJ,BM,BN,BO,BR,BS,BT,BV,BW,BY,BZ,CA,CC,CF,CG,CH,CI,CK,"
+         + "CL,CM,CN,CO,CR,CU,CV,CX,CY,CZ,DE,DJ,DK,DM,DO,DZ,EC,EE,EG,EH,ER,"
+         + "ES,ET,FI,FJ,FK,FM,FO,FR,FX,GA,GB,GD,GE,GF,GH,GI,GL,GM,GN,GP,GQ,"
+         + "GR,GS,GT,GU,GW,GY,HK,HM,HN,HR,HT,HU,ID,IE,IL,IN,IO,IQ,IR,IS,IT,"
+         + "JM,JO,JP,KE,KG,KH,KI,KM,KN,KP,KR,KW,KY,KZ,LA,LB,LC,LI,LK,LR,LS,"
+         + "LT,LU,LV,LY,MA,MC,MD,MG,MH,MK,ML,MM,MN,MO,MP,MQ,MR,MS,MT,MU,MV,"
+         + "MW,MX,MY,MZ,NA,NC,NE,NF,NG,NI,NL,NO,NP,NR,NU,NZ,OM,PA,PE,PF,PG,"
+         + "PH,PK,PL,PM,PN,PR,PT,PW,PY,QA,RE,RO,RU,RW,SA,SB,SC,SD,SE,SG,SH,"
+         + "SI,SJ,SK,SL,SM,SN,SO,SR,ST,SV,SY,SZ,TC,TD,TF,TG,TH,TJ,TK,TM,TN,"
+         + "TO,TP,TR,TT,TV,TW,TZ,UA,UG,UM,US,UY,UZ,VA,VC,VE,VG,VI,VN,VU,WF,"
+         + "WS,YE,YT,YU,ZA,ZM,ZR,ZW")
+      .indexOf(country);
+
+    if (index % 3 != 0 || country.length() != 2)
+      throw new MissingResourceException
+        ("Can't find ISO3 country for " + country,
+         "java.util.Locale", country);
+
+    // Don't read this aloud. These are the three letter country codes.
+    return
+      ("ANDAREAFGATGAIAALBARMANTAGOATAARGASMAUTAUSABWAZEBIHBRBBGDBELBFABGR"
+       + "BHRBDIBENBMUBRNBOLBRABHSBTNBVTBWABLRBLZCANCCKCAFCOGCHECIVCOKCHLCMR"
+       + "CHNCOLCRICUBCPVCXRCYPCZEDEUDJIDNKDMADOMDZAECUESTEGYESHERIESPETHFIN"
+       + "FJIFLKFSMFROFRAFXXGABGBRGRDGEOGUFGHAGIBGRLGMBGINGLPGNQGRCSGSGTMGUM"
+       + "GNBGUYHKGHMDHNDHRVHTIHUNIDNIRLISRINDIOTIRQIRNISLITAJAMJORJPNKENKGZ"
+       + "KHMKIRCOMKNAPRKKORKWTCYMKAZLAOLBNLCALIELKALBRLSOLTULUXLVALBYMARMCO"
+       + "MDAMDGMHLMKDMLIMMRMNGMACMNPMTQMRTMSRMLTMUSMDVMWIMEXMYSMOZNAMNCLNER"
+       + "NFKNGANICNLDNORNPLNRUNIUNZLOMNPANPERPYFPNGPHLPAKPOLSPMPCNPRIPRTPLW"
+       + "PRYQATREUROMRUSRWASAUSLBSYCSDNSWESGPSHNSVNSJMSVKSLESMRSENSOMSURSTP"
+       + "SLVSYRSWZTCATCDATFTGOTHATJKTKLTKMTUNTONTMPTURTTOTUVTWNTZAUKRUGAUMI"
+       + "USAURYUZBVATVCTVENVGBVIRVNMVUTWLFWSMYEMMYTYUGZAFZMBZARZWE")
+      .substring(index, index + 3);
+  }
+
+  /**
+   * Gets the country name suitable for display to the user, formatted
+   * for the default locale.  This has the same effect as
+   * <pre>
+   * getDisplayLanguage(Locale.getDefault());
+   * </pre>
+   *
+   * @return the language name of this locale localized to the default locale,
+   *         with the ISO code as backup
+   */
+  public String getDisplayLanguage()
+  {
+    return getDisplayLanguage(defaultLocale);
+  }
+
+  /**
+   * <p>
+   * Gets the name of the language specified by this locale, in a form suitable
+   * for display to the user.  If possible, the display name will be localized
+   * to the specified locale.  For example, if the locale instance is
+   * <code>Locale.GERMANY</code>, and the specified locale is <code>Locale.UK</code>,
+   * the result would be 'German'.  Using the German locale would instead give
+   * 'Deutsch'.  If the display name can not be localized to the supplied
+   * locale, it will fall back on other output in the following order:
+   * </p>
+   * <ul>
+   * <li>the display name in the default locale</li>
+   * <li>the display name in English</li>
+   * <li>the ISO code</li>
+   * </ul>
+   * <p>
+   * If the language is unspecified by this locale, then the empty string is
+   * returned.
+   * </p>
+   *
+   * @param inLocale the locale to use for formatting the display string.
+   * @return the language name of this locale localized to the given locale,
+   *         with the default locale, English and the ISO code as backups.
+   * @throws NullPointerException if the supplied locale is null.
+   */
+  public String getDisplayLanguage(Locale inLocale)
+  {
+    try
+      {
+	ResourceBundle res =
+          ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+                                   inLocale,
+                                   ClassLoader.getSystemClassLoader());
+
+        return res.getString("languages." + language);
+      }
+    catch (MissingResourceException e)
+      {
+	return language;
+      }
+  }
+
+  /**
+   * Returns the country name of this locale localized to the
+   * default locale. If the localized is not found, the ISO code
+   * is returned. This has the same effect as
+   * <pre>
+   * getDisplayCountry(Locale.getDefault());
+   * </pre>
+   *
+   * @return the country name of this locale localized to the given locale,
+   *         with the ISO code as backup
+   */
+  public String getDisplayCountry()
+  {
+    return getDisplayCountry(defaultLocale);
+  }
+
+  /**
+   * <p>
+   * Gets the name of the country specified by this locale, in a form suitable
+   * for display to the user.  If possible, the display name will be localized
+   * to the specified locale.  For example, if the locale instance is
+   * <code>Locale.GERMANY</code>, and the specified locale is <code>Locale.UK</code>,
+   * the result would be 'Germany'.  Using the German locale would instead give
+   * 'Deutschland'.  If the display name can not be localized to the supplied
+   * locale, it will fall back on other output in the following order:
+   * </p>
+   * <ul>
+   * <li>the display name in the default locale</li>
+   * <li>the display name in English</li>
+   * <li>the ISO code</li>
+   * </ul>
+   * <p>
+   * If the country is unspecified by this locale, then the empty string is
+   * returned.
+   * </p>
+   *
+   * @param inLocale the locale to use for formatting the display string.
+   * @return the country name of this locale localized to the given locale,
+   *         with the default locale, English and the ISO code as backups.
+   * @throws NullPointerException if the supplied locale is null.
+   */
+  public String getDisplayCountry(Locale inLocale)
+  {
+    try
+      {
+        ResourceBundle res =
+          ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+                                   inLocale,
+                                   ClassLoader.getSystemClassLoader());
+    
+        return res.getString("territories." + country);
+      }
+    catch (MissingResourceException e)
+      {
+        return country;
+      }
+  }
+
+  /**
+   * Returns the variant name of this locale localized to the
+   * default locale. If the localized is not found, the variant code
+   * itself is returned. This has the same effect as
+   * <pre>
+   * getDisplayVariant(Locale.getDefault());
+   * </pre>
+   *
+   * @return the variant code of this locale localized to the given locale,
+   *         with the ISO code as backup
+   */
+  public String getDisplayVariant()
+  {
+    return getDisplayVariant(defaultLocale);
+  }
+
+
+  /**
+   * <p>
+   * Gets the name of the variant specified by this locale, in a form suitable
+   * for display to the user.  If possible, the display name will be localized
+   * to the specified locale.  For example, if the locale instance is a revised
+   * variant, and the specified locale is <code>Locale.UK</code>, the result
+   * would be 'REVISED'.  Using the German locale would instead give
+   * 'Revidiert'.  If the display name can not be localized to the supplied
+   * locale, it will fall back on other output in the following order:
+   * </p>
+   * <ul>
+   * <li>the display name in the default locale</li>
+   * <li>the display name in English</li>
+   * <li>the ISO code</li>
+   * </ul>
+   * <p>
+   * If the variant is unspecified by this locale, then the empty string is
+   * returned.
+   * </p>
+   *
+   * @param inLocale the locale to use for formatting the display string.
+   * @return the variant name of this locale localized to the given locale,
+   *         with the default locale, English and the ISO code as backups.
+   * @throws NullPointerException if the supplied locale is null.
+   */
+  public String getDisplayVariant(Locale inLocale)
+  {
+    try
+      {
+        ResourceBundle res =
+          ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
+                                   inLocale,
+                                   ClassLoader.getSystemClassLoader());
+    
+        return res.getString("variants." + variant);
+      }
+    catch (MissingResourceException e)
+      {
+        return variant;
+      }
+  }
+
+  /**
+   * Gets all local components suitable for display to the user, formatted
+   * for the default locale. For the language component, getDisplayLanguage
+   * is called. For the country component, getDisplayCountry is called.
+   * For the variant set component, getDisplayVariant is called.
+   *
+   * <p>The returned String will be one of the following forms:<br>
+   * <pre>
+   * language (country, variant)
+   * language (country)
+   * language (variant)
+   * country (variant)
+   * language
+   * country
+   * variant
+   * </pre>
+   *
+   * @return String version of this locale, suitable for display to the user
+   */
+  public String getDisplayName()
+  {
+    return getDisplayName(defaultLocale);
+  }
+
+  /**
+   * Gets all local components suitable for display to the user, formatted
+   * for a specified locale. For the language component,
+   * getDisplayLanguage(Locale) is called. For the country component,
+   * getDisplayCountry(Locale) is called. For the variant set component,
+   * getDisplayVariant(Locale) is called.
+   *
+   * <p>The returned String will be one of the following forms:<br>
+   * <pre>
+   * language (country, variant)
+   * language (country)
+   * language (variant)
+   * country (variant)
+   * language
+   * country
+   * variant
+   * </pre>
+   *
+   * @param locale locale to use for formatting
+   * @return String version of this locale, suitable for display to the user
+   */
+  public String getDisplayName(Locale locale)
+  {
+    StringBuffer result = new StringBuffer();
+    int count = 0;
+    String[] delimiters = {"", " (", ","};
+    if (language.length() != 0)
+      {
+        result.append(delimiters[count++]);
+        result.append(getDisplayLanguage(locale));
+      }
+    if (country.length() != 0)
+      {
+        result.append(delimiters[count++]);
+        result.append(getDisplayCountry(locale));
+      }
+    if (variant.length() != 0)
+      {
+        result.append(delimiters[count++]);
+        result.append(getDisplayVariant(locale));
+      }
+    if (count > 1)
+      result.append(")");
+    return result.toString();
+  }
+
+  /**
+   * Does the same as <code>Object.clone()</code> but does not throw
+   * a <code>CloneNotSupportedException</code>. Why anyone would
+   * use this method is a secret to me, since this class is immutable.
+   *
+   * @return the clone
+   */
+  public Object clone()
+  {
+    // This class is final, so no need to use native super.clone().
+    return new Locale(language, country, variant);
+  }
+
+  /**
+   * Return the hash code for this locale. The hashcode is the logical
+   * xor of the hash codes of the language, the country and the variant.
+   * The hash code is precomputed, since <code>Locale</code>s are often
+   * used in hash tables.
+   *
+   * @return the hashcode
+   */
+  public int hashCode()
+  {
+    return hashcode;
+  }
+
+  /**
+   * Compares two locales. To be equal, obj must be a Locale with the same
+   * language, country, and variant code.
+   *
+   * @param obj the other locale
+   * @return true if obj is equal to this
+   */
+  public boolean equals(Object obj)
+  {
+    if (this == obj)
+      return true;
+    if (! (obj instanceof Locale))
+      return false;
+    Locale l = (Locale) obj;
+
+    return (language == l.language
+            && country == l.country
+            && variant == l.variant);
+  }
+
+  /**
+   * Write the locale to an object stream.
+   *
+   * @param s the stream to write to
+   * @throws IOException if the write fails
+   * @serialData The first three fields are Strings representing language,
+   *             country, and variant. The fourth field is a placeholder for 
+   *             the cached hashcode, but this is always written as -1, and 
+   *             recomputed when reading it back.
+   */
+  private void writeObject(ObjectOutputStream s)
+    throws IOException
+  {
+    s.writeObject(language);
+    s.writeObject(country);
+    s.writeObject(variant);
+    // Hashcode field is always written as -1.
+    s.writeInt(-1);
+  }
+
+  /**
+   * Reads a locale from the input stream.
+   *
+   * @param s the stream to read from
+   * @throws IOException if reading fails
+   * @throws ClassNotFoundException if reading fails
+   * @serialData the hashCode is always invalid and must be recomputed
+   */
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException
+  {
+    language = ((String) s.readObject()).intern();
+    country = ((String) s.readObject()).intern();
+    variant = ((String) s.readObject()).intern();
+    // Recompute hashcode.
+    hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
+  }
+} // class Locale

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Map.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Map.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Map.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Map.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,338 @@
+/* Map.java: interface Map -- An object that maps keys to values
+             interface Map.Entry -- an Entry in a Map
+   Copyright (C) 1998, 2001, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * An object that maps keys onto values. Keys cannot be duplicated. This
+ * interface replaces the obsolete {@link Dictionary} abstract class.
+ * <p>
+ *
+ * The map has three collection views, which are backed by the map
+ * (modifications on one show up on the other): a set of keys, a collection
+ * of values, and a set of key-value mappings. Some maps have a guaranteed
+ * order, but not all do.
+ * <p>
+ *
+ * Note: Be careful about using mutable keys.  Behavior is unspecified if
+ * a key's comparison behavior is changed after the fact.  As a corollary
+ * to this rule, don't use a Map as one of its own keys or values, as it makes
+ * hashCode and equals have undefined behavior.
+ * <p>
+ *
+ * All maps are recommended to provide a no argument constructor, which builds
+ * an empty map, and one that accepts a Map parameter and copies the mappings
+ * (usually by putAll), to create an equivalent map.  Unfortunately, Java
+ * cannot enforce these suggestions.
+ * <p>
+ *
+ * The map may be unmodifiable, in which case unsupported operations will
+ * throw an UnsupportedOperationException.  Note that some operations may be
+ * safe, such as putAll(m) where m is empty, even if the operation would
+ * normally fail with a non-empty argument.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see HashMap
+ * @see TreeMap
+ * @see Hashtable
+ * @see SortedMap
+ * @see Collection
+ * @see Set
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Map
+{
+  /**
+   * Remove all entries from this Map (optional operation).
+   *
+   * @throws UnsupportedOperationException if clear is not supported
+   */
+  void clear();
+
+  /**
+   * Returns true if this contains a mapping for the given key.
+   *
+   * @param key the key to search for
+   * @return true if the map contains the key
+   * @throws ClassCastException if the key is of an inappropriate type
+   * @throws NullPointerException if key is <code>null</code> but the map
+   *         does not permit null keys
+   */
+  boolean containsKey(Object key);
+
+  /**
+   * Returns true if this contains at least one mapping with the given value.
+   * In other words, returns true if a value v exists where
+   * <code>(value == null ? v == null : value.equals(v))</code>. This usually
+   * requires linear time.
+   *
+   * @param value the value to search for
+   * @return true if the map contains the value
+   * @throws ClassCastException if the type of the value is not a valid type
+   *         for this map.
+   * @throws NullPointerException if the value is null and the map doesn't
+   *         support null values.
+   */
+  boolean containsValue(Object value);
+
+  /**
+   * Returns a set view of the mappings in this Map.  Each element in the
+   * set is a Map.Entry.  The set is backed by the map, so that changes in
+   * one show up in the other.  Modifications made while an iterator is
+   * in progress cause undefined behavior.  If the set supports removal,
+   * these methods remove the underlying mapping from the map:
+   * <code>Iterator.remove</code>, <code>Set.remove</code>,
+   * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
+   * Element addition, via <code>add</code> or <code>addAll</code>, is
+   * not supported via this set.
+   *
+   * @return the set view of all mapping entries
+   * @see Map.Entry
+   */
+  Set entrySet();
+
+  /**
+   * Compares the specified object with this map for equality. Returns
+   * <code>true</code> if the other object is a Map with the same mappings,
+   * that is,<br>
+   * <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
+   * This allows comparison of maps, regardless of implementation.
+   *
+   * @param o the object to be compared
+   * @return true if the object equals this map
+   * @see Set#equals(Object)
+   */
+  boolean equals(Object o);
+
+  /**
+   * Returns the value mapped by the given key. Returns <code>null</code> if
+   * there is no mapping.  However, in Maps that accept null values, you
+   * must rely on <code>containsKey</code> to determine if a mapping exists.
+   *
+   * @param key the key to look up
+   * @return the value associated with the key, or null if key not in map
+   * @throws ClassCastException if the key is an inappropriate type
+   * @throws NullPointerException if this map does not accept null keys
+   * @see #containsKey(Object)
+   */
+  Object get(Object key);
+
+  /**
+   * Associates the given key to the given value (optional operation). If the
+   * map already contains the key, its value is replaced. Be aware that in
+   * a map that permits <code>null</code> values, a null return does not
+   * always imply that the mapping was created.
+   *
+   * @param key the key to map
+   * @param value the value to be mapped
+   * @return the previous value of the key, or null if there was no mapping
+   * @throws UnsupportedOperationException if the operation is not supported
+   * @throws ClassCastException if the key or value is of the wrong type
+   * @throws IllegalArgumentException if something about this key or value
+   *         prevents it from existing in this map
+   * @throws NullPointerException if either the key or the value is null,
+   *         and the map forbids null keys or values
+   * @see #containsKey(Object)
+   */
+  Object put(Object key, Object value);
+
+  /**
+   * Returns the hash code for this map. This is the sum of all hashcodes
+   * for each Map.Entry object in entrySet.  This allows comparison of maps,
+   * regardless of implementation, and satisfies the contract of
+   * Object.hashCode.
+   *
+   * @return the hash code
+   * @see Map.Entry#hashCode()
+   */
+  int hashCode();
+
+  /**
+   * Returns true if the map contains no mappings.
+   *
+   * @return true if the map is empty
+   */
+  boolean isEmpty();
+
+  /**
+   * Returns a set view of the keys in this Map.  The set is backed by the
+   * map, so that changes in one show up in the other.  Modifications made
+   * while an iterator is in progress cause undefined behavior.  If the set
+   * supports removal, these methods remove the underlying mapping from
+   * the map: <code>Iterator.remove</code>, <code>Set.remove</code>,
+   * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
+   * Element addition, via <code>add</code> or <code>addAll</code>, is
+   * not supported via this set.
+   *
+   * @return the set view of all keys
+   */
+  Set keySet();
+
+  /**
+   * Copies all entries of the given map to this one (optional operation). If
+   * the map already contains a key, its value is replaced.
+   *
+   * @param m the mapping to load into this map
+   * @throws UnsupportedOperationException if the operation is not supported
+   * @throws ClassCastException if a key or value is of the wrong type
+   * @throws IllegalArgumentException if something about a key or value
+   *         prevents it from existing in this map
+   * @throws NullPointerException if the map forbids null keys or values, or
+   *         if <code>m</code> is null.
+   * @see #put(Object, Object)
+   */
+  void putAll(Map m);
+
+  /**
+   * Removes the mapping for this key if present (optional operation). If
+   * the key is not present, this returns null. Note that maps which permit
+   * null values may also return null if the key was removed.
+   *
+   * @param key the key to remove
+   * @return the value the key mapped to, or null if not present.
+   * @throws UnsupportedOperationException if deletion is unsupported
+   * @throws NullPointerException if the key is null and this map doesn't
+   *         support null keys.
+   * @throws ClassCastException if the type of the key is not a valid type
+   *         for this map.
+   */
+  Object remove(Object key);
+
+  /**
+   * Returns the number of key-value mappings in the map. If there are more
+   * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE.
+   *
+   * @return the number of mappings
+   */
+  int size();
+
+  /**
+   * Returns a collection (or bag) view of the values in this Map.  The
+   * collection is backed by the map, so that changes in one show up in
+   * the other.  Modifications made while an iterator is in progress cause
+   * undefined behavior.  If the collection supports removal, these methods
+   * remove the underlying mapping from the map: <code>Iterator.remove</code>,
+   * <code>Collection.remove</code>, <code>removeAll</code>,
+   * <code>retainAll</code>, and <code>clear</code>. Element addition, via
+   * <code>add</code> or <code>addAll</code>, is not supported via this
+   * collection.
+   *
+   * @return the collection view of all values
+   */
+  Collection values();
+
+  /**
+   * A map entry (key-value pair). The Map.entrySet() method returns a set
+   * view of these objects; there is no other valid way to come across them.
+   * These objects are only valid for the duration of an iteration; in other
+   * words, if you mess with one after modifying the map, you are asking
+   * for undefined behavior.
+   *
+   * @author Original author unknown
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   * @see Map
+   * @see Map#entrySet()
+   * @since 1.2
+   * @status updated to 1.4
+   */
+  interface Entry
+  {
+    /**
+     * Get the key corresponding to this entry.
+     *
+     * @return the key
+     */
+    Object getKey();
+
+    /**
+     * Get the value corresponding to this entry. If you already called
+     * Iterator.remove(), this is undefined.
+     *
+     * @return the value
+     */
+    Object getValue();
+
+    /**
+     * Replaces the value with the specified object (optional operation).
+     * This writes through to the map, and is undefined if you already
+     * called Iterator.remove().
+     *
+     * @param value the new value to store
+     * @return the old value
+     * @throws UnsupportedOperationException if the operation is not supported
+     * @throws ClassCastException if the value is of the wrong type
+     * @throws IllegalArgumentException if something about the value
+     *         prevents it from existing in this map
+     * @throws NullPointerException if the map forbids null values
+     */
+    Object setValue(Object value);
+
+
+    /**
+     * Returns the hash code of the entry.  This is defined as the
+     * exclusive-or of the hashcodes of the key and value (using 0 for
+     * <code>null</code>). In other words, this must be:
+     * 
+<p><pre>(getKey() == null ? 0 : getKey().hashCode())
+^ (getValue() == null ? 0 : getValue().hashCode())</pre>
+     *
+     * @return the hash code
+     */
+    int hashCode();
+
+    /**
+     * Compares the specified object with this entry. Returns true only if
+     * the object is a mapping of identical key and value. In other words,
+     * this must be:
+     * 
+<p><pre>(o instanceof Map.Entry)
+&& (getKey() == null ? ((Map.Entry) o).getKey() == null
+                     : getKey().equals(((Map.Entry) o).getKey()))
+&& (getValue() == null ? ((Map.Entry) o).getValue() == null
+                       : getValue().equals(((Map.Entry) o).getValue()))</pre>
+     *
+     * @param o the object to compare
+     *
+     * @return <code>true</code> if it is equal
+     */
+    boolean equals(Object o);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingFormatArgumentException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingFormatArgumentException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingFormatArgumentException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingFormatArgumentException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,90 @@
+/* MissingFormatArgumentException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when the a format specification for a {@link Formatter}
+ * refers to an argument that is non-existent, or an argument index
+ * references a non-existent argument.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class MissingFormatArgumentException 
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 19190115L;
+
+  /**
+   * The format specification which contains the
+   * unmatched argument.
+   *
+   * @serial the format specification.
+   */
+  // Note: name fixed by serialization.
+  private String s;
+
+  /**
+   * Constructs a new <code>MissingFormatArgumentException</code>
+   * for a format specification, <code>s</code>, which refers
+   * to a non-existent argument.
+   *
+   * @param s the format specification.
+   * @throws NullPointerException if <code>s</code> is null.
+   */
+  public MissingFormatArgumentException(String s)
+  {
+    super("The specification, " + s + 
+	  ", refers to a non-existent argument.");
+    if (s == null)
+      throw new NullPointerException("The specification is null.");
+    this.s = s;
+  }
+
+  /**
+   * Returns the format specification.
+   *
+   * @return the format specification.
+   */
+  public String getFormatSpecifier()
+  {
+    return s;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingFormatWidthException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingFormatWidthException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingFormatWidthException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingFormatWidthException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,88 @@
+/* MissingFormatWidthException.java
+   Copyright (C) 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/** 
+ * Thrown when the a format specification for a {@link Formatter}
+ * does not include a width for a value where one is required.
+ *
+ * @author Tom Tromey (tromey at redhat.com)
+ * @author Andrew John Hughes (gnu_andrew at member.fsf.org)
+ * @since 1.5 
+ */
+public class MissingFormatWidthException 
+  extends IllegalFormatException
+{
+  private static final long serialVersionUID = 15560123L;
+
+  /**
+   * The format specification which contains the
+   * unmatched argument.
+   *
+   * @serial the format specification.
+   */
+  // Note: name fixed by serialization.
+  private String s;
+
+  /**
+   * Constructs a new <code>MissingFormatWidthException</code>
+   * for a format specification, <code>s</code>, which excludes
+   * a required width argument.
+   *
+   * @param s the format specification.
+   * @throws NullPointerException if <code>s</code> is null.
+   */
+  public MissingFormatWidthException(String s)
+  {
+    super("The specification, " + s + ", misses a required width.");
+    if (s == null)
+      throw new NullPointerException("The specification is null.");
+    this.s = s;
+  }
+
+  /**
+   * Returns the format specification.
+   *
+   * @return the format specification.
+   */
+  public String getFormatSpecifier()
+  {
+    return s;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingResourceException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingResourceException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingResourceException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/MissingResourceException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,105 @@
+/* MissingResourceException.java -- thrown for a missing resource
+   Copyright (C) 1998, 1999, 2001, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This exception is thrown when a resource is missing.
+ *
+ * @author Jochen Hoenicke
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @see ResourceBundle
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class MissingResourceException extends RuntimeException
+{
+  /**
+   * Compatible with JDK 1.1+.
+   */
+  private static final long serialVersionUID = -4876345176062000401L;
+
+  /**
+   * The name of the resource bundle requested by user.
+   *
+   * @serial the class name of the resource bundle
+   */
+  private final String className;
+
+  /**
+   * The key of the resource in the bundle requested by user.
+   *
+   * @serial the name of the resouce
+   */
+  private final String key;
+
+  /**
+   * Creates a new exception, with the specified parameters.
+   *
+   * @param s the detail message
+   * @param className the name of the resource bundle
+   * @param key the key of the missing resource
+   */
+  public MissingResourceException(String s, String className, String key)
+  {
+    super(s);
+    this.className = className;
+    this.key = key;
+  }
+
+  /**
+   * Gets the name of the resource bundle, for which a resource is missing.
+   *
+   * @return the name of the resource bundle
+   */
+  public String getClassName()
+  {
+    return className;
+  }
+
+  /**
+   * Gets the key of the resource that is missing bundle, this is an empty
+   * string if the whole resource bundle is missing.
+   *
+   * @return the name of the resource bundle
+   */
+  public String getKey()
+  {
+    return key;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/NoSuchElementException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/NoSuchElementException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/NoSuchElementException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/NoSuchElementException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,88 @@
+/* NoSuchElementException.java -- Attempt to access element that does not exist
+   Copyright (C) 1998, 1999, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ */
+
+/**
+ * Exception thrown when an attempt is made to access an element that does not
+ * exist. This exception is thrown by the Enumeration, Iterator and
+ * ListIterator classes if the nextElement, next or previous method goes
+ * beyond the end of the list of elements that are being accessed. It is also
+ * thrown by Vector and Stack when attempting to access the first or last
+ * element of an empty collection.
+ *
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Enumeration
+ * @see Iterator
+ * @see ListIterator
+ * @see Enumeration#nextElement()
+ * @see Iterator#next()
+ * @see ListIterator#previous()
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class NoSuchElementException extends RuntimeException
+{
+  /**
+   * Compatible with JDK 1.0.
+   */
+  private static final long serialVersionUID = 6769829250639411880L;
+
+  /**
+   * Constructs a NoSuchElementException with no detail message.
+   */
+  public NoSuchElementException()
+  {
+  }
+
+  /**
+   * Constructs a NoSuchElementException with a detail message.
+   *
+   * @param detail the detail message for the exception
+   */
+  public NoSuchElementException(String detail)
+  {
+    super(detail);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Observable.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Observable.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Observable.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Observable.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,182 @@
+/* Observable.java -- an object to be observed
+   Copyright (C) 1999, 2000, 2001, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This class represents an object which is observable.  Other objects may
+ * register their intent to be notified when this object changes; and when
+ * this object does change, it will trigger the <code>update</code> method
+ * of each observer.
+ *
+ * Note that the <code>notifyObservers()</code> method of this class is
+ * unrelated to the <code>notify()</code> of Object.
+ *
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Observer
+ * @status updated to 1.4
+ */
+public class Observable
+{
+  /** Tracks whether this object has changed. */
+  private boolean changed;
+
+  /* List of the Observers registered as interested in this Observable. */
+  private LinkedHashSet observers;
+
+  /**
+   * Constructs an Observable with zero Observers.
+   */
+  public Observable()
+  {
+    observers = new LinkedHashSet();
+  }
+
+  /**
+   * Adds an Observer. If the observer was already added this method does
+   * nothing.
+   *
+   * @param observer Observer to add
+   * @throws NullPointerException if observer is null
+   */
+  public synchronized void addObserver(Observer observer)
+  {
+    if (observer == null)
+      throw new NullPointerException("can't add null observer");
+    observers.add(observer);
+  }
+
+  /**
+   * Reset this Observable's state to unchanged. This is called automatically
+   * by <code>notifyObservers</code> once all observers have been notified.
+   *
+   * @see #notifyObservers()
+   */
+  protected synchronized void clearChanged()
+  {
+    changed = false;
+  }
+
+  /**
+   * Returns the number of observers for this object.
+   *
+   * @return number of Observers for this
+   */
+  public synchronized int countObservers()
+  {
+    return observers.size();
+  }
+
+  /**
+   * Deletes an Observer of this Observable.
+   *
+   * @param victim Observer to delete
+   */
+  public synchronized void deleteObserver(Observer victim)
+  {
+    observers.remove(victim);
+  }
+
+  /**
+   * Deletes all Observers of this Observable.
+   */
+  public synchronized void deleteObservers()
+  {
+    observers.clear();
+  }
+
+  /**
+   * True if <code>setChanged</code> has been called more recently than
+   * <code>clearChanged</code>.
+   *
+   * @return whether or not this Observable has changed
+   */
+  public synchronized boolean hasChanged()
+  {
+    return changed;
+  }
+
+  /**
+   * If the Observable has actually changed then tell all Observers about it,
+   * then reset state to unchanged.
+   *
+   * @see #notifyObservers(Object)
+   * @see Observer#update(Observable, Object)
+   */
+  public void notifyObservers()
+  {
+    notifyObservers(null);
+  }
+
+  /**
+   * If the Observable has actually changed then tell all Observers about it,
+   * then reset state to unchanged. Note that though the order of
+   * notification is unspecified in subclasses, in Observable it is in the
+   * order of registration.
+   *
+   * @param obj argument to Observer's update method
+   * @see Observer#update(Observable, Object)
+   */
+  public void notifyObservers(Object obj)
+  {
+    if (! hasChanged())
+      return;
+    // Create clone inside monitor, as that is relatively fast and still
+    // important to keep threadsafe, but update observers outside of the
+    // lock since update() can call arbitrary code.
+    Set s;
+    synchronized (this)
+      {
+        s = (Set) observers.clone();
+      }
+    int i = s.size();
+    Iterator iter = s.iterator();
+    while (--i >= 0)
+      ((Observer) iter.next()).update(this, obj);
+    clearChanged();
+  }
+
+  /**
+   * Marks this Observable as having changed.
+   */
+  protected synchronized void setChanged()
+  {
+    changed = true;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Observer.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Observer.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Observer.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Observer.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,60 @@
+/* Observer.java -- an object that will be informed of changes in an Observable
+   Copyright (C) 1998, 1999, 2001, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Interface that is implemented when a class wants to be informed of changes
+ * in Observable objects.
+ *
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @see Observable
+ * @status updated to 1.4
+ */
+public interface Observer
+{
+  /**
+   * This method is called whenever the observable object changes, and has
+   * called <code>notifyObservers</code>. The Observable object can pass
+   * arbitrary information in the second parameter.
+   *
+   * @param observable the Observable object that changed
+   * @param arg arbitrary information, usually relating to the change
+   */
+  void update(Observable observable, Object arg);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Properties.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Properties.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Properties.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Properties.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,801 @@
+/* Properties.java -- a set of persistent properties
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Element;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSSerializer;
+
+/**
+ * A set of persistent properties, which can be saved or loaded from a stream.
+ * A property list may also contain defaults, searched if the main list
+ * does not contain a property for a given key.
+ *
+ * An example of a properties file for the german language is given
+ * here.  This extends the example given in ListResourceBundle.
+ * Create a file MyResource_de.properties with the following contents
+ * and put it in the CLASSPATH.  (The character
+ * <code>\</code><code>u00e4</code> is the german umlaut)
+ *
+ * 
+<pre>s1=3
+s2=MeineDisk
+s3=3. M\<code></code>u00e4rz 96
+s4=Die Diskette ''{1}'' enth\<code></code>u00e4lt {0} in {2}.
+s5=0
+s6=keine Dateien
+s7=1
+s8=eine Datei
+s9=2
+s10={0,number} Dateien
+s11=Das Formatieren schlug fehl mit folgender Exception: {0}
+s12=FEHLER
+s13=Ergebnis
+s14=Dialog
+s15=Auswahlkriterium
+s16=1,3</pre>
+ *
+ * <p>Although this is a sub class of a hash table, you should never
+ * insert anything other than strings to this property, or several
+ * methods, that need string keys and values, will fail.  To ensure
+ * this, you should use the <code>get/setProperty</code> method instead
+ * of <code>get/put</code>.
+ *
+ * Properties are saved in ISO 8859-1 encoding, using Unicode escapes with
+ * a single <code>u</code> for any character which cannot be represented.
+ *
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see PropertyResourceBundle
+ * @status updated to 1.4
+ */
+public class Properties extends Hashtable
+{
+  // WARNING: Properties is a CORE class in the bootstrap cycle. See the
+  // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+  /**
+   * The property list that contains default values for any keys not
+   * in this property list.
+   *
+   * @serial the default properties
+   */
+  protected Properties defaults;
+
+  /**
+   * Compatible with JDK 1.0+.
+   */
+  private static final long serialVersionUID = 4112578634029874840L;
+
+  /**
+   * Creates a new empty property list with no default values.
+   */
+  public Properties()
+  {
+  }
+
+  /**
+   * Create a new empty property list with the specified default values.
+   *
+   * @param defaults a Properties object containing the default values
+   */
+  public Properties(Properties defaults)
+  {
+    this.defaults = defaults;
+  }
+
+  /**
+   * Adds the given key/value pair to this properties.  This calls
+   * the hashtable method put.
+   *
+   * @param key the key for this property
+   * @param value the value for this property
+   * @return The old value for the given key
+   * @see #getProperty(String)
+   * @since 1.2
+   */
+  public Object setProperty(String key, String value)
+  {
+    return put(key, value);
+  }
+
+  /**
+   * Reads a property list from an input stream.  The stream should
+   * have the following format: <br>
+   *
+   * An empty line or a line starting with <code>#</code> or
+   * <code>!</code> is ignored.  An backslash (<code>\</code>) at the
+   * end of the line makes the line continueing on the next line
+   * (but make sure there is no whitespace after the backslash).
+   * Otherwise, each line describes a key/value pair. <br>
+   *
+   * The chars up to the first whitespace, = or : are the key.  You
+   * can include this caracters in the key, if you precede them with
+   * a backslash (<code>\</code>). The key is followed by optional
+   * whitespaces, optionally one <code>=</code> or <code>:</code>,
+   * and optionally some more whitespaces.  The rest of the line is
+   * the resource belonging to the key. <br>
+   *
+   * Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a
+   * space), and unicode characters with the
+   * <code>\\u</code><em>xxxx</em> notation are detected, and
+   * converted to the corresponding single character. <br>
+   *
+   * 
+<pre># This is a comment
+key     = value
+k\:5      \ a string starting with space and ending with newline\n
+# This is a multiline specification; note that the value contains
+# no white space.
+weekdays: Sunday,Monday,Tuesday,Wednesday,\\
+          Thursday,Friday,Saturday
+# The safest way to include a space at the end of a value:
+label   = Name:\\u0020</pre>
+   *
+   * @param inStream the input stream
+   * @throws IOException if an error occurred when reading the input
+   * @throws NullPointerException if in is null
+   */
+  public void load(InputStream inStream) throws IOException
+  {
+    // The spec says that the file must be encoded using ISO-8859-1.
+    BufferedReader reader =
+      new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1"));
+    String line;
+
+    while ((line = reader.readLine()) != null)
+      {
+        char c = 0;
+        int pos = 0;
+	// Leading whitespaces must be deleted first.
+        while (pos < line.length()
+               && Character.isWhitespace(c = line.charAt(pos)))
+          pos++;
+
+        // If empty line or begins with a comment character, skip this line.
+        if ((line.length() - pos) == 0
+	    || line.charAt(pos) == '#' || line.charAt(pos) == '!')
+          continue;
+
+        // The characters up to the next Whitespace, ':', or '='
+        // describe the key.  But look for escape sequences.
+	// Try to short-circuit when there is no escape char.
+	int start = pos;
+	boolean needsEscape = line.indexOf('\\', pos) != -1;
+        StringBuilder key = needsEscape ? new StringBuilder() : null;
+        while (pos < line.length()
+               && ! Character.isWhitespace(c = line.charAt(pos++))
+               && c != '=' && c != ':')
+          {
+            if (needsEscape && c == '\\')
+              {
+                if (pos == line.length())
+                  {
+                    // The line continues on the next line.  If there
+                    // is no next line, just treat it as a key with an
+                    // empty value.
+                    line = reader.readLine();
+		    if (line == null)
+		      line = "";
+                    pos = 0;
+                    while (pos < line.length()
+                           && Character.isWhitespace(c = line.charAt(pos)))
+                      pos++;
+                  }
+                else
+                  {
+                    c = line.charAt(pos++);
+                    switch (c)
+                      {
+                      case 'n':
+                        key.append('\n');
+                        break;
+                      case 't':
+                        key.append('\t');
+                        break;
+                      case 'r':
+                        key.append('\r');
+                        break;
+                      case 'u':
+                        if (pos + 4 <= line.length())
+                          {
+                            char uni = (char) Integer.parseInt
+                              (line.substring(pos, pos + 4), 16);
+                            key.append(uni);
+                            pos += 4;
+                          }        // else throw exception?
+                        break;
+                      default:
+                        key.append(c);
+                        break;
+                      }
+                  }
+              }
+            else if (needsEscape)
+              key.append(c);
+          }
+
+        boolean isDelim = (c == ':' || c == '=');
+
+	String keyString;
+	if (needsEscape)
+	  keyString = key.toString();
+	else if (isDelim || Character.isWhitespace(c))
+	  keyString = line.substring(start, pos - 1);
+	else
+	  keyString = line.substring(start, pos);
+
+        while (pos < line.length()
+               && Character.isWhitespace(c = line.charAt(pos)))
+          pos++;
+
+        if (! isDelim && (c == ':' || c == '='))
+          {
+            pos++;
+            while (pos < line.length()
+                   && Character.isWhitespace(c = line.charAt(pos)))
+              pos++;
+          }
+
+	// Short-circuit if no escape chars found.
+	if (!needsEscape)
+	  {
+	    put(keyString, line.substring(pos));
+	    continue;
+	  }
+
+	// Escape char found so iterate through the rest of the line.
+        StringBuilder element = new StringBuilder(line.length() - pos);
+        while (pos < line.length())
+          {
+            c = line.charAt(pos++);
+            if (c == '\\')
+              {
+                if (pos == line.length())
+                  {
+                    // The line continues on the next line.
+                    line = reader.readLine();
+
+		    // We might have seen a backslash at the end of
+		    // the file.  The JDK ignores the backslash in
+		    // this case, so we follow for compatibility.
+		    if (line == null)
+		      break;
+
+                    pos = 0;
+                    while (pos < line.length()
+                           && Character.isWhitespace(c = line.charAt(pos)))
+                      pos++;
+                    element.ensureCapacity(line.length() - pos +
+                                           element.length());
+                  }
+                else
+                  {
+                    c = line.charAt(pos++);
+                    switch (c)
+                      {
+                      case 'n':
+                        element.append('\n');
+                        break;
+                      case 't':
+                        element.append('\t');
+                        break;
+                      case 'r':
+                        element.append('\r');
+                        break;
+                      case 'u':
+                        if (pos + 4 <= line.length())
+                          {
+                            char uni = (char) Integer.parseInt
+                              (line.substring(pos, pos + 4), 16);
+                            element.append(uni);
+                            pos += 4;
+                          }        // else throw exception?
+                        break;
+                      default:
+                        element.append(c);
+                        break;
+                      }
+                  }
+              }
+            else
+              element.append(c);
+          }
+        put(keyString, element.toString());
+      }
+  }
+
+  /**
+   * Calls <code>store(OutputStream out, String header)</code> and
+   * ignores the IOException that may be thrown.
+   *
+   * @param out the stream to write to
+   * @param header a description of the property list
+   * @throws ClassCastException if this property contains any key or
+   *         value that are not strings
+   * @deprecated use {@link #store(OutputStream, String)} instead
+   */
+  public void save(OutputStream out, String header)
+  {
+    try
+      {
+        store(out, header);
+      }
+    catch (IOException ex)
+      {
+      }
+  }
+
+  /**
+   * Writes the key/value pairs to the given output stream, in a format
+   * suitable for <code>load</code>.<br>
+   *
+   * If header is not null, this method writes a comment containing
+   * the header as first line to the stream.  The next line (or first
+   * line if header is null) contains a comment with the current date.
+   * Afterwards the key/value pairs are written to the stream in the
+   * following format.<br>
+   *
+   * Each line has the form <code>key = value</code>.  Newlines,
+   * Returns and tabs are written as <code>\n,\t,\r</code> resp.
+   * The characters <code>\, !, #, =</code> and <code>:</code> are
+   * preceeded by a backslash.  Spaces are preceded with a backslash,
+   * if and only if they are at the beginning of the key.  Characters
+   * that are not in the ascii range 33 to 127 are written in the
+   * <code>\</code><code>u</code>xxxx Form.<br>
+   *
+   * Following the listing, the output stream is flushed but left open.
+   *
+   * @param out the output stream
+   * @param header the header written in the first line, may be null
+   * @throws ClassCastException if this property contains any key or
+   *         value that isn't a string
+   * @throws IOException if writing to the stream fails
+   * @throws NullPointerException if out is null
+   * @since 1.2
+   */
+  public void store(OutputStream out, String header) throws IOException
+  {
+    // The spec says that the file must be encoded using ISO-8859-1.
+    PrintWriter writer
+      = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
+    if (header != null)
+      writer.println("#" + header);
+    writer.println ("#" + Calendar.getInstance ().getTime ());
+    
+    Iterator iter = entrySet ().iterator ();
+    int i = size ();
+    StringBuilder s = new StringBuilder (); // Reuse the same buffer.
+    while (--i >= 0)
+      {
+        Map.Entry entry = (Map.Entry) iter.next ();
+        formatForOutput ((String) entry.getKey (), s, true);
+        s.append ('=');
+        formatForOutput ((String) entry.getValue (), s, false);
+        writer.println (s);
+      }
+
+    writer.flush ();
+  }
+
+  /**
+   * Gets the property with the specified key in this property list.
+   * If the key is not found, the default property list is searched.
+   * If the property is not found in the default, null is returned.
+   *
+   * @param key The key for this property
+   * @return the value for the given key, or null if not found
+   * @throws ClassCastException if this property contains any key or
+   *         value that isn't a string
+   * @see #defaults
+   * @see #setProperty(String, String)
+   * @see #getProperty(String, String)
+   */
+  public String getProperty(String key)
+  {
+    Properties prop = this;
+    // Eliminate tail recursion.
+    do
+      {
+        String value = (String) prop.get(key);
+        if (value != null)
+          return value;
+        prop = prop.defaults;
+      }
+    while (prop != null);
+    return null;
+  }
+
+  /**
+   * Gets the property with the specified key in this property list.  If
+   * the key is not found, the default property list is searched.  If the
+   * property is not found in the default, the specified defaultValue is
+   * returned.
+   *
+   * @param key The key for this property
+   * @param defaultValue A default value
+   * @return The value for the given key
+   * @throws ClassCastException if this property contains any key or
+   *         value that isn't a string
+   * @see #defaults
+   * @see #setProperty(String, String)
+   */
+  public String getProperty(String key, String defaultValue)
+  {
+    String prop = getProperty(key);
+    if (prop == null)
+      prop = defaultValue;
+    return prop;
+  }
+
+  /**
+   * Returns an enumeration of all keys in this property list, including
+   * the keys in the default property list.
+   *
+   * @return an Enumeration of all defined keys
+   */
+  public Enumeration propertyNames()
+  {
+    // We make a new Set that holds all the keys, then return an enumeration
+    // for that. This prevents modifications from ruining the enumeration,
+    // as well as ignoring duplicates.
+    Properties prop = this;
+    Set s = new HashSet();
+    // Eliminate tail recursion.
+    do
+      {
+        s.addAll(prop.keySet());
+        prop = prop.defaults;
+      }
+    while (prop != null);
+    return Collections.enumeration(s);
+  }
+
+  /**
+   * Prints the key/value pairs to the given print stream.  This is 
+   * mainly useful for debugging purposes.
+   *
+   * @param out the print stream, where the key/value pairs are written to
+   * @throws ClassCastException if this property contains a key or a
+   *         value that isn't a string
+   * @see #list(PrintWriter)
+   */
+  public void list(PrintStream out)
+  {
+    PrintWriter writer = new PrintWriter (out);
+    list (writer);
+  }
+
+  /**
+   * Prints the key/value pairs to the given print writer.  This is
+   * mainly useful for debugging purposes.
+   *
+   * @param out the print writer where the key/value pairs are written to
+   * @throws ClassCastException if this property contains a key or a
+   *         value that isn't a string
+   * @see #list(PrintStream)
+   * @since 1.1
+   */
+  public void list(PrintWriter out)
+  {
+    out.println ("-- listing properties --");
+
+    Iterator iter = entrySet ().iterator ();
+    int i = size ();
+    while (--i >= 0)
+      {
+        Map.Entry entry = (Map.Entry) iter.next ();
+        out.print ((String) entry.getKey () + "=");
+
+        // JDK 1.3/1.4 restrict the printed value, but not the key,
+        // to 40 characters, including the truncating ellipsis.
+        String s = (String ) entry.getValue ();
+        if (s != null && s.length () > 40)
+          out.println (s.substring (0, 37) + "...");
+        else
+          out.println (s);
+      }
+    out.flush ();
+  }
+
+  /**
+   * Formats a key or value for output in a properties file.
+   * See store for a description of the format.
+   *
+   * @param str the string to format
+   * @param buffer the buffer to add it to
+   * @param key true if all ' ' must be escaped for the key, false if only
+   *        leading spaces must be escaped for the value
+   * @see #store(OutputStream, String)
+   */
+  private void formatForOutput(String str, StringBuilder buffer, boolean key)
+  {
+    if (key)
+      {
+        buffer.setLength(0);
+        buffer.ensureCapacity(str.length());
+      }
+    else
+      buffer.ensureCapacity(buffer.length() + str.length());
+    boolean head = true;
+    int size = str.length();
+    for (int i = 0; i < size; i++)
+      {
+        char c = str.charAt(i);
+        switch (c)
+          {
+          case '\n':
+            buffer.append("\\n");
+            break;
+          case '\r':
+            buffer.append("\\r");
+            break;
+          case '\t':
+            buffer.append("\\t");
+            break;
+          case ' ':
+            buffer.append(head ? "\\ " : " ");
+            break;
+          case '\\':
+          case '!':
+          case '#':
+          case '=':
+          case ':':
+            buffer.append('\\').append(c);
+            break;
+          default:
+            if (c < ' ' || c > '~')
+              {
+                String hex = Integer.toHexString(c);
+                buffer.append("\\u0000".substring(0, 6 - hex.length()));
+                buffer.append(hex);
+              }
+            else
+              buffer.append(c);
+          }
+        if (c != ' ')
+          head = key;
+      }
+  }
+
+  /**
+   * <p>
+   * Encodes the properties as an XML file using the UTF-8 encoding.
+   * The format of the XML file matches the DTD
+   * <a href="http://java.sun.com/dtd/properties.dtd">
+   * http://java.sun.com/dtd/properties.dtd</a>.
+   * </p>
+   * <p>
+   * Invoking this method provides the same behaviour as invoking
+   * <code>storeToXML(os, comment, "UTF-8")</code>.
+   * </p>
+   * 
+   * @param os the stream to output to.
+   * @param comment a comment to include at the top of the XML file, or
+   *                <code>null</code> if one is not required.
+   * @throws IOException if the serialization fails.
+   * @throws NullPointerException if <code>os</code> is null.
+   * @since 1.5
+   */
+  public void storeToXML(OutputStream os, String comment)
+    throws IOException
+  {
+    storeToXML(os, comment, "UTF-8");
+  }
+
+  /**
+   * <p>
+   * Encodes the properties as an XML file using the supplied encoding.
+   * The format of the XML file matches the DTD
+   * <a href="http://java.sun.com/dtd/properties.dtd">
+   * http://java.sun.com/dtd/properties.dtd</a>.
+   * </p>
+   * 
+   * @param os the stream to output to.
+   * @param comment a comment to include at the top of the XML file, or
+   *                <code>null</code> if one is not required.
+   * @param encoding the encoding to use for the XML output.
+   * @throws IOException if the serialization fails.
+   * @throws NullPointerException if <code>os</code> or <code>encoding</code>
+   *                              is null.
+   * @since 1.5
+   */
+  public void storeToXML(OutputStream os, String comment, String encoding)
+    throws IOException
+  {
+    if (os == null)
+      throw new NullPointerException("Null output stream supplied.");
+    if (encoding == null)
+      throw new NullPointerException("Null encoding supplied.");
+    try
+      {
+	DOMImplementationRegistry registry = 
+	  DOMImplementationRegistry.newInstance();
+	DOMImplementation domImpl = registry.getDOMImplementation("LS 3.0");
+	DocumentType doctype =
+	  domImpl.createDocumentType("properties", null,
+				     "http://java.sun.com/dtd/properties.dtd");
+	Document doc = domImpl.createDocument(null, "properties", doctype);
+	Element root = doc.getDocumentElement();
+	if (comment != null)
+	  {
+	    Element commentElement = doc.createElement("comment");
+	    commentElement.appendChild(doc.createTextNode(comment));
+	    root.appendChild(commentElement);
+	  }
+	Iterator iterator = entrySet().iterator();
+	while (iterator.hasNext())
+	  {
+	    Map.Entry entry = (Map.Entry) iterator.next();
+	    Element entryElement = doc.createElement("entry");
+	    entryElement.setAttribute("key", (String) entry.getKey());
+	    entryElement.appendChild(doc.createTextNode((String)
+							entry.getValue()));
+	    root.appendChild(entryElement);
+	  }
+	DOMImplementationLS loadAndSave = (DOMImplementationLS) domImpl;
+	LSSerializer serializer = loadAndSave.createLSSerializer();
+	LSOutput output = loadAndSave.createLSOutput();
+	output.setByteStream(os);
+	output.setEncoding(encoding);
+	serializer.write(doc, output);
+      }
+    catch (ClassNotFoundException e)
+      {
+	throw (IOException) 
+	  new IOException("The XML classes could not be found.").initCause(e);
+      }
+    catch (InstantiationException e)
+      {
+	throw (IOException)
+	  new IOException("The XML classes could not be instantiated.")
+	  .initCause(e);
+      }
+    catch (IllegalAccessException e)
+      {
+	throw (IOException)
+	  new IOException("The XML classes could not be accessed.")
+	  .initCause(e);
+      }
+  }
+
+  /**
+   * <p>
+   * Decodes the contents of the supplied <code>InputStream</code> as
+   * an XML file, which represents a set of properties.  The format of
+   * the XML file must match the DTD
+   * <a href="http://java.sun.com/dtd/properties.dtd">
+   * http://java.sun.com/dtd/properties.dtd</a>.
+   * </p>
+   *
+   * @param in the input stream from which to receive the XML data.
+   * @throws IOException if an I/O error occurs in reading the input data.
+   * @throws InvalidPropertiesFormatException if the input data does not
+   *                                          constitute an XML properties
+   *                                          file.
+   * @throws NullPointerException if <code>in</code> is null.
+   * @since 1.5
+   */
+  public void loadFromXML(InputStream in)
+    throws IOException, InvalidPropertiesFormatException
+  {
+    if (in == null)
+      throw new NullPointerException("Null input stream supplied.");
+    try
+      {
+        XMLInputFactory factory = XMLInputFactory.newInstance();
+        // Don't resolve external entity references
+        factory.setProperty("javax.xml.stream.isSupportingExternalEntities",
+                            Boolean.FALSE);
+        XMLStreamReader reader = factory.createXMLStreamReader(in);
+        String name, key = null;
+        StringBuffer buf = null;
+        while (reader.hasNext())
+          {
+            switch (reader.next())
+              {
+              case XMLStreamConstants.START_ELEMENT:
+                name = reader.getLocalName();
+                if (buf == null && "entry".equals(name))
+                  {
+                    key = reader.getAttributeValue(null, "key");
+                    if (key == null)
+                      {
+                        String msg = "missing 'key' attribute";
+                        throw new InvalidPropertiesFormatException(msg);
+                      }
+                    buf = new StringBuffer();
+                  }
+                else if (!"properties".equals(name) && !"comment".equals(name))
+                  {
+                    String msg = "unexpected element name '" + name + "'";
+                    throw new InvalidPropertiesFormatException(msg);
+                  }
+                break;
+              case XMLStreamConstants.END_ELEMENT:
+                name = reader.getLocalName();
+                if (buf != null && "entry".equals(name))
+                  {
+                    put(key, buf.toString());
+                    buf = null;
+                  }
+                else if (!"properties".equals(name) && !"comment".equals(name))
+                  {
+                    String msg = "unexpected element name '" + name + "'";
+                    throw new InvalidPropertiesFormatException(msg);
+                  }
+                break;
+              case XMLStreamConstants.CHARACTERS:
+              case XMLStreamConstants.SPACE:
+              case XMLStreamConstants.CDATA:
+                if (buf != null)
+                  buf.append(reader.getText());
+                break;
+              }
+          }
+        reader.close();
+      }
+    catch (XMLStreamException e)
+      {
+	throw (InvalidPropertiesFormatException)
+	  new InvalidPropertiesFormatException("Error in parsing XML.").
+	  initCause(e);
+      }
+  }
+
+} // class Properties

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyPermission.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyPermission.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyPermission.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyPermission.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,271 @@
+/* PropertyPermission.java -- permission to get and set System properties
+   Copyright (C) 1999, 2000, 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+
+/**
+ * This class represents the permission to access and modify a property.<br>
+ *
+ * The name is the name of the property, e.g. xxx.  You can also
+ * use an asterisk "*" as described in BasicPermission.<br>
+ *
+ * The action string is a comma-separated list of keywords.  There are
+ * two possible actions:
+ * <dl>
+ * <dt>read</dt>
+ * <dd>Allows to read the property via <code>System.getProperty</code>.</dd>
+ * <dt>write</dt>
+ * <dd>Allows to write the property via <code>System.setProperty</code>.</dd>
+ * </dl>
+ *
+ * The action string is case insensitive (it is converted to lower case).
+ *
+ * @see Permission
+ * @see BasicPermission
+ * @see SecurityManager
+ * @author Jochen Hoenicke
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class PropertyPermission extends BasicPermission
+{
+  /**
+   * PropertyPermission uses a more efficient representation than the
+   * serialized form; this documents the difference.
+   *
+   * @serialField action String the action string
+   */
+  private static final ObjectStreamField[] serialPersistentFields =
+  {
+    new ObjectStreamField("action", String.class)
+  };
+
+  /**
+   * Compatible with JDK 1.2+.
+   */
+  private static final long serialVersionUID = 885438825399942851L;
+
+  /** Permission to read. */
+  private static final int READ = 1;
+  /** Permission to write. */
+  private static final int WRITE = 2;
+
+  /** The set of actions permitted. */
+  // Package visible for use by PropertyPermissionCollection.
+  transient int actions;
+
+  /**
+   * The String forms of the actions permitted.
+   */
+  private static final String actionStrings[] =
+  {
+    "", "read", "write", "read,write"
+  };
+
+  /**
+   * Constructs a PropertyPermission with the specified property.  Possible
+   * actions are read and write, comma-separated and case-insensitive.
+   *
+   * @param name the name of the property
+   * @param actions the action string
+   * @throws NullPointerException if name is null
+   * @throws IllegalArgumentException if name string contains an
+   *         illegal wildcard or actions string contains an illegal action
+   *         (this includes a null actions string)
+   */
+  public PropertyPermission(String name, String actions)
+  {
+    super(name);
+    if (actions == null)
+      throw new IllegalArgumentException();
+    setActions(actions);
+  }
+
+  /**
+   * Parse the action string and convert actions from external to internal
+   * form.  This will set the internal actions field.
+   *
+   * @param str the action string
+   * @throws IllegalArgumentException if actions string contains an
+   *         illegal action
+   */
+  private void setActions(String str)
+  {
+    // Initialising the class java.util.Locale ...
+    //    tries to initialise the Locale.defaultLocale static
+    //    which calls System.getProperty, 
+    //    which calls SecurityManager.checkPropertiesAccess,
+    //    which creates a PropertyPermission with action "read,write",
+    //    which calls setActions("read,write").
+    // If we now were to call toLowerCase on 'str',
+    //    this would call Locale.getDefault() which returns null
+    //       because Locale.defaultLocale hasn't been set yet
+    //    then toLowerCase will fail with a null pointer exception.
+    // 
+    // The solution is to take a punt on 'str' being lower case, and
+    // test accordingly.  If that fails, we convert 'str' to lower case 
+    // and try the tests again.
+    if ("read".equals(str))
+      actions = READ;
+    else if ("write".equals(str))
+      actions = WRITE;
+    else if ("read,write".equals(str) || "write,read".equals(str))
+      actions = READ | WRITE;
+    else
+      {
+	String lstr = str.toLowerCase();
+	if ("read".equals(lstr))
+ 	  actions = READ;
+	else if ("write".equals(lstr))
+	  actions = WRITE;
+	else if ("read,write".equals(lstr) || "write,read".equals(lstr))
+	  actions = READ | WRITE;
+	else
+	  throw new IllegalArgumentException("illegal action " + str);
+      }
+  }
+
+  /**
+   * Reads an object from the stream. This converts the external to the
+   * internal representation.
+   *
+   * @param s the stream to read from
+   * @throws IOException if the stream fails
+   * @throws ClassNotFoundException if reserialization fails
+   */
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException
+  {
+    ObjectInputStream.GetField fields = s.readFields();
+    setActions((String) fields.get("actions", null));
+  }
+
+  /**
+   * Writes an object to the stream. This converts the internal to the
+   * external representation.
+   *
+   * @param s the stram to write to
+   * @throws IOException if the stream fails
+   */
+  private void writeObject(ObjectOutputStream s) throws IOException
+  {
+    ObjectOutputStream.PutField fields = s.putFields();
+    fields.put("actions", getActions());
+    s.writeFields();
+  }
+
+  /**
+   * Check if this permission implies p.  This returns true iff all of
+   * the following conditions are true:
+   * <ul>
+   * <li> p is a PropertyPermission </li>
+   * <li> this.getName() implies p.getName(),
+   *  e.g. <code>java.*</code> implies <code>java.home</code> </li>
+   * <li> this.getActions is a subset of p.getActions </li>
+   * </ul>
+   *
+   * @param p the permission to check
+   * @return true if this permission implies p
+   */
+  public boolean implies(Permission p)
+  {
+    // BasicPermission checks for name and type.
+    if (super.implies(p))
+      {
+        // We have to check the actions.
+        PropertyPermission pp = (PropertyPermission) p;
+        return (pp.actions & ~actions) == 0;
+      }
+    return false;
+  }
+
+  /**
+   * Check to see whether this object is the same as another
+   * PropertyPermission object; this is true if it has the same name and
+   * actions.
+   *
+   * @param obj the other object
+   * @return true if the two are equivalent
+   */
+  public boolean equals(Object obj)
+  {
+    return super.equals(obj) && actions == ((PropertyPermission) obj).actions;
+  }
+
+  /**
+   * Returns the hash code for this permission.  It is equivalent to
+   * <code>getName().hashCode()</code>.
+   *
+   * @return the hash code
+   */
+  public int hashCode()
+  {
+    return super.hashCode();
+  }
+
+  /**
+   * Returns the action string.  Note that this may differ from the string
+   * given at the constructor:  The actions are converted to lowercase and
+   * may be reordered.
+   *
+   * @return one of "read", "write", or "read,write"
+   */
+  public String getActions()
+  {
+    return actionStrings[actions];
+  }
+
+  /**
+   * Returns a permission collection suitable to take
+   * PropertyPermission objects.
+   *
+   * @return a new empty PermissionCollection
+   */
+  public PermissionCollection newPermissionCollection()
+  {
+    return new PropertyPermissionCollection();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyPermissionCollection.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyPermissionCollection.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyPermissionCollection.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyPermissionCollection.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,166 @@
+/* PropertyPermissionCollection.java -- a collection of PropertyPermissions
+   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.security.Permission;
+import java.security.PermissionCollection;
+
+/**
+ * This class provides the implementation for
+ * <code>PropertyPermission.newPermissionCollection()</code>. It only accepts
+ * PropertyPermissions, and correctly implements <code>implies</code>. It
+ * is synchronized, as specified in the superclass.
+ *
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @status an undocumented class, but this matches Sun's serialization
+ */
+class PropertyPermissionCollection extends PermissionCollection
+{
+  /**
+   * Compatible with JDK 1.4.
+   */
+  private static final long serialVersionUID = 7015263904581634791L;
+
+  /**
+   * The permissions.
+   *
+   * @serial the table of permissions in the collection
+   */
+  private final Hashtable permissions = new Hashtable();
+
+  /**
+   * A flag to detect if "*" is in the collection.
+   *
+   * @serial true if "*" is in the collection 
+   */
+  private boolean all_allowed;
+
+  /**
+   * Adds a PropertyPermission to this collection.
+   *
+   * @param permission the permission to add
+   * @throws IllegalArgumentException if permission is not a PropertyPermission
+   * @throws SecurityException if collection is read-only
+   */
+  public void add(Permission permission)
+  {
+    if (isReadOnly())
+      throw new SecurityException("readonly");
+    if (! (permission instanceof PropertyPermission))
+      throw new IllegalArgumentException();
+    PropertyPermission pp = (PropertyPermission) permission;
+    String name = pp.getName();
+    if (name.equals("*"))
+        all_allowed = true;
+    PropertyPermission old = (PropertyPermission) permissions.get(name);
+    if (old != null)
+      {
+        if ((pp.actions | old.actions) == old.actions)
+          pp = old; // Old implies pp.
+        else if ((pp.actions | old.actions) != pp.actions)
+          // Here pp doesn't imply old; the only case left is both actions.
+          pp = new PropertyPermission(name, "read,write");
+      }
+    permissions.put(name, pp);
+  }
+
+  /**
+   * Returns true if this collection implies the given permission. This even
+   * returns true for this case:
+   *
+   * <pre>
+   * collection.add(new PropertyPermission("a.*", "read"));
+   * collection.add(new PropertyPermission("a.b.*", "write"));
+   * collection.implies(new PropertyPermission("a.b.c", "read,write"));
+   * </pre>
+   *
+   * @param permission the permission to check
+   * @return true if it is implied by this
+   */
+  public boolean implies(Permission permission)
+  {
+    if (! (permission instanceof PropertyPermission))
+      return false;
+    PropertyPermission toImply = (PropertyPermission) permission;
+    int actions = toImply.actions;
+
+    if (all_allowed)
+      {
+        int all_actions = ((PropertyPermission) permissions.get("*")).actions;
+        actions &= ~all_actions;
+        if (actions == 0)
+          return true;
+      }
+
+    String name = toImply.getName();
+    if (name.equals("*"))
+      return false;
+
+    int prefixLength = name.length();
+    if (name.endsWith("*"))
+      prefixLength -= 2;
+
+    while (true)
+      {
+        PropertyPermission forName =
+          (PropertyPermission) permissions.get(name);
+        if (forName != null)
+          {
+            actions &= ~forName.actions;
+            if (actions == 0)
+              return true;
+          }
+
+        prefixLength = name.lastIndexOf('.', prefixLength - 1);
+        if (prefixLength < 0)
+          return false;
+        name = name.substring(0, prefixLength + 1) + '*';
+      }
+  }
+
+  /**
+   * Enumerate over the collection.
+   *
+   * @return an enumeration of the collection contents
+   */
+  public Enumeration elements()
+  {
+    return permissions.elements();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyResourceBundle.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyResourceBundle.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyResourceBundle.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/PropertyResourceBundle.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,152 @@
+/* PropertyResourceBundle -- a resource bundle built from a Property file
+   Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class is a concrete <code>ResourceBundle</code> that gets it
+ * resources from a property file. This implies that the resources are
+ * strings. For more information about resource bundles see the class
+ * <code>ResourceBundle</code>.
+ *
+ * You should not use this class directly, or subclass it, but you get
+ * an object of this class automatically when you call
+ * <code>ResourceBundle.getBundle()</code> and there is a properties
+ * file.
+ *
+ * If there is also a class for this resource and the same locale, the
+ * class will be chosen. The properties file should have the name of the
+ * resource bundle, appended with the locale (e.g. <code>_de</code> and the
+ * extension <code>.properties</code>. The file should have the same format
+ * as for <code>Properties.load()</code>
+ *
+ * An example of a properties file for the german language is given
+ * here. This extends the example given in ListResourceBundle.
+ * Create a file MyResource_de.properties with the following contents
+ * and put it in the CLASSPATH. (The char <code>\u00e4</code> is the
+ * german umlaut)
+ *
+ *
+<pre>
+s1=3
+s2=MeineDisk
+s3=3. M\u00e4rz 96
+s4=Die Diskette ''{1}'' enth\u00e4lt {0} in {2}.
+s5=0
+s6=keine Dateien
+s7=1
+s8=eine Datei
+s9=2
+s10={0,number} Dateien
+s11=Die Formatierung warf eine Exception: {0}
+s12=FEHLER
+s13=Ergebnis
+s14=Dialog
+s15=Auswahlkriterium
+s16=1,3
+</pre>
+ *
+ * @author Jochen Hoenicke
+ * @see ResourceBundle
+ * @see ListResourceBundle
+ * @see Properties#load(InputStream)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class PropertyResourceBundle extends ResourceBundle
+{
+  /** The properties file this bundle is based on. */
+  private Properties properties;
+
+  /**
+   * Creates a new property resource bundle.
+   *
+   * @param stream an input stream, where the resources are read from
+   * @throws NullPointerException if stream is null
+   * @throws IOException if reading the stream fails
+   */
+  public PropertyResourceBundle(InputStream stream) throws IOException
+  {
+    properties = new Properties();
+    properties.load(stream);
+  }
+
+  /**
+   * Called by <code>getObject</code> when a resource is needed. This
+   * returns the resource given by the key.
+   *
+   * @param key the key of the resource
+   * @return the resource for the key, or null if it doesn't exist
+   */
+  public Object handleGetObject(String key)
+  {
+    return properties.getProperty(key);
+  }
+
+  /**
+   * This method should return all keys for which a resource exists.
+   *
+   * @return an enumeration of the keys
+   */
+  public Enumeration getKeys()
+  {
+    if (parent == null)
+      return properties.propertyNames();
+    // We make a new Set that holds all the keys, then return an enumeration
+    // for that. This prevents modifications from ruining the enumeration,
+    // as well as ignoring duplicates.
+    Set s = new HashSet();
+    Enumeration e = properties.propertyNames();
+    while (e.hasMoreElements())
+      s.add(e.nextElement());
+    ResourceBundle bundle = parent;
+    // Eliminate tail recursion.
+    do
+      {
+        e = bundle.getKeys();
+        while (e.hasMoreElements())
+          s.add(e.nextElement());
+        bundle = bundle.parent;
+      }
+    while (bundle != null);
+    return Collections.enumeration(s);
+  }
+} // class PropertyResourceBundle

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Random.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Random.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Random.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Random.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,429 @@
+/* Random.java -- a pseudo-random number generator
+   Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * This class generates pseudorandom numbers.  It uses the same
+ * algorithm as the original JDK-class, so that your programs behave
+ * exactly the same way, if started with the same seed.
+ *
+ * The algorithm is described in <em>The Art of Computer Programming,
+ * Volume 2</em> by Donald Knuth in Section 3.2.1.  It is a 48-bit seed,
+ * linear congruential formula.
+ *
+ * If two instances of this class are created with the same seed and
+ * the same calls to these classes are made, they behave exactly the
+ * same way.  This should be even true for foreign implementations
+ * (like this), so every port must use the same algorithm as described
+ * here.
+ *
+ * If you want to implement your own pseudorandom algorithm, you
+ * should extend this class and overload the <code>next()</code> and
+ * <code>setSeed(long)</code> method.  In that case the above
+ * paragraph doesn't apply to you.
+ *
+ * This class shouldn't be used for security sensitive purposes (like
+ * generating passwords or encryption keys.  See <code>SecureRandom</code>
+ * in package <code>java.security</code> for this purpose.
+ *
+ * For simple random doubles between 0.0 and 1.0, you may consider using
+ * Math.random instead.
+ *
+ * @see java.security.SecureRandom
+ * @see Math#random()
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @status updated to 1.4
+ */
+public class Random implements Serializable
+{
+  /**
+   * True if the next nextGaussian is available.  This is used by
+   * nextGaussian, which generates two gaussian numbers by one call,
+   * and returns the second on the second call.
+   *
+   * @serial whether nextNextGaussian is available
+   * @see #nextGaussian()
+   * @see #nextNextGaussian
+   */
+  private boolean haveNextNextGaussian;
+
+  /**
+   * The next nextGaussian, when available.  This is used by nextGaussian,
+   * which generates two gaussian numbers by one call, and returns the
+   * second on the second call.
+   *
+   * @serial the second gaussian of a pair
+   * @see #nextGaussian()
+   * @see #haveNextNextGaussian
+   */
+  private double nextNextGaussian;
+
+  /**
+   * The seed.  This is the number set by setSeed and which is used
+   * in next.
+   *
+   * @serial the internal state of this generator
+   * @see #next(int)
+   */
+  private long seed;
+
+  /**
+   * Compatible with JDK 1.0+.
+   */
+  private static final long serialVersionUID = 3905348978240129619L;
+
+  /**
+   * Creates a new pseudorandom number generator.  The seed is initialized
+   * to the current time, as if by
+   * <code>setSeed(System.currentTimeMillis());</code>.
+   *
+   * @see System#currentTimeMillis()
+   */
+  public Random()
+  {
+    this(System.currentTimeMillis());
+  }
+
+  /**
+   * Creates a new pseudorandom number generator, starting with the
+   * specified seed, using <code>setSeed(seed);</code>.
+   *
+   * @param seed the initial seed
+   */
+  public Random(long seed)
+  {
+    setSeed(seed);
+  }
+
+  /**
+   * Sets the seed for this pseudorandom number generator.  As described
+   * above, two instances of the same random class, starting with the
+   * same seed, should produce the same results, if the same methods
+   * are called.  The implementation for java.util.Random is:
+   *
+<pre>public synchronized void setSeed(long seed)
+{
+  this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
+  haveNextNextGaussian = false;
+}</pre>
+   *
+   * @param seed the new seed
+   */
+  public synchronized void setSeed(long seed)
+  {
+    this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
+    haveNextNextGaussian = false;
+  }
+
+  /**
+   * Generates the next pseudorandom number.  This returns
+   * an int value whose <code>bits</code> low order bits are
+   * independent chosen random bits (0 and 1 are equally likely).
+   * The implementation for java.util.Random is:
+   *
+<pre>protected synchronized int next(int bits)
+{
+  seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
+  return (int) (seed >>> (48 - bits));
+}</pre>
+   *
+   * @param bits the number of random bits to generate, in the range 1..32
+   * @return the next pseudorandom value
+   * @since 1.1
+   */
+  protected synchronized int next(int bits)
+  {
+    seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
+    return (int) (seed >>> (48 - bits));
+  }
+
+  /**
+   * Fills an array of bytes with random numbers.  All possible values
+   * are (approximately) equally likely.
+   * The JDK documentation gives no implementation, but it seems to be:
+   *
+<pre>public void nextBytes(byte[] bytes)
+{
+  for (int i = 0; i < bytes.length; i += 4)
+  {
+    int random = next(32);
+    for (int j = 0; i + j < bytes.length && j < 4; j++)
+    {
+      bytes[i+j] = (byte) (random & 0xff)
+      random >>= 8;
+    }
+  }
+}</pre>
+   *
+   * @param bytes the byte array that should be filled
+   * @throws NullPointerException if bytes is null
+   * @since 1.1
+   */
+  public void nextBytes(byte[] bytes)
+  {
+    int random;
+    // Do a little bit unrolling of the above algorithm.
+    int max = bytes.length & ~0x3;
+    for (int i = 0; i < max; i += 4)
+      {
+        random = next(32);
+        bytes[i] = (byte) random;
+        bytes[i + 1] = (byte) (random >> 8);
+        bytes[i + 2] = (byte) (random >> 16);
+        bytes[i + 3] = (byte) (random >> 24);
+      }
+    if (max < bytes.length)
+      {
+        random = next(32);
+        for (int j = max; j < bytes.length; j++)
+          {
+            bytes[j] = (byte) random;
+            random >>= 8;
+          }
+      }
+  }
+
+  /**
+   * Generates the next pseudorandom number.  This returns
+   * an int value whose 32 bits are independent chosen random bits
+   * (0 and 1 are equally likely).  The implementation for
+   * java.util.Random is:
+   * 
+<pre>public int nextInt()
+{
+  return next(32);
+}</pre>
+   *
+   * @return the next pseudorandom value
+   */
+  public int nextInt()
+  {
+    return next(32);
+  }
+
+  /**
+   * Generates the next pseudorandom number.  This returns
+   * a value between 0(inclusive) and <code>n</code>(exclusive), and
+   * each value has the same likelihodd (1/<code>n</code>).
+   * (0 and 1 are equally likely).  The implementation for
+   * java.util.Random is:
+   * 
+<pre>
+public int nextInt(int n)
+{
+  if (n <= 0)
+    throw new IllegalArgumentException("n must be positive");
+
+  if ((n & -n) == n)  // i.e., n is a power of 2
+    return (int)((n * (long) next(31)) >> 31);
+
+  int bits, val;
+  do
+  {
+    bits = next(31);
+    val = bits % n;
+  }
+  while(bits - val + (n-1) < 0);
+
+  return val;
+}</pre>
+   *   
+   * <p>This algorithm would return every value with exactly the same
+   * probability, if the next()-method would be a perfect random number
+   * generator.
+   *
+   * The loop at the bottom only accepts a value, if the random
+   * number was between 0 and the highest number less then 1<<31,
+   * which is divisible by n.  The probability for this is high for small
+   * n, and the worst case is 1/2 (for n=(1<<30)+1).
+   *
+   * The special treatment for n = power of 2, selects the high bits of
+   * the random number (the loop at the bottom would select the low order
+   * bits).  This is done, because the low order bits of linear congruential
+   * number generators (like the one used in this class) are known to be
+   * ``less random'' than the high order bits.
+   *
+   * @param n the upper bound
+   * @throws IllegalArgumentException if the given upper bound is negative
+   * @return the next pseudorandom value
+   * @since 1.2
+   */
+  public int nextInt(int n)
+  {
+    if (n <= 0)
+      throw new IllegalArgumentException("n must be positive");
+    if ((n & -n) == n) // i.e., n is a power of 2
+      return (int) ((n * (long) next(31)) >> 31);
+    int bits, val;
+    do
+      {
+        bits = next(31);
+        val = bits % n;
+      }
+    while (bits - val + (n - 1) < 0);
+    return val;
+  }
+
+  /**
+   * Generates the next pseudorandom long number.  All bits of this
+   * long are independently chosen and 0 and 1 have equal likelihood.
+   * The implementation for java.util.Random is:
+   *
+<pre>public long nextLong()
+{
+  return ((long) next(32) << 32) + next(32);
+}</pre>
+   *
+   * @return the next pseudorandom value
+   */
+  public long nextLong()
+  {
+    return ((long) next(32) << 32) + next(32);
+  }
+
+  /**
+   * Generates the next pseudorandom boolean.  True and false have
+   * the same probability.  The implementation is:
+   * 
+<pre>public boolean nextBoolean()
+{
+  return next(1) != 0;
+}</pre>
+   *
+   * @return the next pseudorandom boolean
+   * @since 1.2
+   */
+  public boolean nextBoolean()
+  {
+    return next(1) != 0;
+  }
+
+  /**
+   * Generates the next pseudorandom float uniformly distributed
+   * between 0.0f (inclusive) and 1.0f (exclusive).  The
+   * implementation is as follows.
+   * 
+<pre>public float nextFloat()
+{
+  return next(24) / ((float)(1 << 24));
+}</pre>
+   *
+   * @return the next pseudorandom float
+   */
+  public float nextFloat()
+  {
+    return next(24) / (float) (1 << 24);
+  }
+
+  /**
+   * Generates the next pseudorandom double uniformly distributed
+   * between 0.0 (inclusive) and 1.0 (exclusive).  The
+   * implementation is as follows.
+   *
+<pre>public double nextDouble()
+{
+  return (((long) next(26) << 27) + next(27)) / (double)(1L << 53);
+}</pre>
+   *
+   * @return the next pseudorandom double
+   */
+  public double nextDouble()
+  {
+    return (((long) next(26) << 27) + next(27)) / (double) (1L << 53);
+  }
+
+  /**
+   * Generates the next pseudorandom, Gaussian (normally) distributed
+   * double value, with mean 0.0 and standard deviation 1.0.
+   * The algorithm is as follows.
+   * 
+<pre>public synchronized double nextGaussian()
+{
+  if (haveNextNextGaussian)
+  {
+    haveNextNextGaussian = false;
+    return nextNextGaussian;
+  }
+  else
+  {
+    double v1, v2, s;
+    do
+    {
+      v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
+      v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
+      s = v1 * v1 + v2 * v2;
+    }
+    while (s >= 1);
+
+    double norm = Math.sqrt(-2 * Math.log(s) / s);
+    nextNextGaussian = v2 * norm;
+    haveNextNextGaussian = true;
+    return v1 * norm;
+  }
+}</pre>
+   *
+   * <p>This is described in section 3.4.1 of <em>The Art of Computer
+   * Programming, Volume 2</em> by Donald Knuth.
+   *
+   * @return the next pseudorandom Gaussian distributed double
+   */
+  public synchronized double nextGaussian()
+  {
+    if (haveNextNextGaussian)
+      {
+        haveNextNextGaussian = false;
+        return nextNextGaussian;
+      }
+    double v1, v2, s;
+    do
+      {
+        v1 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
+        v2 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
+        s = v1 * v1 + v2 * v2;
+      }
+    while (s >= 1);
+    double norm = Math.sqrt(-2 * Math.log(s) / s);
+    nextNextGaussian = v2 * norm;
+    haveNextNextGaussian = true;
+    return v1 * norm;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/RandomAccess.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/RandomAccess.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/RandomAccess.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/RandomAccess.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,64 @@
+/* RandomAccess.java -- A tagging interface that lists can use to tailor
+   operations to the correct algorithm
+   Copyright (C) 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * Marker interface used to inform <code>List</code> implementations that
+ * they support fast (usually constant time) random access. This allows
+ * generic list algorithms to tailor their behavior based on the list
+ * type.
+ * <p>
+ *
+ * For example, some sorts are n*log(n) on an array, but decay to quadratic
+ * time on a linked list.  As a rule of thumb, this interface should be
+ * used is this loop:<br>
+ * <code>for (int i = 0, n = list.size(); i < n; i++) list.get(i);</code>
+ * <br>runs faster than this loop:<br>
+ * <code>for (Iterator i = list.iterator(); i.hasNext(); ) i.next();</code>
+ *
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see List
+ * @since 1.4
+ * @status updated to 1.4
+ */
+public interface RandomAccess
+{
+  // Tagging interface only.
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/ResourceBundle.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/ResourceBundle.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/ResourceBundle.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/ResourceBundle.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,581 @@
+/* ResourceBundle -- aids in loading resource bundles
+   Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.classpath.VMStackWalker;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A resource bundle contains locale-specific data. If you need localized
+ * data, you can load a resource bundle that matches the locale with
+ * <code>getBundle</code>. Now you can get your object by calling
+ * <code>getObject</code> or <code>getString</code> on that bundle.
+ *
+ * <p>When a bundle is demanded for a specific locale, the ResourceBundle
+ * is searched in following order (<i>def. language</i> stands for the
+ * two letter ISO language code of the default locale (see
+ * <code>Locale.getDefault()</code>).
+ *
+<pre>baseName_<i>language code</i>_<i>country code</i>_<i>variant</i>
+baseName_<i>language code</i>_<i>country code</i>
+baseName_<i>language code</i>
+baseName_<i>def. language</i>_<i>def. country</i>_<i>def. variant</i>
+baseName_<i>def. language</i>_<i>def. country</i>
+baseName_<i>def. language</i>
+baseName</pre>
+ *
+ * <p>A bundle is backed up by less specific bundles (omitting variant, country
+ * or language). But it is not backed up by the default language locale.
+ *
+ * <p>If you provide a bundle for a given locale, say
+ * <code>Bundle_en_UK_POSIX</code>, you must also provide a bundle for
+ * all sub locales, ie. <code>Bundle_en_UK</code>, <code>Bundle_en</code>, and
+ * <code>Bundle</code>.
+ *
+ * <p>When a bundle is searched, we look first for a class with the given
+ * name, then for a file with <code>.properties</code> extension in the
+ * classpath. The name must be a fully qualified classname (with dots as
+ * path separators).
+ *
+ * <p>(Note: This implementation always backs up the class with a properties
+ * file if that is existing, but you shouldn't rely on this, if you want to
+ * be compatible to the standard JDK.)
+ *
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Locale
+ * @see ListResourceBundle
+ * @see PropertyResourceBundle
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ResourceBundle
+{
+  /**
+   * The parent bundle. This is consulted when you call getObject and there
+   * is no such resource in the current bundle. This field may be null.
+   */
+  protected ResourceBundle parent;
+
+  /**
+   * The locale of this resource bundle. You can read this with
+   * <code>getLocale</code> and it is automatically set in
+   * <code>getBundle</code>.
+   */
+  private Locale locale;
+
+  /**
+   * The resource bundle cache.
+   */
+  private static Map bundleCache;
+
+  /**
+   * The last default Locale we saw. If this ever changes then we have to
+   * reset our caches.
+   */
+  private static Locale lastDefaultLocale;
+
+  /**
+   * The `empty' locale is created once in order to optimize
+   * tryBundle().
+   */
+  private static final Locale emptyLocale = new Locale("");
+
+  /**
+   * The constructor. It does nothing special.
+   */
+  public ResourceBundle()
+  {
+  }
+
+  /**
+   * Get a String from this resource bundle. Since most localized Objects
+   * are Strings, this method provides a convenient way to get them without
+   * casting.
+   *
+   * @param key the name of the resource
+   * @throws MissingResourceException if the resource can't be found
+   * @throws NullPointerException if key is null
+   * @throws ClassCastException if resource is not a string
+   */
+  public final String getString(String key)
+  {
+    return (String) getObject(key);
+  }
+
+  /**
+   * Get an array of Strings from this resource bundle. This method
+   * provides a convenient way to get it without casting.
+   *
+   * @param key the name of the resource
+   * @throws MissingResourceException if the resource can't be found
+   * @throws NullPointerException if key is null
+   * @throws ClassCastException if resource is not a string
+   */
+  public final String[] getStringArray(String key)
+  {
+    return (String[]) getObject(key);
+  }
+
+  /**
+   * Get an object from this resource bundle. This will call
+   * <code>handleGetObject</code> for this resource and all of its parents,
+   * until it finds a non-null resource.
+   *
+   * @param key the name of the resource
+   * @throws MissingResourceException if the resource can't be found
+   * @throws NullPointerException if key is null
+   */
+  public final Object getObject(String key)
+  {
+    for (ResourceBundle bundle = this; bundle != null; bundle = bundle.parent)
+      {
+        Object o = bundle.handleGetObject(key);
+        if (o != null)
+          return o;
+      }
+
+    String className = getClass().getName();
+    throw new MissingResourceException("Key '" + key
+				       + "'not found in Bundle: "
+				       + className, className, key);
+  }
+
+  /**
+   * Return the actual locale of this bundle. You can use it after calling
+   * getBundle, to know if the bundle for the desired locale was loaded or
+   * if the fall back was used.
+   *
+   * @return the bundle's locale
+   */
+  public Locale getLocale()
+  {
+    return locale;
+  }
+
+  /**
+   * Set the parent of this bundle. The parent is consulted when you call
+   * getObject and there is no such resource in the current bundle.
+   *
+   * @param parent the parent of this bundle
+   */
+  protected void setParent(ResourceBundle parent)
+  {
+    this.parent = parent;
+  }
+
+  /**
+   * Get the appropriate ResourceBundle for the default locale. This is like
+   * calling <code>getBundle(baseName, Locale.getDefault(),
+   * getClass().getClassLoader()</code>, except that any security check of
+   * getClassLoader won't fail.
+   *
+   * @param baseName the name of the ResourceBundle
+   * @return the desired resource bundle
+   * @throws MissingResourceException if the resource bundle can't be found
+   * @throws NullPointerException if baseName is null
+   */
+  public static ResourceBundle getBundle(String baseName)
+  {
+    ClassLoader cl = VMStackWalker.getCallingClassLoader();
+    if (cl == null)
+      cl = ClassLoader.getSystemClassLoader();
+    return getBundle(baseName, Locale.getDefault(), cl);
+  }
+
+  /**
+   * Get the appropriate ResourceBundle for the given locale. This is like
+   * calling <code>getBundle(baseName, locale,
+   * getClass().getClassLoader()</code>, except that any security check of
+   * getClassLoader won't fail.
+   *
+   * @param baseName the name of the ResourceBundle
+   * @param locale A locale
+   * @return the desired resource bundle
+   * @throws MissingResourceException if the resource bundle can't be found
+   * @throws NullPointerException if baseName or locale is null
+   */
+  public static ResourceBundle getBundle(String baseName, Locale locale)
+  {
+    ClassLoader cl = VMStackWalker.getCallingClassLoader();
+    if (cl == null)
+      cl = ClassLoader.getSystemClassLoader();
+    return getBundle(baseName, locale, cl);
+  }
+
+  /** Cache key for the ResourceBundle cache.  Resource bundles are keyed
+      by the combination of bundle name, locale, and class loader. */
+  private static class BundleKey
+  {
+    String baseName;
+    Locale locale;
+    ClassLoader classLoader;
+    int hashcode;
+
+    BundleKey() {}
+
+    BundleKey(String s, Locale l, ClassLoader cl)
+    {
+      set(s, l, cl);
+    }
+    
+    void set(String s, Locale l, ClassLoader cl)
+    {
+      baseName = s;
+      locale = l;
+      classLoader = cl;
+      hashcode = baseName.hashCode() ^ locale.hashCode() ^
+        classLoader.hashCode();
+    }
+    
+    public int hashCode()
+    {
+      return hashcode;
+    }
+    
+    public boolean equals(Object o)
+    {
+      if (! (o instanceof BundleKey))
+        return false;
+      BundleKey key = (BundleKey) o;
+      return hashcode == key.hashcode &&
+	baseName.equals(key.baseName) &&
+        locale.equals(key.locale) &&
+	classLoader.equals(key.classLoader);
+    }    
+  }
+  
+  /** A cache lookup key. This avoids having to a new one for every
+   *  getBundle() call. */
+  private static BundleKey lookupKey = new BundleKey();
+  
+  /** Singleton cache entry to represent previous failed lookups. */
+  private static Object nullEntry = new Object();
+
+  /**
+   * Get the appropriate ResourceBundle for the given locale. The following
+   * strategy is used:
+   *
+   * <p>A sequence of candidate bundle names are generated, and tested in
+   * this order, where the suffix 1 means the string from the specified
+   * locale, and the suffix 2 means the string from the default locale:</p>
+   *
+   * <ul>
+   * <li>baseName + "_" + language1 + "_" + country1 + "_" + variant1</li>
+   * <li>baseName + "_" + language1 + "_" + country1</li>
+   * <li>baseName + "_" + language1</li>
+   * <li>baseName + "_" + language2 + "_" + country2 + "_" + variant2</li>
+   * <li>baseName + "_" + language2 + "_" + country2</li>
+   * <li>baseName + "_" + language2</li>
+   * <li>baseName</li>
+   * </ul>
+   *
+   * <p>In the sequence, entries with an empty string are ignored. Next,
+   * <code>getBundle</code> tries to instantiate the resource bundle:</p>
+   *
+   * <ul>
+   * <li>First, an attempt is made to load a class in the specified classloader
+   * which is a subclass of ResourceBundle, and which has a public constructor
+   * with no arguments, via reflection.</li>
+   * <li>Next, a search is made for a property resource file, by replacing
+   * '.' with '/' and appending ".properties", and using
+   * ClassLoader.getResource(). If a file is found, then a
+   * PropertyResourceBundle is created from the file's contents.</li>
+   * </ul>
+   * If no resource bundle was found, a MissingResourceException is thrown.
+   *
+   * <p>Next, the parent chain is implemented. The remaining candidate names
+   * in the above sequence are tested in a similar manner, and if any results
+   * in a resource bundle, it is assigned as the parent of the first bundle
+   * using the <code>setParent</code> method (unless the first bundle already
+   * has a parent).</p>
+   *
+   * <p>For example, suppose the following class and property files are
+   * provided: MyResources.class, MyResources_fr_CH.properties,
+   * MyResources_fr_CH.class, MyResources_fr.properties,
+   * MyResources_en.properties, and MyResources_es_ES.class. The contents of
+   * all files are valid (that is, public non-abstract subclasses of
+   * ResourceBundle with public nullary constructors for the ".class" files,
+   * syntactically correct ".properties" files). The default locale is
+   * Locale("en", "UK").</p>
+   *
+   * <p>Calling getBundle with the shown locale argument values instantiates
+   * resource bundles from the following sources:</p>
+   *
+   * <ul>
+   * <li>Locale("fr", "CH"): result MyResources_fr_CH.class, parent
+   *   MyResources_fr.properties, parent MyResources.class</li>
+   * <li>Locale("fr", "FR"): result MyResources_fr.properties, parent
+   *   MyResources.class</li>
+   * <li>Locale("de", "DE"): result MyResources_en.properties, parent
+   *   MyResources.class</li>
+   * <li>Locale("en", "US"): result MyResources_en.properties, parent
+   *   MyResources.class</li>
+   * <li>Locale("es", "ES"): result MyResources_es_ES.class, parent
+   *   MyResources.class</li>
+   * </ul>
+   * 
+   * <p>The file MyResources_fr_CH.properties is never used because it is hidden
+   * by MyResources_fr_CH.class.</p>
+   *
+   * @param baseName the name of the ResourceBundle
+   * @param locale A locale
+   * @param classLoader a ClassLoader
+   * @return the desired resource bundle
+   * @throws MissingResourceException if the resource bundle can't be found
+   * @throws NullPointerException if any argument is null
+   * @since 1.2
+   */
+  // This method is synchronized so that the cache is properly
+  // handled.
+  public static synchronized ResourceBundle getBundle
+    (String baseName, Locale locale, ClassLoader classLoader)
+  {
+    // If the default locale changed since the last time we were called,
+    // all cache entries are invalidated.
+    Locale defaultLocale = Locale.getDefault();
+    if (defaultLocale != lastDefaultLocale)
+      {
+	bundleCache = new HashMap();
+	lastDefaultLocale = defaultLocale;
+      }
+
+    // This will throw NullPointerException if any arguments are null.
+    lookupKey.set(baseName, locale, classLoader);
+    
+    Object obj = bundleCache.get(lookupKey);
+    ResourceBundle rb = null;
+    
+    if (obj instanceof ResourceBundle)
+      {
+        return (ResourceBundle) obj;
+      }
+    else if (obj == nullEntry)
+      {
+        // Lookup has failed previously. Fall through.
+      }
+    else
+      {
+	// First, look for a bundle for the specified locale. We don't want
+	// the base bundle this time.
+	boolean wantBase = locale.equals(defaultLocale);
+	ResourceBundle bundle = tryBundle(baseName, locale, classLoader, 
+					  wantBase);
+
+        // Try the default locale if neccessary.
+	if (bundle == null && !locale.equals(defaultLocale))
+	  bundle = tryBundle(baseName, defaultLocale, classLoader, true);
+
+	BundleKey key = new BundleKey(baseName, locale, classLoader);
+        if (bundle == null)
+	  {
+	    // Cache the fact that this lookup has previously failed.
+	    bundleCache.put(key, nullEntry);
+	  }
+	else
+	  {
+            // Cache the result and return it.
+	    bundleCache.put(key, bundle);
+	    return bundle;
+	  }
+      }
+
+    throw new MissingResourceException("Bundle " + baseName 
+				       + " not found for locale "
+				       + locale
+				       + " by classloader "
+				       + classLoader,
+				       baseName, "");
+  }
+
+  /**
+   * Override this method to provide the resource for a keys. This gets
+   * called by <code>getObject</code>. If you don't have a resource
+   * for the given key, you should return null instead throwing a
+   * MissingResourceException. You don't have to ask the parent, getObject()
+   * already does this; nor should you throw a MissingResourceException.
+   *
+   * @param key the key of the resource
+   * @return the resource for the key, or null if not in bundle
+   * @throws NullPointerException if key is null
+   */
+  protected abstract Object handleGetObject(String key);
+
+  /**
+   * This method should return all keys for which a resource exists; you
+   * should include the enumeration of any parent's keys, after filtering out
+   * duplicates.
+   *
+   * @return an enumeration of the keys
+   */
+  public abstract Enumeration getKeys();
+
+  /**
+   * Tries to load a class or a property file with the specified name.
+   *
+   * @param localizedName the name
+   * @param classloader the classloader
+   * @return the resource bundle if it was loaded, otherwise the backup
+   */
+  private static ResourceBundle tryBundle(String localizedName,
+                                          ClassLoader classloader)
+  {
+    ResourceBundle bundle = null;
+    try
+      {
+        Class rbClass;
+        if (classloader == null)
+          rbClass = Class.forName(localizedName);
+        else
+          rbClass = classloader.loadClass(localizedName);
+	// Note that we do the check up front instead of catching
+	// ClassCastException.  The reason for this is that some crazy
+	// programs (Eclipse) have classes that do not extend
+	// ResourceBundle but that have the same name as a property
+	// bundle; in fact Eclipse relies on ResourceBundle not
+	// instantiating these classes.
+	if (ResourceBundle.class.isAssignableFrom(rbClass))
+	  bundle = (ResourceBundle) rbClass.newInstance();
+      }
+    catch (Exception ex) {}
+
+    if (bundle == null)
+      {
+	try
+	  {
+	    InputStream is;
+	    String resourceName
+	      = localizedName.replace('.', '/') + ".properties";
+	    if (classloader == null)
+	      is = ClassLoader.getSystemResourceAsStream(resourceName);
+	    else
+	      is = classloader.getResourceAsStream(resourceName);
+	    if (is != null)
+	      bundle = new PropertyResourceBundle(is);
+	  }
+	catch (IOException ex)
+	  {
+	    MissingResourceException mre = new MissingResourceException
+	      ("Failed to load bundle: " + localizedName, localizedName, "");
+	    mre.initCause(ex);
+	    throw mre;
+	  }
+      }
+
+    return bundle;
+  }
+
+  /**
+   * Tries to load a the bundle for a given locale, also loads the backup
+   * locales with the same language.
+   *
+   * @param baseName the raw bundle name, without locale qualifiers
+   * @param locale the locale
+   * @param classLoader the classloader
+   * @param wantBase whether a resource bundle made only from the base name
+   *        (with no locale information attached) should be returned.
+   * @return the resource bundle if it was loaded, otherwise the backup
+   */
+  private static ResourceBundle tryBundle(String baseName, Locale locale,
+                                          ClassLoader classLoader, 
+					  boolean wantBase)
+  {
+    String language = locale.getLanguage();
+    String country = locale.getCountry();
+    String variant = locale.getVariant();
+    
+    int baseLen = baseName.length();
+
+    // Build up a StringBuffer containing the complete bundle name, fully
+    // qualified by locale.
+    StringBuffer sb = new StringBuffer(baseLen + variant.length() + 7);
+
+    sb.append(baseName);
+    
+    if (language.length() > 0)
+      {
+	sb.append('_');
+	sb.append(language);
+	
+	if (country.length() > 0)
+	  {
+	    sb.append('_');
+	    sb.append(country);
+	    
+	    if (variant.length() > 0)
+	      {
+	        sb.append('_');
+		sb.append(variant);
+	      }
+	  }
+      }
+
+    // Now try to load bundles, starting with the most specialized name.
+    // Build up the parent chain as we go.
+    String bundleName = sb.toString();
+    ResourceBundle first = null; // The most specialized bundle.
+    ResourceBundle last = null; // The least specialized bundle.
+    
+    while (true)
+      {
+        ResourceBundle foundBundle = tryBundle(bundleName, classLoader);
+	if (foundBundle != null)
+	  {
+	    if (first == null)
+	      first = foundBundle;
+	    if (last != null)
+	      last.parent = foundBundle;
+	    foundBundle.locale = locale;
+	    last = foundBundle;
+	  }
+	int idx = bundleName.lastIndexOf('_');
+	// Try the non-localized base name only if we already have a
+	// localized child bundle, or wantBase is true.
+	if (idx > baseLen || (idx == baseLen && (first != null || wantBase)))
+	  bundleName = bundleName.substring(0, idx);
+	else
+	  break;
+      }
+    
+    return first;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Set.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Set.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Set.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Set.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,264 @@
+/* Set.java -- A collection that prohibits duplicates
+   Copyright (C) 1998, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A collection that contains no duplicates. In other words, for two set
+ * elements e1 and e2, <code>e1.equals(e2)</code> returns false. There
+ * are additional stipulations on <code>add</code>, <code>equals</code>
+ * and <code>hashCode</code>, as well as the requirements that constructors
+ * do not permit duplicate elements. The Set interface is incompatible with
+ * List; you cannot implement both simultaneously.
+ * <p>
+ *
+ * Note: Be careful about using mutable objects in sets.  In particular,
+ * if a mutable object changes to become equal to another set element, you
+ * have violated the contract.  As a special case of this, a Set is not
+ * allowed to be an element of itself, without risking undefined behavior.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Collection
+ * @see List
+ * @see SortedSet
+ * @see HashSet
+ * @see TreeSet
+ * @see LinkedHashSet
+ * @see AbstractSet
+ * @see Collections#singleton(Object)
+ * @see Collections#EMPTY_SET
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface Set extends Collection
+{
+  /**
+   * Adds the specified element to the set if it is not already present
+   * (optional operation). In particular, the comparison algorithm is
+   * <code>o == null ? e == null : o.equals(e)</code>. Sets need not permit
+   * all values, and may document what exceptions will be thrown if
+   * a value is not permitted.
+   *
+   * @param o the object to add
+   * @return true if the object was not previously in the set
+   * @throws UnsupportedOperationException if this operation is not allowed
+   * @throws ClassCastException if the class of o prevents it from being added
+   * @throws IllegalArgumentException if some aspect of o prevents it from
+   *         being added
+   * @throws NullPointerException if null is not permitted in this set
+   */
+  boolean add(Object o);
+
+  /**
+   * Adds all of the elements of the given collection to this set (optional
+   * operation). If the argument is also a Set, this returns the mathematical
+   * <i>union</i> of the two. The behavior is unspecified if the set is
+   * modified while this is taking place.
+   *
+   * @param c the collection to add
+   * @return true if the set changed as a result
+   * @throws UnsupportedOperationException if this operation is not allowed
+   * @throws ClassCastException if the class of an element prevents it from
+   *         being added
+   * @throws IllegalArgumentException if something about an element prevents
+   *         it from being added
+   * @throws NullPointerException if null is not permitted in this set, or
+   *         if the argument c is null
+   * @see #add(Object)
+   */
+  boolean addAll(Collection c);
+
+  /**
+   * Removes all elements from this set (optional operation). This set will
+   * be empty afterwords, unless an exception occurs.
+   *
+   * @throws UnsupportedOperationException if this operation is not allowed
+   */
+  void clear();
+
+  /**
+   * Returns true if the set contains the specified element. In other words,
+   * this looks for <code>o == null ? e == null : o.equals(e)</code>.
+   *
+   * @param o the object to look for
+   * @return true if it is found in the set
+   * @throws ClassCastException if the type of o is not a valid type
+   *         for this set.
+   * @throws NullPointerException if o is null and this set doesn't
+   *         support null values.
+   */
+  boolean contains(Object o);
+
+  /**
+   * Returns true if this set contains all elements in the specified
+   * collection. If the argument is also a set, this is the <i>subset</i>
+   * relationship.
+   *
+   * @param c the collection to check membership in
+   * @return true if all elements in this set are in c
+   * @throws NullPointerException if c is null
+   * @throws ClassCastException if the type of any element in c is not
+   *         a valid type for this set.
+   * @throws NullPointerException if some element of c is null and this
+   *         set doesn't support null values.
+   * @see #contains(Object)
+   */
+  boolean containsAll(Collection c);
+
+  /**
+   * Compares the specified object to this for equality. For sets, the object
+   * must be a set, the two must have the same size, and every element in
+   * one must be in the other.
+   *
+   * @param o the object to compare to
+   * @return true if it is an equal set
+   */
+  boolean equals(Object o);
+
+  /**
+   * Returns the hash code for this set. In order to satisfy the contract of
+   * equals, this is the sum of the hashcode of all elements in the set.
+   *
+   * @return the sum of the hashcodes of all set elements
+   * @see #equals(Object)
+   */
+  int hashCode();
+
+  /**
+   * Returns true if the set contains no elements.
+   *
+   * @return true if the set is empty
+   */
+  boolean isEmpty();
+
+  /**
+   * Returns an iterator over the set.  The iterator has no specific order,
+   * unless further specified.
+   *
+   * @return a set iterator
+   */
+  Iterator iterator();
+
+  /**
+   * Removes the specified element from this set (optional operation). If
+   * an element e exists, <code>o == null ? e == null : o.equals(e)</code>,
+   * it is removed from the set.
+   *
+   * @param o the object to remove
+   * @return true if the set changed (an object was removed)
+   * @throws UnsupportedOperationException if this operation is not allowed
+   * @throws ClassCastException if the type of o is not a valid type
+   *         for this set.
+   * @throws NullPointerException if o is null and this set doesn't allow
+   *         the removal of a null value.
+   */
+  boolean remove(Object o);
+
+  /**
+   * Removes from this set all elements contained in the specified collection
+   * (optional operation). If the argument is a set, this returns the
+   * <i>asymmetric set difference</i> of the two sets.
+   *
+   * @param c the collection to remove from this set
+   * @return true if this set changed as a result
+   * @throws UnsupportedOperationException if this operation is not allowed
+   * @throws NullPointerException if c is null
+   * @throws ClassCastException if the type of any element in c is not
+   *         a valid type for this set.
+   * @throws NullPointerException if some element of c is null and this
+   *         set doesn't support removing null values.
+   * @see #remove(Object)
+   */
+  boolean removeAll(Collection c);
+
+  /**
+   * Retains only the elements in this set that are also in the specified
+   * collection (optional operation). If the argument is also a set, this
+   * performs the <i>intersection</i> of the two sets.
+   *
+   * @param c the collection to keep
+   * @return true if this set was modified
+   * @throws UnsupportedOperationException if this operation is not allowed
+   * @throws NullPointerException if c is null
+   * @throws ClassCastException if the type of any element in c is not
+   *         a valid type for this set.
+   * @throws NullPointerException if some element of c is null and this
+   *         set doesn't support retaining null values.
+   * @see #remove(Object)
+   */
+  boolean retainAll(Collection c);
+
+  /**
+   * Returns the number of elements in the set. If there are more
+   * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
+   * the <i>cardinality</i> of the set.
+   *
+   * @return the number of elements
+   */
+  int size();
+
+  /**
+   * Returns an array containing the elements of this set. If the set
+   * makes a guarantee about iteration order, the array has the same
+   * order. The array is distinct from the set; modifying one does not
+   * affect the other.
+   *
+   * @return an array of this set's elements
+   * @see #toArray(Object[])
+   */
+  Object[] toArray();
+
+  /**
+   * Returns an array containing the elements of this set, of the same runtime
+   * type of the argument. If the given set is large enough, it is reused,
+   * and null is inserted in the first unused slot. Otherwise, reflection
+   * is used to build a new array. If the set makes a guarantee about iteration
+   * order, the array has the same order. The array is distinct from the set;
+   * modifying one does not affect the other.
+   *
+   * @param a the array to determine the return type; if it is big enough
+   *        it is used and returned
+   * @return an array holding the elements of the set
+   * @throws ArrayStoreException if the runtime type of a is not a supertype
+   *         of all elements in the set
+   * @throws NullPointerException if a is null
+   * @see #toArray()
+   */
+  Object[] toArray(Object[] a);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/SimpleTimeZone.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/SimpleTimeZone.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/SimpleTimeZone.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/SimpleTimeZone.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1078 @@
+/* java.util.SimpleTimeZone
+   Copyright (C) 1998, 1999, 2000, 2003, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+
+/**
+ * This class represents a simple time zone offset and handles
+ * daylight savings.  It can only handle one daylight savings rule, so
+ * it can't represent historical changes.
+ *
+ * This object is tightly bound to the Gregorian calendar.  It assumes
+ * a regular seven days week, and the month lengths are that of the
+ * Gregorian Calendar.  It can only handle daylight savings for years
+ * lying in the AD era.
+ *
+ * @see Calendar
+ * @see GregorianCalendar
+ * @author Jochen Hoenicke
+ */
+public class SimpleTimeZone extends TimeZone
+{
+  /**
+   * The raw time zone offset in milliseconds to GMT, ignoring
+   * daylight savings.
+   * @serial
+   */
+  private int rawOffset;
+
+  /**
+   * True, if this timezone uses daylight savings, false otherwise.
+   * @serial
+   */
+  private boolean useDaylight;
+
+  /**
+   * The daylight savings offset.  This is a positive offset in
+   * milliseconds with respect to standard time.  Typically this
+   * is one hour, but for some time zones this may be half an hour.
+   * @serial
+   * @since JDK1.1.4
+   */
+  private int dstSavings = 60 * 60 * 1000;
+
+  /**
+   * The first year, in which daylight savings rules applies.
+   * @serial
+   */
+  private int startYear;
+  private static final int DOM_MODE = 1;
+  private static final int DOW_IN_MONTH_MODE = 2;
+  private static final int DOW_GE_DOM_MODE = 3;
+  private static final int DOW_LE_DOM_MODE = 4;
+
+  /**
+   * The mode of the start rule. This takes one of the following values:
+   * <dl>
+   * <dt>DOM_MODE (1)</dt>
+   * <dd> startDay contains the day in month of the start date,
+   * startDayOfWeek is unused. </dd>
+   * <dt>DOW_IN_MONTH_MODE (2)</dt>
+   * <dd> The startDay gives the day of week in month, and
+   * startDayOfWeek the day of week.  For example startDay=2 and
+   * startDayOfWeek=Calender.SUNDAY specifies that the change is on
+   * the second sunday in that month.  You must make sure, that this
+   * day always exists (ie. don't specify the 5th sunday).
+   * </dd>
+   * <dt>DOW_GE_DOM_MODE (3)</dt>
+   * <dd> The start is on the first startDayOfWeek on or after
+   * startDay.  For example startDay=13 and
+   * startDayOfWeek=Calendar.FRIDAY specifies that the daylight
+   * savings start on the first FRIDAY on or after the 13th of that
+   * Month. Make sure that the change is always in the given month, or
+   * the result is undefined.
+   * </dd>
+   * <dt>DOW_LE_DOM_MONTH (4)</dt>
+   * <dd> The start is on the first startDayOfWeek on or before the
+   * startDay.  Make sure that the change is always in the given
+   * month, or the result is undefined.
+   </dd>
+   * </dl>
+   * @serial */
+  private int startMode;
+
+  /**
+   * The month in which daylight savings start.  This is one of the
+   * constants Calendar.JANUARY, ..., Calendar.DECEMBER.
+   * @serial
+   */
+  private int startMonth;
+
+  /**
+   * This variable can have different meanings.  See startMode for details
+   * @see #startMode
+   * @serial
+   */
+  private int startDay;
+
+  /**
+   * This variable specifies the day of week the change takes place.  If
+   * startMode == DOM_MODE, this is undefined.
+   * @serial
+   * @see #startMode
+   */
+  private int startDayOfWeek;
+
+  /**
+   * This variable specifies the time of change to daylight savings.
+   * This time is given in milliseconds after midnight local
+   * standard time.
+   * @serial
+   */
+  private int startTime;
+
+  /**
+   * This variable specifies the mode that startTime is specified in.  By
+   * default it is WALL_TIME, but can also be STANDARD_TIME or UTC_TIME.  For
+   * startTime, STANDARD_TIME and WALL_TIME are equivalent.
+   * @serial
+   */
+  private int startTimeMode = WALL_TIME;
+
+  /**
+   * The month in which daylight savings ends.  This is one of the
+   * constants Calendar.JANUARY, ..., Calendar.DECEMBER.
+   * @serial
+   */
+  private int endMonth;
+
+  /**
+   * This variable gives the mode for the end of daylight savings rule.
+   * It can take the same values as startMode.
+   * @serial
+   * @see #startMode
+   */
+  private int endMode;
+
+  /**
+   * This variable can have different meanings.  See startMode for details
+   * @serial
+   * @see #startMode
+   */
+  private int endDay;
+
+  /**
+   * This variable specifies the day of week the change takes place.  If
+   * endMode == DOM_MODE, this is undefined.
+   * @serial
+   * @see #startMode
+   */
+  private int endDayOfWeek;
+
+  /**
+   * This variable specifies the time of change back to standard time.
+   * This time is given in milliseconds after midnight local
+   * standard time.
+   * @serial
+   */
+  private int endTime;
+
+  /**
+   * This variable specifies the mode that endTime is specified in.  By
+   * default it is WALL_TIME, but can also be STANDARD_TIME or UTC_TIME.
+   * @serial
+   */
+  private int endTimeMode = WALL_TIME;
+
+  /**
+   * This variable points to a deprecated array from JDK 1.1.  It is
+   * ignored in JDK 1.2 but streamed out for compatibility with JDK 1.1.
+   * The array contains the lengths of the months in the year and is
+   * assigned from a private static final field to avoid allocating
+   * the array for every instance of the object.
+   * Note that static final fields are not serialized.
+   * @serial
+   */
+  private byte[] monthLength = monthArr;
+  private static final byte[] monthArr = 
+                                         {
+                                           31, 28, 31, 30, 31, 30, 31, 31, 30,
+                                           31, 30, 31
+                                         };
+
+  /**
+   * The version of the serialized data on the stream.
+   * <dl>
+   * <dt>0 or not present on stream</dt>
+   * <dd> JDK 1.1.3 or earlier, only provides this fields:
+   * rawOffset, startDay, startDayOfWeek, startMonth, startTime,
+   * startYear, endDay, endDayOfWeek, endMonth, endTime
+   * </dd>
+   * <dd> JDK 1.1.4 or later. This includes three new fields, namely
+   * startMode, endMode and dstSavings.  And there is a optional section
+   * as described in writeObject.
+   * </dd>
+   * </dl>
+   *
+   * XXX - JDK 1.2 Beta 4 docu states 1.1.4, but my 1.1.5 has the old
+   * version.
+   *
+   * When streaming out this class it is always written in the latest
+   * version.
+   * @serial
+   * @since JDK1.1.4
+   */
+  private int serialVersionOnStream = 2;
+  private static final long serialVersionUID = -403250971215465050L;
+
+  /**
+   * Constant to indicate that start and end times are specified in standard
+   * time, without adjusting for daylight savings.
+   */
+  public static final int STANDARD_TIME = 1;
+
+  /**
+   * Constant to indicate that start and end times are specified in wall
+   * time, adjusting for daylight savings.  This is the default.
+   */
+  public static final int WALL_TIME = 0;
+
+  /**
+   * Constant to indicate that start and end times are specified in UTC.
+   */
+  public static final int UTC_TIME = 2;
+
+  /**
+   * Create a <code>SimpleTimeZone</code> with the given time offset
+   * from GMT and without daylight savings.
+   * @param rawOffset the time offset from GMT in milliseconds.
+   * @param id The identifier of this time zone.
+   */
+  public SimpleTimeZone(int rawOffset, String id)
+  {
+    this.rawOffset = rawOffset;
+    setID(id);
+    useDaylight = false;
+    startYear = 0;
+  }
+
+  /**
+   * Create a <code>SimpleTimeZone</code> with the given time offset
+   * from GMT and with daylight savings.  The start/end parameters
+   * can have different meaning (replace WEEKDAY with a real day of
+   * week). Only the first two meanings were supported by earlier
+   * versions of jdk.
+   *
+   * <dl>
+   * <dt><code>day > 0, dayOfWeek = Calendar.WEEKDAY</code></dt>
+   * <dd>The start/end of daylight savings is on the <code>day</code>-th
+   * <code>WEEKDAY</code> in the given month. </dd>
+   * <dt><code>day < 0, dayOfWeek = Calendar.WEEKDAY</code></dt>
+   * <dd>The start/end of daylight savings is on the <code>-day</code>-th
+   * <code>WEEKDAY</code> counted from the <i>end</i> of the month. </dd>
+   * <dt><code>day > 0, dayOfWeek = 0</code></dt>
+   * <dd>The start/end of daylight is on the <code>day</code>-th day of
+   * the month. </dd>
+   * <dt><code>day > 0, dayOfWeek = -Calendar.WEEKDAY</code></dt>
+   * <dd>The start/end of daylight is on the first WEEKDAY on or after
+   * the <code>day</code>-th day of the month.  You must make sure that
+   * this day lies in the same month. </dd>
+   * <dt><code>day < 0, dayOfWeek = -Calendar.WEEKDAY</code></dt>
+   * <dd>The start/end of daylight is on the first WEEKDAY on or
+   * <i>before</i> the <code>-day</code>-th day of the month.  You
+   * must make sure that this day lies in the same month. </dd>
+   * </dl>
+   *
+   * If you give a non existing month, a day that is zero, or too big,
+   * or a dayOfWeek that is too big,  the result is undefined.
+   *
+   * The start rule must have a different month than the end rule.
+   * This restriction shouldn't hurt for all possible time zones.
+   *
+   * @param rawOffset The time offset from GMT in milliseconds.
+   * @param id  The identifier of this time zone.
+   * @param startMonth The start month of daylight savings; use the
+   * constants in Calendar.
+   * @param startDayOfWeekInMonth A day in month or a day of week number, as
+   * described above.
+   * @param startDayOfWeek The start rule day of week; see above.
+   * @param startTime A time in millis in standard time.
+   * @param endMonth The end month of daylight savings; use the
+   * constants in Calendar.
+   * @param endDayOfWeekInMonth A day in month or a day of week number, as
+   * described above.
+   * @param endDayOfWeek The end rule day of week; see above.
+   * @param endTime A time in millis in standard time.
+   * @throws IllegalArgumentException if parameters are invalid or out of
+   * range.
+   */
+  public SimpleTimeZone(int rawOffset, String id, int startMonth,
+                        int startDayOfWeekInMonth, int startDayOfWeek,
+                        int startTime, int endMonth, int endDayOfWeekInMonth,
+                        int endDayOfWeek, int endTime)
+  {
+    this.rawOffset = rawOffset;
+    setID(id);
+    useDaylight = true;
+
+    setStartRule(startMonth, startDayOfWeekInMonth, startDayOfWeek, startTime);
+    setEndRule(endMonth, endDayOfWeekInMonth, endDayOfWeek, endTime);
+    if (startMonth == endMonth)
+      throw new IllegalArgumentException("startMonth and endMonth must be different");
+    this.startYear = 0;
+  }
+
+  /**
+   * This constructs a new SimpleTimeZone that supports a daylight savings
+   * rule.  The parameter are the same as for the constructor above, except
+   * there is the additional dstSavaings parameter.
+   *
+   * @param dstSavings the amount of savings for daylight savings
+   * time in milliseconds.  This must be positive.
+   * @since 1.2
+   */
+  public SimpleTimeZone(int rawOffset, String id, int startMonth,
+                        int startDayOfWeekInMonth, int startDayOfWeek,
+                        int startTime, int endMonth, int endDayOfWeekInMonth,
+                        int endDayOfWeek, int endTime, int dstSavings)
+  {
+    this(rawOffset, id, startMonth, startDayOfWeekInMonth, startDayOfWeek,
+         startTime, endMonth, endDayOfWeekInMonth, endDayOfWeek, endTime);
+
+    this.dstSavings = dstSavings;
+  }
+
+  /**
+   * This constructs a new SimpleTimeZone that supports a daylight savings
+   * rule.  The parameter are the same as for the constructor above, except
+   * there are the additional startTimeMode, endTimeMode, and dstSavings
+   * parameters.
+   *
+   * @param startTimeMode the mode that start times are specified in.  One of
+   * WALL_TIME, STANDARD_TIME, or UTC_TIME.
+   * @param endTimeMode the mode that end times are specified in.  One of
+   * WALL_TIME, STANDARD_TIME, or UTC_TIME.
+   * @param dstSavings the amount of savings for daylight savings
+   * time in milliseconds.  This must be positive.
+   * @throws IllegalArgumentException if parameters are invalid or out of
+   * range.
+   * @since 1.4
+   */
+  public SimpleTimeZone(int rawOffset, String id, int startMonth,
+                        int startDayOfWeekInMonth, int startDayOfWeek,
+                        int startTime, int startTimeMode, int endMonth,
+                        int endDayOfWeekInMonth, int endDayOfWeek,
+                        int endTime, int endTimeMode, int dstSavings)
+  {
+    this.rawOffset = rawOffset;
+    setID(id);
+    useDaylight = true;
+
+    if (startTimeMode < WALL_TIME || startTimeMode > UTC_TIME)
+      throw new IllegalArgumentException("startTimeMode must be one of WALL_TIME, STANDARD_TIME, or UTC_TIME");
+    if (endTimeMode < WALL_TIME || endTimeMode > UTC_TIME)
+      throw new IllegalArgumentException("endTimeMode must be one of WALL_TIME, STANDARD_TIME, or UTC_TIME");
+    this.startTimeMode = startTimeMode;
+    this.endTimeMode = endTimeMode;
+
+    setStartRule(startMonth, startDayOfWeekInMonth, startDayOfWeek, startTime);
+    setEndRule(endMonth, endDayOfWeekInMonth, endDayOfWeek, endTime);
+    if (startMonth == endMonth)
+      throw new IllegalArgumentException("startMonth and endMonth must be different");
+    this.startYear = 0;
+
+    this.dstSavings = dstSavings;
+  }
+
+  /**
+   * Sets the first year, where daylight savings applies.  The daylight
+   * savings rule never apply for years in the BC era.  Note that this
+   * is gregorian calendar specific.
+   * @param year the start year.
+   */
+  public void setStartYear(int year)
+  {
+    startYear = year;
+    useDaylight = true;
+  }
+
+  /**
+   * Checks if the month, day, dayOfWeek arguments are in range and
+   * returns the mode of the rule.
+   * @param month the month parameter as in the constructor
+   * @param day the day parameter as in the constructor
+   * @param dayOfWeek the day of week parameter as in the constructor
+   * @return the mode of this rule see startMode.
+   * @exception IllegalArgumentException if parameters are out of range.
+   * @see #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)
+   * @see #startMode
+   */
+  private int checkRule(int month, int day, int dayOfWeek)
+  {
+    if (month < 0 || month > 11)
+      throw new IllegalArgumentException("month out of range");
+
+    int daysInMonth = getDaysInMonth(month, 1);
+    if (dayOfWeek == 0)
+      {
+	if (day <= 0 || day > daysInMonth)
+	  throw new IllegalArgumentException("day out of range");
+	return DOM_MODE;
+      }
+    else if (dayOfWeek > 0)
+      {
+	if (Math.abs(day) > (daysInMonth + 6) / 7)
+	  throw new IllegalArgumentException("dayOfWeekInMonth out of range");
+	if (dayOfWeek > Calendar.SATURDAY)
+	  throw new IllegalArgumentException("dayOfWeek out of range");
+	return DOW_IN_MONTH_MODE;
+      }
+    else
+      {
+	if (day == 0 || Math.abs(day) > daysInMonth)
+	  throw new IllegalArgumentException("day out of range");
+	if (dayOfWeek < -Calendar.SATURDAY)
+	  throw new IllegalArgumentException("dayOfWeek out of range");
+	if (day < 0)
+	  return DOW_LE_DOM_MODE;
+	else
+	  return DOW_GE_DOM_MODE;
+      }
+  }
+
+  /**
+   * Sets the daylight savings start rule.  You must also set the
+   * end rule with <code>setEndRule</code> or the result of
+   * getOffset is undefined.  For the parameters see the ten-argument
+   * constructor above.
+   *
+   * @param month The month where daylight savings start, zero
+   * based.  You should use the constants in Calendar.
+   * @param day A day of month or day of week in month.
+   * @param dayOfWeek The day of week where daylight savings start.
+   * @param time The time in milliseconds standard time where daylight
+   * savings start.
+   * @exception IllegalArgumentException if parameters are out of range.
+   * @see SimpleTimeZone
+   */
+  public void setStartRule(int month, int day, int dayOfWeek, int time)
+  {
+    this.startMode = checkRule(month, day, dayOfWeek);
+    this.startMonth = month;
+    this.startDay = day;
+    this.startDayOfWeek = Math.abs(dayOfWeek);
+    if (this.startTimeMode == WALL_TIME || this.startTimeMode == STANDARD_TIME)
+      this.startTime = time;
+    else
+      // Convert from UTC to STANDARD
+      this.startTime = time + this.rawOffset;
+    useDaylight = true;
+  }
+
+  /**
+   * Sets the daylight savings start rule.  You must also set the
+   * end rule with <code>setEndRule</code> or the result of
+   * getOffset is undefined.  For the parameters see the ten-argument
+   * constructor above.
+   *
+   * Note that this API isn't incredibly well specified.  It appears that the
+   * after flag must override the parameters, since normally, the day and
+   * dayofweek can select this.  I.e., if day < 0 and dayOfWeek < 0, on or
+   * before mode is chosen.  But if after == true, this implementation
+   * overrides the signs of the other arguments.  And if dayOfWeek == 0, it
+   * falls back to the behavior in the other APIs.  I guess this should be
+   * checked against Sun's implementation.
+   *
+   * @param month The month where daylight savings start, zero
+   * based.  You should use the constants in Calendar.
+   * @param day A day of month or day of week in month.
+   * @param dayOfWeek The day of week where daylight savings start.
+   * @param time The time in milliseconds standard time where daylight
+   * savings start.
+   * @param after If true, day and dayOfWeek specify first day of week on or
+   * after day, else first day of week on or before.
+   * @since 1.2
+   * @see SimpleTimeZone
+   */
+  public void setStartRule(int month, int day, int dayOfWeek, int time,
+                           boolean after)
+  {
+    // FIXME: XXX: Validate that checkRule and offset processing work with on
+    // or before mode.
+    this.startDay = after ? Math.abs(day) : -Math.abs(day);
+    this.startDayOfWeek = after ? Math.abs(dayOfWeek) : -Math.abs(dayOfWeek);
+    this.startMode = (dayOfWeek != 0)
+                     ? (after ? DOW_GE_DOM_MODE : DOW_LE_DOM_MODE)
+                     : checkRule(month, day, dayOfWeek);
+    this.startDay = Math.abs(this.startDay);
+    this.startDayOfWeek = Math.abs(this.startDayOfWeek);
+
+    this.startMonth = month;
+
+    if (this.startTimeMode == WALL_TIME || this.startTimeMode == STANDARD_TIME)
+      this.startTime = time;
+    else
+      // Convert from UTC to STANDARD
+      this.startTime = time + this.rawOffset;
+    useDaylight = true;
+  }
+
+  /**
+   * Sets the daylight savings start rule.  You must also set the
+   * end rule with <code>setEndRule</code> or the result of
+   * getOffset is undefined.  For the parameters see the ten-argument
+   * constructor above.
+   *
+   * @param month The month where daylight savings start, zero
+   * based.  You should use the constants in Calendar.
+   * @param day A day of month or day of week in month.
+   * @param time The time in milliseconds standard time where daylight
+   * savings start.
+   * @see SimpleTimeZone
+   * @since 1.2
+   */
+  public void setStartRule(int month, int day, int time)
+  {
+    setStartRule(month, day, 0, time);
+  }
+
+  /**
+   * Sets the daylight savings end rule.  You must also set the
+   * start rule with <code>setStartRule</code> or the result of
+   * getOffset is undefined. For the parameters see the ten-argument
+   * constructor above.
+   *
+   * @param month The end month of daylight savings.
+   * @param day A day in month, or a day of week in month.
+   * @param dayOfWeek A day of week, when daylight savings ends.
+   * @param time A time in millis in standard time.
+   * @see #setStartRule(int, int, int, int)
+   */
+  public void setEndRule(int month, int day, int dayOfWeek, int time)
+  {
+    this.endMode = checkRule(month, day, dayOfWeek);
+    this.endMonth = month;
+    this.endDay = day;
+    this.endDayOfWeek = Math.abs(dayOfWeek);
+    if (this.endTimeMode == WALL_TIME)
+      this.endTime = time;
+    else if (this.endTimeMode == STANDARD_TIME)
+      // Convert from STANDARD to DST
+      this.endTime = time + this.dstSavings;
+    else
+      // Convert from UTC to DST
+      this.endTime = time + this.rawOffset + this.dstSavings;
+    useDaylight = true;
+  }
+
+  /**
+   * Sets the daylight savings end rule.  You must also set the
+   * start rule with <code>setStartRule</code> or the result of
+   * getOffset is undefined. For the parameters see the ten-argument
+   * constructor above.
+   *
+   * Note that this API isn't incredibly well specified.  It appears that the
+   * after flag must override the parameters, since normally, the day and
+   * dayofweek can select this.  I.e., if day < 0 and dayOfWeek < 0, on or
+   * before mode is chosen.  But if after == true, this implementation
+   * overrides the signs of the other arguments.  And if dayOfWeek == 0, it
+   * falls back to the behavior in the other APIs.  I guess this should be
+   * checked against Sun's implementation.
+   *
+   * @param month The end month of daylight savings.
+   * @param day A day in month, or a day of week in month.
+   * @param dayOfWeek A day of week, when daylight savings ends.
+   * @param time A time in millis in standard time.
+   * @param after If true, day and dayOfWeek specify first day of week on or
+   * after day, else first day of week on or before.
+   * @since 1.2
+   * @see #setStartRule(int, int, int, int, boolean)
+   */
+  public void setEndRule(int month, int day, int dayOfWeek, int time,
+                         boolean after)
+  {
+    // FIXME: XXX: Validate that checkRule and offset processing work with on
+    // or before mode.
+    this.endDay = after ? Math.abs(day) : -Math.abs(day);
+    this.endDayOfWeek = after ? Math.abs(dayOfWeek) : -Math.abs(dayOfWeek);
+    this.endMode = (dayOfWeek != 0)
+                   ? (after ? DOW_GE_DOM_MODE : DOW_LE_DOM_MODE)
+                   : checkRule(month, day, dayOfWeek);
+    this.endDay = Math.abs(this.endDay);
+    this.endDayOfWeek = Math.abs(endDayOfWeek);
+
+    this.endMonth = month;
+
+    if (this.endTimeMode == WALL_TIME)
+      this.endTime = time;
+    else if (this.endTimeMode == STANDARD_TIME)
+      // Convert from STANDARD to DST
+      this.endTime = time + this.dstSavings;
+    else
+      // Convert from UTC to DST
+      this.endTime = time + this.rawOffset + this.dstSavings;
+    useDaylight = true;
+  }
+
+  /**
+   * Sets the daylight savings end rule.  You must also set the
+   * start rule with <code>setStartRule</code> or the result of
+   * getOffset is undefined. For the parameters see the ten-argument
+   * constructor above.
+   *
+   * @param month The end month of daylight savings.
+   * @param day A day in month, or a day of week in month.
+   * @param time A time in millis in standard time.
+   * @see #setStartRule(int, int, int)
+   */
+  public void setEndRule(int month, int day, int time)
+  {
+    setEndRule(month, day, 0, time);
+  }
+
+  /**
+   * Gets the time zone offset, for current date, modified in case of
+   * daylight savings.  This is the offset to add to UTC to get the local
+   * time.
+   *
+   * In the standard JDK the results given by this method may result in
+   * inaccurate results at the end of February or the beginning of March.
+   * To avoid this, you should use Calendar instead:
+   * <code>offset = cal.get(Calendar.ZONE_OFFSET)
+   * + cal.get(Calendar.DST_OFFSET);</code>
+   *
+   * This version doesn't suffer this inaccuracy.
+   *
+   * The arguments don't follow the approach for setting start and end rules.
+   * The day must be a positive number and dayOfWeek must be a positive value
+   * from Calendar.  dayOfWeek is redundant, but must match the other values
+   * or an inaccurate result may be returned.
+   *
+   * @param era the era of the given date
+   * @param year the year of the given date
+   * @param month the month of the given date, 0 for January.
+   * @param day the day of month
+   * @param dayOfWeek the day of week; this must match the other fields.
+   * @param millis the millis in the day (in local standard time)
+   * @return the time zone offset in milliseconds.
+   * @throws IllegalArgumentException if arguments are incorrect.
+   */
+  public int getOffset(int era, int year, int month, int day, int dayOfWeek,
+                       int millis)
+  {
+    int daysInMonth = getDaysInMonth(month, year);
+    if (day < 1 || day > daysInMonth)
+      throw new IllegalArgumentException("day out of range");
+    if (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY)
+      throw new IllegalArgumentException("dayOfWeek out of range");
+    if (month < Calendar.JANUARY || month > Calendar.DECEMBER)
+      throw new IllegalArgumentException("month out of range:" + month);
+
+    // This method is called by Calendar, so we mustn't use that class.
+    int daylightSavings = 0;
+    if (useDaylight && era == GregorianCalendar.AD && year >= startYear)
+      {
+	// This does only work for Gregorian calendars :-(
+	// This is mainly because setStartYear doesn't take an era.
+	boolean afterStart = ! isBefore(year, month, day, dayOfWeek, millis,
+	                                startMode, startMonth, startDay,
+	                                startDayOfWeek, startTime);
+	boolean beforeEnd = isBefore(year, month, day, dayOfWeek,
+				     millis + dstSavings,
+	                             endMode, endMonth, endDay, endDayOfWeek,
+	                             endTime);
+
+	if (startMonth < endMonth)
+	  // use daylight savings, if the date is after the start of
+	  // savings, and before the end of savings.
+	  daylightSavings = afterStart && beforeEnd ? dstSavings : 0;
+	else
+	  // use daylight savings, if the date is before the end of
+	  // savings, or after the start of savings.
+	  daylightSavings = beforeEnd || afterStart ? dstSavings : 0;
+      }
+    return rawOffset + daylightSavings;
+  }
+
+  /**
+   * Returns the time zone offset to GMT in milliseconds, ignoring
+   * day light savings.
+   * @return the time zone offset.
+   */
+  public int getRawOffset()
+  {
+    return rawOffset;
+  }
+
+  /**
+   * Sets the standard time zone offset to GMT.
+   * @param rawOffset The time offset from GMT in milliseconds.
+   */
+  public void setRawOffset(int rawOffset)
+  {
+    this.rawOffset = rawOffset;
+  }
+
+  /**
+   * Gets the daylight savings offset.  This is a positive offset in
+   * milliseconds with respect to standard time.  Typically this
+   * is one hour, but for some time zones this may be half an our.
+   * @return the daylight savings offset in milliseconds.
+   *
+   * @since 1.2
+   */
+  public int getDSTSavings()
+  {
+    return dstSavings;
+  }
+
+  /**
+   * Sets the daylight savings offset.  This is a positive offset in
+   * milliseconds with respect to standard time.
+   *
+   * @param dstSavings the daylight savings offset in milliseconds.
+   *
+   * @since 1.2
+   */
+  public void setDSTSavings(int dstSavings)
+  {
+    if (dstSavings <= 0)
+      throw new IllegalArgumentException("illegal value for dstSavings");
+
+    this.dstSavings = dstSavings;
+  }
+
+  /**
+   * Returns if this time zone uses daylight savings time.
+   * @return true, if we use daylight savings time, false otherwise.
+   */
+  public boolean useDaylightTime()
+  {
+    return useDaylight;
+  }
+
+  /**
+   * Returns the number of days in the given month.
+   * Uses gregorian rules prior to 1582 (The default and earliest cutover)
+   * @param month The month, zero based; use one of the Calendar constants.
+   * @param year  The year.
+   */
+  private int getDaysInMonth(int month, int year)
+  {    
+    if (month == Calendar.FEBRUARY)
+      {
+	if ((year & 3) != 0)
+	  return 28;
+
+	// Assume default Gregorian cutover, 
+	// all years prior to this must be Julian
+	if (year < 1582)
+	  return 29;
+
+	// Gregorian rules 
+	return ((year % 100) != 0 || (year % 400) == 0) ? 29 : 28;
+      }
+    else
+      return monthArr[month];
+  }
+
+  /**
+   * Checks if the date given in calXXXX, is before the change between
+   * dst and standard time.
+   * @param calYear the year of the date to check (for leap day checking).
+   * @param calMonth the month of the date to check.
+   * @param calDayOfMonth the day of month of the date to check.
+   * @param calDayOfWeek the day of week of the date to check.
+   * @param calMillis the millis of day of the date to check (standard time).
+   * @param mode  the change mode; same semantic as startMode.
+   * @param month the change month; same semantic as startMonth.
+   * @param day   the change day; same semantic as startDay.
+   * @param dayOfWeek the change day of week;
+   * @param millis the change time in millis since midnight standard time.
+   * same semantic as startDayOfWeek.
+   * @return true, if cal is before the change, false if cal is on
+   * or after the change.
+   */
+  private boolean isBefore(int calYear, int calMonth, int calDayOfMonth,
+                           int calDayOfWeek, int calMillis, int mode,
+                           int month, int day, int dayOfWeek, int millis)
+  {
+    // This method is called by Calendar, so we mustn't use that class.
+    // We have to do all calculations by hand.
+    // check the months:
+    // XXX - this is not correct:
+    // for the DOW_GE_DOM and DOW_LE_DOM modes the change date may
+    // be in a different month.
+    if (calMonth != month)
+      return calMonth < month;
+
+    // check the day:
+    switch (mode)
+      {
+      case DOM_MODE:
+	if (calDayOfMonth != day)
+	  return calDayOfMonth < day;
+	break;
+      case DOW_IN_MONTH_MODE:
+        {
+	  // This computes the day of month of the day of type
+	  // "dayOfWeek" that lies in the same (sunday based) week as cal.
+	  calDayOfMonth += (dayOfWeek - calDayOfWeek);
+
+	  // Now we convert it to 7 based number (to get a one based offset
+	  // after dividing by 7).  If we count from the end of the
+	  // month, we get want a -7 based number counting the days from 
+	  // the end:
+	  if (day < 0)
+	    calDayOfMonth -= getDaysInMonth(calMonth, calYear) + 7;
+	  else
+	    calDayOfMonth += 6;
+
+	  //  day > 0                    day < 0
+	  //  S  M  T  W  T  F  S        S  M  T  W  T  F  S
+	  //     7  8  9 10 11 12         -36-35-34-33-32-31
+	  // 13 14 15 16 17 18 19      -30-29-28-27-26-25-24
+	  // 20 21 22 23 24 25 26      -23-22-21-20-19-18-17
+	  // 27 28 29 30 31 32 33      -16-15-14-13-12-11-10
+	  // 34 35 36                   -9 -8 -7
+	  // Now we calculate the day of week in month:
+	  int week = calDayOfMonth / 7;
+
+	  //  day > 0                    day < 0
+	  //  S  M  T  W  T  F  S        S  M  T  W  T  F  S
+	  //     1  1  1  1  1  1          -5 -5 -4 -4 -4 -4
+	  //  1  2  2  2  2  2  2       -4 -4 -4 -3 -3 -3 -3
+	  //  2  3  3  3  3  3  3       -3 -3 -3 -2 -2 -2 -2
+	  //  3  4  4  4  4  4  4       -2 -2 -2 -1 -1 -1 -1
+	  //  4  5  5                   -1 -1 -1
+	  if (week != day)
+	    return week < day;
+
+	  if (calDayOfWeek != dayOfWeek)
+	    return calDayOfWeek < dayOfWeek;
+
+	  // daylight savings starts/ends  on the given day.
+	  break;
+        }
+      case DOW_LE_DOM_MODE:
+	// The greatest sunday before or equal December, 12
+	// is the same as smallest sunday after or equal December, 6.
+	day = Math.abs(day) - 6;
+      case DOW_GE_DOM_MODE:
+	// Calculate the day of month of the day of type
+	// "dayOfWeek" that lies before (or on) the given date.
+	calDayOfMonth -= (calDayOfWeek < dayOfWeek ? 7 : 0) + calDayOfWeek
+	- dayOfWeek;
+	if (calDayOfMonth < day)
+	  return true;
+	if (calDayOfWeek != dayOfWeek || calDayOfMonth >= day + 7)
+	  return false;
+
+	// now we have the same day
+	break;
+      }
+
+    // the millis decides:
+    return (calMillis < millis);
+  }
+
+  /**
+   * Determines if the given date is in daylight savings time.
+   * @return true, if it is in daylight savings time, false otherwise.
+   */
+  public boolean inDaylightTime(Date date)
+  {
+    Calendar cal = Calendar.getInstance(this);
+    cal.setTime(date);
+    return (cal.get(Calendar.DST_OFFSET) != 0);
+  }
+
+  /**
+   * Generates the hashCode for the SimpleDateFormat object.  It is
+   * the rawOffset, possibly, if useDaylightSavings is true, xored
+   * with startYear, startMonth, startDayOfWeekInMonth, ..., endTime.
+   */
+  public synchronized int hashCode()
+  {
+    return rawOffset
+           ^ (useDaylight
+              ? startMonth ^ startDay ^ startDayOfWeek ^ startTime ^ endMonth
+              ^ endDay ^ endDayOfWeek ^ endTime : 0);
+  }
+
+  public synchronized boolean equals(Object o)
+  {
+    if (this == o)
+      return true;
+    if (! (o instanceof SimpleTimeZone))
+      return false;
+    SimpleTimeZone zone = (SimpleTimeZone) o;
+    if (zone.hashCode() != hashCode() || ! getID().equals(zone.getID())
+        || rawOffset != zone.rawOffset || useDaylight != zone.useDaylight)
+      return false;
+    if (! useDaylight)
+      return true;
+    return (startYear == zone.startYear && startMonth == zone.startMonth
+           && startDay == zone.startDay
+           && startDayOfWeek == zone.startDayOfWeek
+           && startTime == zone.startTime
+           && startTimeMode == zone.startTimeMode && endMonth == zone.endMonth
+           && endDay == zone.endDay && endDayOfWeek == zone.endDayOfWeek
+           && endTime == zone.endTime && endTimeMode == zone.endTimeMode);
+  }
+
+  /**
+   * Test if the other time zone uses the same rule and only
+   * possibly differs in ID.  This implementation for this particular
+   * class will return true if the other object is a SimpleTimeZone,
+   * the raw offsets and useDaylight are identical and if useDaylight
+   * is true, also the start and end datas are identical.
+   * @return true if this zone uses the same rule.
+   */
+  public boolean hasSameRules(TimeZone other)
+  {
+    if (this == other)
+      return true;
+    if (! (other instanceof SimpleTimeZone))
+      return false;
+    SimpleTimeZone zone = (SimpleTimeZone) other;
+    if (zone.hashCode() != hashCode() || rawOffset != zone.rawOffset
+        || useDaylight != zone.useDaylight)
+      return false;
+    if (! useDaylight)
+      return true;
+    return (startYear == zone.startYear && startMonth == zone.startMonth
+           && startDay == zone.startDay
+           && startDayOfWeek == zone.startDayOfWeek
+           && startTime == zone.startTime
+           && startTimeMode == zone.startTimeMode && endMonth == zone.endMonth
+           && endDay == zone.endDay && endDayOfWeek == zone.endDayOfWeek
+           && endTime == zone.endTime && endTimeMode == zone.endTimeMode);
+  }
+
+  /**
+   * Returns a string representation of this SimpleTimeZone object.
+   * @return a string representation of this SimpleTimeZone object.
+   */
+  public String toString()
+  {
+    // the test for useDaylight is an incompatibility to jdk1.2, but
+    // I think this shouldn't hurt.
+    return getClass().getName() + "[" + "id=" + getID() + ",offset="
+           + rawOffset + ",dstSavings=" + dstSavings + ",useDaylight="
+           + useDaylight
+           + (useDaylight
+              ? ",startYear=" + startYear + ",startMode=" + startMode
+              + ",startMonth=" + startMonth + ",startDay=" + startDay
+              + ",startDayOfWeek=" + startDayOfWeek + ",startTime="
+              + startTime + ",startTimeMode=" + startTimeMode + ",endMode="
+              + endMode + ",endMonth=" + endMonth + ",endDay=" + endDay
+              + ",endDayOfWeek=" + endDayOfWeek + ",endTime=" + endTime
+              + ",endTimeMode=" + endTimeMode : "") + "]";
+  }
+
+  /**
+   * Reads a serialized simple time zone from stream.
+   * @see #writeObject
+   */
+  private void readObject(java.io.ObjectInputStream input)
+    throws java.io.IOException, ClassNotFoundException
+  {
+    input.defaultReadObject();
+    if (serialVersionOnStream == 0)
+      {
+	// initialize the new fields to default values.
+	dstSavings = 60 * 60 * 1000;
+	endMode = DOW_IN_MONTH_MODE;
+	startMode = DOW_IN_MONTH_MODE;
+	startTimeMode = WALL_TIME;
+	endTimeMode = WALL_TIME;
+	serialVersionOnStream = 2;
+      }
+    else
+      {
+	int length = input.readInt();
+	byte[] byteArray = new byte[length];
+	input.read(byteArray, 0, length);
+	if (length >= 4)
+	  {
+	    // Lets hope that Sun does extensions to the serialized
+	    // form in a sane manner.
+	    startDay = byteArray[0];
+	    startDayOfWeek = byteArray[1];
+	    endDay = byteArray[2];
+	    endDayOfWeek = byteArray[3];
+	  }
+      }
+  }
+
+  /**
+   * Serializes this object to a stream.  @serialdata The object is
+   * first written in the old JDK 1.1 format, so that it can be read
+   * by by the old classes.  This means, that the
+   * <code>start/endDay(OfWeek)</code>-Fields are written in the
+   * DOW_IN_MONTH_MODE rule, since this was the only supported rule
+   * in 1.1.
+   *
+   * In the optional section, we write first the length of an byte
+   * array as int and afterwards the byte array itself.  The byte
+   * array contains in this release four elements, namely the real
+   * startDay, startDayOfWeek endDay, endDayOfWeek in that Order.
+   * These fields are needed, because for compatibility reasons only
+   * approximative values are written to the required section, as
+   * described above.
+   */
+  private void writeObject(java.io.ObjectOutputStream output)
+    throws java.io.IOException
+  {
+    byte[] byteArray = new byte[]
+                       {
+                         (byte) startDay, (byte) startDayOfWeek, (byte) endDay,
+                         (byte) endDayOfWeek
+                       };
+
+    /* calculate the approximation for JDK 1.1 */
+    switch (startMode)
+      {
+      case DOM_MODE:
+	startDayOfWeek = Calendar.SUNDAY; // random day of week
+
+      // fall through
+      case DOW_GE_DOM_MODE:
+      case DOW_LE_DOM_MODE:
+	startDay = (startDay + 6) / 7;
+      }
+    switch (endMode)
+      {
+      case DOM_MODE:
+	endDayOfWeek = Calendar.SUNDAY;
+
+      // fall through
+      case DOW_GE_DOM_MODE:
+      case DOW_LE_DOM_MODE:
+	endDay = (endDay + 6) / 7;
+      }
+
+    // the required part:
+    output.defaultWriteObject();
+    // the optional part:
+    output.writeInt(byteArray.length);
+    output.write(byteArray, 0, byteArray.length);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/SortedMap.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/SortedMap.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/SortedMap.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/SortedMap.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,173 @@
+/* SortedMap.java -- A map that makes guarantees about the order of its keys
+   Copyright (C) 1998, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A map which guarantees its key's iteration order. The entries in the
+ * map are related by the <i>natural ordering</i> of the keys if they
+ * are Comparable, or by the provided Comparator.  Additional operations
+ * take advantage of the sorted nature of the map.
+ * <p>
+ *
+ * All keys entered in the map must be mutually comparable; in other words,
+ * <code>k1.compareTo(k2)</code> or <code>comparator.compare(k1, k2)</code>
+ * must not throw a ClassCastException. The ordering must be <i>consistent
+ * with equals</i> (see {@link Comparator} for this definition), if the
+ * map is to obey the general contract of the Map interface.  If not,
+ * the results are well-defined, but probably not what you wanted.
+ * <p>
+ *
+ * It is recommended that all implementing classes provide four constructors:
+ * 1) one that takes no arguments and builds an empty map sorted by natural
+ * order of the keys; 2) one that takes a Comparator for the sorting order;
+ * 3) one that takes a Map and sorts according to the natural order of its
+ * keys; and 4) one that takes a SortedMap and sorts by the same comparator.
+ * Unfortunately, the Java language does not provide a way to enforce this.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Map
+ * @see TreeMap
+ * @see SortedSet
+ * @see Comparable
+ * @see Comparator
+ * @see Collection
+ * @see ClassCastException
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface SortedMap extends Map
+{
+  /**
+   * Returns the comparator used in sorting this map, or null if it is
+   * the keys' natural ordering.
+   *
+   * @return the sorting comparator
+   */
+  Comparator comparator();
+
+  /**
+   * Returns the first (lowest sorted) key in the map.
+   *
+   * @return the first key
+   * @throws NoSuchElementException if this map is empty.
+   */
+  Object firstKey();
+
+  /**
+   * Returns a view of the portion of the map strictly less than toKey. The
+   * view is backed by this map, so changes in one show up in the other.
+   * The submap supports all optional operations of the original.
+   * <p>
+   *
+   * The returned map throws an IllegalArgumentException any time a key is
+   * used which is out of the range of toKey. Note that the endpoint, toKey,
+   * is not included; if you want this value to be included, pass its successor
+   * object in to toKey.  For example, for Integers, you could request
+   * <code>headMap(new Integer(limit.intValue() + 1))</code>.
+   *
+   * @param toKey the exclusive upper range of the submap
+   * @return the submap
+   * @throws ClassCastException if toKey is not comparable to the map contents
+   * @throws IllegalArgumentException if this is a subMap, and toKey is out
+   *         of range
+   * @throws NullPointerException if toKey is null but the map does not allow
+   *         null keys
+   */
+  SortedMap headMap(Object toKey);
+
+  /**
+   * Returns the last (highest sorted) key in the map.
+   *
+   * @return the last key
+   * @throws NoSuchElementException if this map is empty.
+   */
+  Object lastKey();
+
+  /**
+   * Returns a view of the portion of the map greater than or equal to
+   * fromKey, and strictly less than toKey. The view is backed by this map,
+   * so changes in one show up in the other. The submap supports all
+   * optional operations of the original.
+   * <p>
+   *
+   * The returned map throws an IllegalArgumentException any time a key is
+   * used which is out of the range of fromKey and toKey. Note that the
+   * lower endpoint is included, but the upper is not; if you want to
+   * change the inclusion or exclusion of an endpoint, pass its successor
+   * object in instead.  For example, for Integers, you could request
+   * <code>subMap(new Integer(lowlimit.intValue() + 1),
+   * new Integer(highlimit.intValue() + 1))</code> to reverse
+   * the inclusiveness of both endpoints.
+   *
+   * @param fromKey the inclusive lower range of the submap
+   * @param toKey the exclusive upper range of the submap
+   * @return the submap
+   * @throws ClassCastException if fromKey or toKey is not comparable to
+   *         the map contents
+   * @throws IllegalArgumentException if this is a subMap, and fromKey or
+   *         toKey is out of range
+   * @throws NullPointerException if fromKey or toKey is null but the map
+   *         does not allow null keys
+   */
+  SortedMap subMap(Object fromKey, Object toKey);
+
+  /**
+   * Returns a view of the portion of the map greater than or equal to
+   * fromKey. The view is backed by this map, so changes in one show up
+   * in the other. The submap supports all optional operations of the original.
+   * <p>
+   *
+   * The returned map throws an IllegalArgumentException any time a key is
+   * used which is out of the range of fromKey. Note that the endpoint, fromKey, is
+   * included; if you do not want this value to be included, pass its successor object in
+   * to fromKey.  For example, for Integers, you could request
+   * <code>tailMap(new Integer(limit.intValue() + 1))</code>.
+   *
+   * @param fromKey the inclusive lower range of the submap
+   * @return the submap
+   * @throws ClassCastException if fromKey is not comparable to the map
+   *         contents
+   * @throws IllegalArgumentException if this is a subMap, and fromKey is out
+   *         of range
+   * @throws NullPointerException if fromKey is null but the map does not allow
+   *         null keys
+   */
+  SortedMap tailMap(Object fromKey);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/SortedSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/SortedSet.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/SortedSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/SortedSet.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,176 @@
+/* SortedSet.java -- A set that makes guarantees about the order of its
+   elements
+   Copyright (C) 1998, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * A set which guarantees its iteration order. The elements in the set
+ * are related by the <i>natural ordering</i> if they are Comparable, or
+ * by the provided Comparator.  Additional operations take advantage of
+ * the sorted nature of the set.
+ * <p>
+ *
+ * All elements entered in the set must be mutually comparable; in other words,
+ * <code>k1.compareTo(k2)</code> or <code>comparator.compare(k1, k2)</code>
+ * must not throw a ClassCastException. The ordering must be <i>consistent
+ * with equals</i> (see {@link Comparator} for this definition), if the
+ * set is to obey the general contract of the Set interface.  If not,
+ * the results are well-defined, but probably not what you wanted.
+ * <p>
+ *
+ * It is recommended that all implementing classes provide four constructors:
+ * 1) one that takes no arguments and builds an empty set sorted by natural
+ * order of the elements; 2) one that takes a Comparator for the sorting order;
+ * 3) one that takes a Set and sorts according to the natural order of its
+ * elements; and 4) one that takes a SortedSet and sorts by the same
+ * comparator. Unfortunately, the Java language does not provide a way to
+ * enforce this.
+ *
+ * @author Original author unknown
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Set
+ * @see TreeSet
+ * @see SortedMap
+ * @see Collection
+ * @see Comparable
+ * @see Comparator
+ * @see ClassCastException
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public interface SortedSet extends Set
+{
+  /**
+   * Returns the comparator used in sorting this set, or null if it is
+   * the elements' natural ordering.
+   *
+   * @return the sorting comparator
+   */
+  Comparator comparator();
+
+  /**
+   * Returns the first (lowest sorted) element in the set.
+   *
+   * @return the first element
+   * @throws NoSuchElementException if the set is empty.
+   */
+  Object first();
+
+  /**
+   * Returns a view of the portion of the set strictly less than toElement. The
+   * view is backed by this set, so changes in one show up in the other.
+   * The subset supports all optional operations of the original.
+   * <p>
+   *
+   * The returned set throws an IllegalArgumentException any time an element is
+   * used which is out of the range of toElement. Note that the endpoint, toElement,
+   * is not included; if you want this value included, pass its successor object in to
+   * toElement.  For example, for Integers, you could request
+   * <code>headSet(new Integer(limit.intValue() + 1))</code>.
+   *
+   * @param toElement the exclusive upper range of the subset
+   * @return the subset
+   * @throws ClassCastException if toElement is not comparable to the set
+   *         contents
+   * @throws IllegalArgumentException if this is a subSet, and toElement is out
+   *         of range
+   * @throws NullPointerException if toElement is null but the set does not
+   *         allow null elements
+   */
+  SortedSet headSet(Object toElement);
+
+  /**
+   * Returns the last (highest sorted) element in the set.
+   *
+   * @return the last element
+   * @throws NoSuchElementException if the set is empty.
+   */
+  Object last();
+
+  /**
+   * Returns a view of the portion of the set greater than or equal to
+   * fromElement, and strictly less than toElement. The view is backed by
+   * this set, so changes in one show up in the other. The subset supports all
+   * optional operations of the original.
+   * <p>
+   *
+   * The returned set throws an IllegalArgumentException any time an element is
+   * used which is out of the range of fromElement and toElement. Note that the
+   * lower endpoint is included, but the upper is not; if you want to
+   * change the inclusion or exclusion of an endpoint, pass its successor
+   * object in instead.  For example, for Integers, you can request
+   * <code>subSet(new Integer(lowlimit.intValue() + 1),
+   * new Integer(highlimit.intValue() + 1))</code> to reverse
+   * the inclusiveness of both endpoints.
+   *
+   * @param fromElement the inclusive lower range of the subset
+   * @param toElement the exclusive upper range of the subset
+   * @return the subset
+   * @throws ClassCastException if fromElement or toElement is not comparable
+   *         to the set contents
+   * @throws IllegalArgumentException if this is a subSet, and fromElement or
+   *         toElement is out of range
+   * @throws NullPointerException if fromElement or toElement is null but the
+   *         set does not allow null elements
+   */
+  SortedSet subSet(Object fromElement, Object toElement);
+
+  /**
+   * Returns a view of the portion of the set greater than or equal to
+   * fromElement. The view is backed by this set, so changes in one show up
+   * in the other. The subset supports all optional operations of the original.
+   * <p>
+   *
+   * The returned set throws an IllegalArgumentException any time an element is
+   * used which is out of the range of fromElement. Note that the endpoint,
+   * fromElement, is included; if you do not want this value to be included, pass its
+   * successor object in to fromElement.  For example, for Integers, you could request
+   * <code>tailSet(new Integer(limit.intValue() + 1))</code>.
+   *
+   * @param fromElement the inclusive lower range of the subset
+   * @return the subset
+   * @throws ClassCastException if fromElement is not comparable to the set
+   *         contents
+   * @throws IllegalArgumentException if this is a subSet, and fromElement is
+   *         out of range
+   * @throws NullPointerException if fromElement is null but the set does not
+   *         allow null elements
+   */
+  SortedSet tailSet(Object fromElement);
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Stack.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Stack.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Stack.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Stack.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,158 @@
+/* Stack.java - Class that provides a Last In First Out (LIFO)
+   datatype, known more commonly as a Stack
+   Copyright (C) 1998, 1999, 2001, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ * Status:  Believed complete and correct
+
+/**
+ * Stack provides a Last In First Out (LIFO) data type, commonly known
+ * as a Stack.  Stack itself extends Vector and provides the additional
+ * methods for stack manipulation (push, pop, peek). You can also seek for
+ * the 1-based position of an element on the stack.
+ *
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see List
+ * @see AbstractList
+ * @see LinkedList
+ * @since 1.0
+ * @status updated to 1.4
+ */
+public class Stack extends Vector
+{
+  // We could use Vector methods internally for the following methods,
+  // but have used Vector fields directly for efficiency (i.e. this
+  // often reduces out duplicate bounds checking).
+
+  /**
+   * Compatible with JDK 1.0+.
+   */
+  private static final long serialVersionUID = 1224463164541339165L;
+
+  /**
+   * This constructor creates a new Stack, initially empty
+   */
+  public Stack()
+  {
+  }
+
+  /**
+   * Pushes an Object onto the top of the stack.  This method is effectively
+   * the same as addElement(item).
+   *
+   * @param item the Object to push onto the stack
+   * @return the Object pushed onto the stack
+   * @see Vector#addElement(Object)
+   */
+  public Object push(Object item)
+  {
+    // When growing the Stack, use the Vector routines in case more
+    // memory is needed.
+    // Note: spec indicates that this method *always* returns obj passed in!
+
+    addElement(item);
+    return item;
+  }
+
+  /**
+   * Pops an item from the stack and returns it.  The item popped is
+   * removed from the Stack.
+   *
+   * @return the Object popped from the stack
+   * @throws EmptyStackException if the stack is empty
+   */
+  public synchronized Object pop()
+  {
+    if (elementCount == 0)
+      throw new EmptyStackException();
+
+    modCount++;
+    Object obj = elementData[--elementCount];
+
+    // Set topmost element to null to assist the gc in cleanup.
+    elementData[elementCount] = null;
+    return obj;
+  }
+
+  /**
+   * Returns the top Object on the stack without removing it.
+   *
+   * @return the top Object on the stack
+   * @throws EmptyStackException if the stack is empty
+   */
+  public synchronized Object peek()
+  {
+    if (elementCount == 0)
+      throw new EmptyStackException();
+
+    return elementData[elementCount - 1];
+  }
+
+  /**
+   * Tests if the stack is empty.
+   *
+   * @return true if the stack contains no items, false otherwise
+   */
+  public synchronized boolean empty()
+  {
+    return elementCount == 0;
+  }
+
+  /**
+   * Returns the position of an Object on the stack, with the top
+   * most Object being at position 1, and each Object deeper in the
+   * stack at depth + 1.
+   *
+   * @param o The object to search for
+   * @return The 1 based depth of the Object, or -1 if the Object
+   *         is not on the stack
+   */
+  public synchronized int search(Object o)
+  {
+    int i = elementCount;
+    while (--i >= 0)
+      if (equals(o, elementData[i]))
+        return elementCount - i;
+    return -1;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/StringTokenizer.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/StringTokenizer.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/StringTokenizer.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/StringTokenizer.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,267 @@
+/* StringTokenizer -- breaks a String into tokens
+   Copyright (C) 1998, 1999, 2001, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This class splits a string into tokens.  The caller can set on which
+ * delimiters the string should be split and if the delimiters should be
+ * returned. This is much simpler than {@link java.io.StreamTokenizer}.
+ *
+ * <p>You may change the delimiter set on the fly by calling
+ * nextToken(String).  But the semantic is quite difficult; it even
+ * depends on calling <code>hasMoreTokens()</code>.  You should call
+ * <code>hasMoreTokens()</code> before, otherwise the old delimiters
+ * after the last token are candidates for being returned.
+ *
+ * <p>If you want to get the delimiters, you have to use the three argument
+ * constructor.  The delimiters are returned as token consisting of a
+ * single character.
+ *
+ * @author Jochen Hoenicke
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @see java.io.StreamTokenizer
+ * @status updated to 1.4
+ */
+public class StringTokenizer implements Enumeration
+{
+  // WARNING: StringTokenizer is a CORE class in the bootstrap cycle. See the
+  // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
+  /**
+   * The position in the str, where we currently are.
+   */
+  private int pos;
+
+  /**
+   * The string that should be split into tokens.
+   */
+  private final String str;
+
+  /**
+   * The length of the string.
+   */
+  private final int len;
+
+  /**
+   * The string containing the delimiter characters.
+   */
+  private String delim;
+
+  /**
+   * Tells, if we should return the delimiters.
+   */
+  private final boolean retDelims;
+
+  /**
+   * Creates a new StringTokenizer for the string <code>str</code>,
+   * that should split on the default delimiter set (space, tab,
+   * newline, return and formfeed), and which doesn't return the
+   * delimiters.
+   *
+   * @param str The string to split
+   * @throws NullPointerException if str is null
+   */
+  public StringTokenizer(String str)
+  {
+    this(str, " \t\n\r\f", false);
+  }
+
+  /**
+   * Create a new StringTokenizer, that splits the given string on
+   * the given delimiter characters.  It doesn't return the delimiter
+   * characters.
+   *
+   * @param str the string to split
+   * @param delim a string containing all delimiter characters
+   * @throws NullPointerException if either argument is null
+   */
+  public StringTokenizer(String str, String delim)
+  {
+    this(str, delim, false);
+  }
+
+  /**
+   * Create a new StringTokenizer, that splits the given string on
+   * the given delimiter characters.  If you set
+   * <code>returnDelims</code> to <code>true</code>, the delimiter
+   * characters are returned as tokens of their own.  The delimiter
+   * tokens always consist of a single character.
+   *
+   * @param str the string to split
+   * @param delim a string containing all delimiter characters
+   * @param returnDelims tells, if you want to get the delimiters
+   * @throws NullPointerException if str or delim is null
+   */
+  public StringTokenizer(String str, String delim, boolean returnDelims)
+  {
+    len = str.length();
+    this.str = str;
+    this.delim = delim;
+    this.retDelims = returnDelims;
+    this.pos = 0;
+  }
+
+  /**
+   * Tells if there are more tokens.
+   *
+   * @return true if the next call of nextToken() will succeed
+   */
+  public boolean hasMoreTokens()
+  {
+    if (! retDelims)
+      {
+        while (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
+          pos++;
+      }
+    return pos < len;
+  }
+
+  /**
+   * Returns the nextToken, changing the delimiter set to the given
+   * <code>delim</code>.  The change of the delimiter set is
+   * permanent, ie. the next call of nextToken(), uses the same
+   * delimiter set.
+   *
+   * @param delim a string containing the new delimiter characters
+   * @return the next token with respect to the new delimiter characters
+   * @throws NoSuchElementException if there are no more tokens
+   * @throws NullPointerException if delim is null
+   */
+  public String nextToken(String delim) throws NoSuchElementException
+  {
+    this.delim = delim;
+    return nextToken();
+  }
+
+  /**
+   * Returns the nextToken of the string.
+   *
+   * @return the next token with respect to the current delimiter characters
+   * @throws NoSuchElementException if there are no more tokens
+   */
+  public String nextToken() throws NoSuchElementException
+  {
+    if (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
+      {
+        if (retDelims)
+          return str.substring(pos, ++pos);
+        while (++pos < len && delim.indexOf(str.charAt(pos)) >= 0);
+      }
+    if (pos < len)
+      {
+        int start = pos;
+        while (++pos < len && delim.indexOf(str.charAt(pos)) < 0);
+
+        return str.substring(start, pos);
+      }
+    throw new NoSuchElementException();
+  }
+
+  /**
+   * This does the same as hasMoreTokens. This is the
+   * <code>Enumeration</code> interface method.
+   *
+   * @return true, if the next call of nextElement() will succeed
+   * @see #hasMoreTokens()
+   */
+  public boolean hasMoreElements()
+  {
+    return hasMoreTokens();
+  }
+
+  /**
+   * This does the same as nextTokens. This is the
+   * <code>Enumeration</code> interface method.
+   *
+   * @return the next token with respect to the current delimiter characters
+   * @throws NoSuchElementException if there are no more tokens
+   * @see #nextToken()
+   */
+  public Object nextElement() throws NoSuchElementException
+  {
+    return nextToken();
+  }
+
+  /**
+   * This counts the number of remaining tokens in the string, with
+   * respect to the current delimiter set.
+   *
+   * @return the number of times <code>nextTokens()</code> will succeed
+   * @see #nextToken()
+   */
+  public int countTokens()
+  {
+    int count = 0;
+    int delimiterCount = 0;
+    boolean tokenFound = false; // Set when a non-delimiter is found
+    int tmpPos = pos;
+
+    // Note for efficiency, we count up the delimiters rather than check
+    // retDelims every time we encounter one.  That way, we can
+    // just do the conditional once at the end of the method
+    while (tmpPos < len)
+      {
+        if (delim.indexOf(str.charAt(tmpPos++)) >= 0)
+          {
+            if (tokenFound)
+              {
+                // Got to the end of a token
+                count++;
+                tokenFound = false;
+              }
+            delimiterCount++; // Increment for this delimiter
+          }
+        else
+          {
+            tokenFound = true;
+            // Get to the end of the token
+            while (tmpPos < len
+                   && delim.indexOf(str.charAt(tmpPos)) < 0)
+              ++tmpPos;
+          }
+      }
+
+    // Make sure to count the last token
+    if (tokenFound)
+      count++;
+
+    // if counting delmiters add them into the token count
+    return retDelims ? count + delimiterCount : count;
+  }
+} // class StringTokenizer

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/TimeZone.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/TimeZone.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/TimeZone.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/TimeZone.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1559 @@
+/* java.util.TimeZone
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+   Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.DateFormatSymbols;
+
+/**
+ * This class represents a time zone offset and handles daylight savings.
+ * 
+ * You can get the default time zone with <code>getDefault</code>.
+ * This represents the time zone where program is running.
+ *
+ * Another way to create a time zone is <code>getTimeZone</code>, where
+ * you can give an identifier as parameter.  For instance, the identifier
+ * of the Central European Time zone is "CET".
+ *
+ * With the <code>getAvailableIDs</code> method, you can get all the
+ * supported time zone identifiers.
+ *
+ * @see Calendar
+ * @see SimpleTimeZone
+ * @author Jochen Hoenicke
+ */
+public abstract class TimeZone implements java.io.Serializable, Cloneable
+{
+
+  /**
+   * Constant used to indicate that a short timezone abbreviation should
+   * be returned, such as "EST"
+   */
+  public static final int SHORT = 0;
+
+  /**
+   * Constant used to indicate that a long timezone name should be
+   * returned, such as "Eastern Standard Time".
+   */
+  public static final int LONG = 1;
+
+  /**
+   * The time zone identifier, e.g. PST.
+   */
+  private String ID;
+
+  /**
+   * The default time zone, as returned by getDefault.
+   */
+  private static TimeZone defaultZone0;
+
+  /**
+   * Tries to get the default TimeZone for this system if not already
+   * set.  It will call <code>getDefaultTimeZone(String)</code> with
+   * the result of <code>System.getProperty("user.timezone")</code>.
+   * If that fails it calls <code>VMTimeZone.getDefaultTimeZoneId()</code>.
+   * If that also fails GMT is returned.
+   */
+  private static synchronized TimeZone defaultZone()
+  {
+    /* Look up default timezone */
+    if (defaultZone0 == null) 
+      {
+	defaultZone0 = (TimeZone) AccessController.doPrivileged
+	  (new PrivilegedAction()
+	    {
+	      public Object run()
+	      {
+		TimeZone zone = null;
+		
+		// Prefer System property user.timezone.
+		String tzid = System.getProperty("user.timezone");
+		if (tzid != null && !tzid.equals(""))
+		  zone = getDefaultTimeZone(tzid);
+		
+		// Try platfom specific way.
+		if (zone == null)
+		  zone = VMTimeZone.getDefaultTimeZoneId();
+		
+		// Fall back on GMT.
+		if (zone == null)
+		  zone = (TimeZone) timezones().get("GMT");
+		
+		return zone;
+	      }
+	    });
+      }
+    
+    return defaultZone0; 
+  }
+  
+  private static final long serialVersionUID = 3581463369166924961L;
+
+  /**
+   * HashMap for timezones by ID.  
+   */
+  private static HashMap timezones0;
+  /* initialize this static field lazily to overhead if
+   * it is not needed: 
+   */
+  // Package-private to avoid a trampoline.
+  static synchronized HashMap timezones()
+  {
+    if (timezones0 == null) 
+      {
+	HashMap timezones = new HashMap();
+	timezones0 = timezones;
+
+	TimeZone tz;
+	// Automatically generated by scripts/timezones.pl
+	// XXX - Should we read this data from a file?
+	tz = new SimpleTimeZone(-11000 * 3600, "MIT");
+	timezones0.put("MIT", tz);
+	timezones0.put("Pacific/Apia", tz);
+	timezones0.put("Pacific/Midway", tz);
+	timezones0.put("Pacific/Niue", tz);
+	timezones0.put("Pacific/Pago_Pago", tz);
+	tz = new SimpleTimeZone
+	  (-10000 * 3600, "America/Adak",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("America/Adak", tz);
+	tz = new SimpleTimeZone(-10000 * 3600, "HST");
+	timezones0.put("HST", tz);
+	timezones0.put("Pacific/Fakaofo", tz);
+	timezones0.put("Pacific/Honolulu", tz);
+	timezones0.put("Pacific/Johnston", tz);
+	timezones0.put("Pacific/Rarotonga", tz);
+	timezones0.put("Pacific/Tahiti", tz);
+	tz = new SimpleTimeZone(-9500 * 3600, "Pacific/Marquesas");
+	timezones0.put("Pacific/Marquesas", tz);
+	tz = new SimpleTimeZone
+	  (-9000 * 3600, "AST",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("AST", tz);
+	timezones0.put("America/Anchorage", tz);
+	timezones0.put("America/Juneau", tz);
+	timezones0.put("America/Nome", tz);
+	timezones0.put("America/Yakutat", tz);
+	tz = new SimpleTimeZone(-9000 * 3600, "Pacific/Gambier");
+	timezones0.put("Pacific/Gambier", tz);
+	tz = new SimpleTimeZone
+	  (-8000 * 3600, "America/Tijuana",
+	   Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("America/Tijuana", tz);
+	tz = new SimpleTimeZone
+	  (-8000 * 3600, "PST",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("PST", tz);
+	timezones0.put("PST8PDT", tz);
+	timezones0.put("America/Dawson", tz);
+	timezones0.put("America/Los_Angeles", tz);
+	timezones0.put("America/Vancouver", tz);
+	timezones0.put("America/Whitehorse", tz);
+	timezones0.put("US/Pacific-New", tz);
+	tz = new SimpleTimeZone(-8000 * 3600, "Pacific/Pitcairn");
+	timezones0.put("Pacific/Pitcairn", tz);
+	tz = new SimpleTimeZone
+	  (-7000 * 3600, "America/Chihuahua",
+	   Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("America/Chihuahua", tz);
+	timezones0.put("America/Mazatlan", tz);
+	tz = new SimpleTimeZone(-7000 * 3600, "MST7");
+	timezones0.put("MST7", tz);
+	timezones0.put("PNT", tz);
+	timezones0.put("America/Dawson_Creek", tz);
+	timezones0.put("America/Hermosillo", tz);
+	timezones0.put("America/Phoenix", tz);
+	tz = new SimpleTimeZone
+	  (-7000 * 3600, "MST",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("MST", tz);
+	timezones0.put("MST7MDT", tz);
+	timezones0.put("America/Boise", tz);
+	timezones0.put("America/Cambridge_Bay", tz);
+	timezones0.put("America/Denver", tz);
+	timezones0.put("America/Edmonton", tz);
+	timezones0.put("America/Inuvik", tz);
+	timezones0.put("America/Shiprock", tz);
+	timezones0.put("America/Yellowknife", tz);
+	tz = new SimpleTimeZone
+	  (-6000 * 3600, "America/Cancun",
+	   Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("America/Cancun", tz);
+	timezones0.put("America/Merida", tz);
+	timezones0.put("America/Mexico_City", tz);
+	timezones0.put("America/Monterrey", tz);
+	tz = new SimpleTimeZone(-6000 * 3600, "America/Belize");
+	timezones0.put("America/Belize", tz);
+	timezones0.put("America/Costa_Rica", tz);
+	timezones0.put("America/El_Salvador", tz);
+	timezones0.put("America/Guatemala", tz);
+	timezones0.put("America/Managua", tz);
+	timezones0.put("America/Regina", tz);
+	timezones0.put("America/Swift_Current", tz);
+	timezones0.put("America/Tegucigalpa", tz);
+	timezones0.put("Pacific/Galapagos", tz);
+	tz = new SimpleTimeZone
+	  (-6000 * 3600, "CST",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("CST", tz);
+	timezones0.put("CST6CDT", tz);
+	timezones0.put("America/Chicago", tz);
+	timezones0.put("America/Indiana/Knox", tz);
+	timezones0.put("America/Indiana/Petersburg", tz);
+	timezones0.put("America/Indiana/Vincennes", tz);
+	timezones0.put("America/Menominee", tz);
+	timezones0.put("America/North_Dakota/Center", tz);
+	timezones0.put("America/North_Dakota/New_Salem", tz);
+	timezones0.put("America/Rainy_River", tz);
+	timezones0.put("America/Rankin_Inlet", tz);
+	timezones0.put("America/Winnipeg", tz);
+	tz = new SimpleTimeZone
+	  (-6000 * 3600, "Pacific/Easter",
+	   Calendar.OCTOBER, 2, Calendar.SATURDAY, 22000 * 3600,
+	   Calendar.MARCH, 2, Calendar.SATURDAY, 22000 * 3600);
+	timezones0.put("Pacific/Easter", tz);
+	tz = new SimpleTimeZone(-5000 * 3600, "EST5");
+	timezones0.put("EST5", tz);
+	timezones0.put("IET", tz);
+	timezones0.put("America/Atikokan", tz);
+	timezones0.put("America/Bogota", tz);
+	timezones0.put("America/Cayman", tz);
+	timezones0.put("America/Eirunepe", tz);
+	timezones0.put("America/Guayaquil", tz);
+	timezones0.put("America/Jamaica", tz);
+	timezones0.put("America/Lima", tz);
+	timezones0.put("America/Panama", tz);
+	timezones0.put("America/Rio_Branco", tz);
+	tz = new SimpleTimeZone
+	  (-5000 * 3600, "America/Havana",
+	   Calendar.APRIL, 1, Calendar.SUNDAY, 0 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600);
+	timezones0.put("America/Havana", tz);
+	tz = new SimpleTimeZone
+	  (-5000 * 3600, "America/Grand_Turk",
+	   Calendar.APRIL, 1, Calendar.SUNDAY, 0 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
+	timezones0.put("America/Grand_Turk", tz);
+	timezones0.put("America/Port-au-Prince", tz);
+	tz = new SimpleTimeZone
+	  (-5000 * 3600, "EST",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("EST", tz);
+	timezones0.put("EST5EDT", tz);
+	timezones0.put("America/Detroit", tz);
+	timezones0.put("America/Indiana/Indianapolis", tz);
+	timezones0.put("America/Indiana/Marengo", tz);
+	timezones0.put("America/Indiana/Vevay", tz);
+	timezones0.put("America/Iqaluit", tz);
+	timezones0.put("America/Kentucky/Louisville", tz);
+	timezones0.put("America/Kentucky/Monticello", tz);
+	timezones0.put("America/Montreal", tz);
+	timezones0.put("America/Nassau", tz);
+	timezones0.put("America/New_York", tz);
+	timezones0.put("America/Nipigon", tz);
+	timezones0.put("America/Pangnirtung", tz);
+	timezones0.put("America/Thunder_Bay", tz);
+	timezones0.put("America/Toronto", tz);
+	tz = new SimpleTimeZone
+	  (-4000 * 3600, "America/Asuncion",
+	   Calendar.OCTOBER, 3, Calendar.SUNDAY, 0 * 3600,
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 0 * 3600);
+	timezones0.put("America/Asuncion", tz);
+	tz = new SimpleTimeZone(-4000 * 3600, "PRT");
+	timezones0.put("PRT", tz);
+	timezones0.put("America/Anguilla", tz);
+	timezones0.put("America/Antigua", tz);
+	timezones0.put("America/Aruba", tz);
+	timezones0.put("America/Barbados", tz);
+	timezones0.put("America/Blanc-Sablon", tz);
+	timezones0.put("America/Boa_Vista", tz);
+	timezones0.put("America/Caracas", tz);
+	timezones0.put("America/Curacao", tz);
+	timezones0.put("America/Dominica", tz);
+	timezones0.put("America/Grenada", tz);
+	timezones0.put("America/Guadeloupe", tz);
+	timezones0.put("America/Guyana", tz);
+	timezones0.put("America/La_Paz", tz);
+	timezones0.put("America/Manaus", tz);
+	timezones0.put("America/Martinique", tz);
+	timezones0.put("America/Montserrat", tz);
+	timezones0.put("America/Port_of_Spain", tz);
+	timezones0.put("America/Porto_Velho", tz);
+	timezones0.put("America/Puerto_Rico", tz);
+	timezones0.put("America/Santo_Domingo", tz);
+	timezones0.put("America/St_Kitts", tz);
+	timezones0.put("America/St_Lucia", tz);
+	timezones0.put("America/St_Thomas", tz);
+	timezones0.put("America/St_Vincent", tz);
+	timezones0.put("America/Tortola", tz);
+	tz = new SimpleTimeZone
+	  (-4000 * 3600, "America/Campo_Grande",
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0 * 3600,
+	   Calendar.FEBRUARY, -1, Calendar.SUNDAY, 0 * 3600);
+	timezones0.put("America/Campo_Grande", tz);
+	timezones0.put("America/Cuiaba", tz);
+	tz = new SimpleTimeZone
+	  (-4000 * 3600, "America/Goose_Bay",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 60000,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 60000);
+	timezones0.put("America/Goose_Bay", tz);
+	tz = new SimpleTimeZone
+	  (-4000 * 3600, "America/Glace_Bay",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("America/Glace_Bay", tz);
+	timezones0.put("America/Halifax", tz);
+	timezones0.put("America/Moncton", tz);
+	timezones0.put("America/Thule", tz);
+	timezones0.put("Atlantic/Bermuda", tz);
+	tz = new SimpleTimeZone
+	  (-4000 * 3600, "America/Santiago",
+	   Calendar.OCTOBER, 9, -Calendar.SUNDAY, 0 * 3600,
+	   Calendar.MARCH, 9, -Calendar.SUNDAY, 0 * 3600);
+	timezones0.put("America/Santiago", tz);
+	timezones0.put("Antarctica/Palmer", tz);
+	tz = new SimpleTimeZone
+	  (-4000 * 3600, "Atlantic/Stanley",
+	   Calendar.SEPTEMBER, 1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.APRIL, 3, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("Atlantic/Stanley", tz);
+	tz = new SimpleTimeZone
+	  (-3500 * 3600, "CNT",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 60000,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 60000);
+	timezones0.put("CNT", tz);
+	timezones0.put("America/St_Johns", tz);
+	tz = new SimpleTimeZone
+	  (-3000 * 3600, "America/Godthab",
+	   Calendar.MARCH, 30, -Calendar.SATURDAY, 22000 * 3600,
+	   Calendar.OCTOBER, 30, -Calendar.SATURDAY, 23000 * 3600);
+	timezones0.put("America/Godthab", tz);
+	tz = new SimpleTimeZone
+	  (-3000 * 3600, "America/Miquelon",
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("America/Miquelon", tz);
+	tz = new SimpleTimeZone
+	  (-3000 * 3600, "America/Montevideo",
+	   Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("America/Montevideo", tz);
+	tz = new SimpleTimeZone
+	  (-3000 * 3600, "America/Sao_Paulo",
+	   Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0 * 3600,
+	   Calendar.FEBRUARY, -1, Calendar.SUNDAY, 0 * 3600);
+	timezones0.put("America/Sao_Paulo", tz);
+	tz = new SimpleTimeZone(-3000 * 3600, "AGT");
+	timezones0.put("AGT", tz);
+	timezones0.put("America/Araguaina", tz);
+	timezones0.put("America/Argentina/Buenos_Aires", tz);
+	timezones0.put("America/Argentina/Catamarca", tz);
+	timezones0.put("America/Argentina/Cordoba", tz);
+	timezones0.put("America/Argentina/Jujuy", tz);
+	timezones0.put("America/Argentina/La_Rioja", tz);
+	timezones0.put("America/Argentina/Mendoza", tz);
+	timezones0.put("America/Argentina/Rio_Gallegos", tz);
+	timezones0.put("America/Argentina/San_Juan", tz);
+	timezones0.put("America/Argentina/Tucuman", tz);
+	timezones0.put("America/Argentina/Ushuaia", tz);
+	timezones0.put("America/Bahia", tz);
+	timezones0.put("America/Belem", tz);
+	timezones0.put("America/Cayenne", tz);
+	timezones0.put("America/Fortaleza", tz);
+	timezones0.put("America/Maceio", tz);
+	timezones0.put("America/Paramaribo", tz);
+	timezones0.put("America/Recife", tz);
+	timezones0.put("Antarctica/Rothera", tz);
+	tz = new SimpleTimeZone(-2000 * 3600, "America/Noronha");
+	timezones0.put("America/Noronha", tz);
+	timezones0.put("Atlantic/South_Georgia", tz);
+	tz = new SimpleTimeZone
+	  (-1000 * 3600, "America/Scoresbysund",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600);
+	timezones0.put("America/Scoresbysund", tz);
+	timezones0.put("Atlantic/Azores", tz);
+	tz = new SimpleTimeZone(-1000 * 3600, "Atlantic/Cape_Verde");
+	timezones0.put("Atlantic/Cape_Verde", tz);
+	tz = new SimpleTimeZone(0 * 3600, "GMT");
+	timezones0.put("GMT", tz);
+	timezones0.put("UTC", tz);
+	timezones0.put("Africa/Abidjan", tz);
+	timezones0.put("Africa/Accra", tz);
+	timezones0.put("Africa/Bamako", tz);
+	timezones0.put("Africa/Banjul", tz);
+	timezones0.put("Africa/Bissau", tz);
+	timezones0.put("Africa/Casablanca", tz);
+	timezones0.put("Africa/Conakry", tz);
+	timezones0.put("Africa/Dakar", tz);
+	timezones0.put("Africa/El_Aaiun", tz);
+	timezones0.put("Africa/Freetown", tz);
+	timezones0.put("Africa/Lome", tz);
+	timezones0.put("Africa/Monrovia", tz);
+	timezones0.put("Africa/Nouakchott", tz);
+	timezones0.put("Africa/Ouagadougou", tz);
+	timezones0.put("Africa/Sao_Tome", tz);
+	timezones0.put("America/Danmarkshavn", tz);
+	timezones0.put("Atlantic/Reykjavik", tz);
+	timezones0.put("Atlantic/St_Helena", tz);
+	tz = new SimpleTimeZone
+	  (0 * 3600, "WET",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 1000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("WET", tz);
+	timezones0.put("Atlantic/Canary", tz);
+	timezones0.put("Atlantic/Faroe", tz);
+	timezones0.put("Atlantic/Madeira", tz);
+	timezones0.put("Europe/Dublin", tz);
+	timezones0.put("Europe/Guernsey", tz);
+	timezones0.put("Europe/Isle_of_Man", tz);
+	timezones0.put("Europe/Jersey", tz);
+	timezones0.put("Europe/Lisbon", tz);
+	timezones0.put("Europe/London", tz);
+	tz = new SimpleTimeZone(1000 * 3600, "Africa/Algiers");
+	timezones0.put("Africa/Algiers", tz);
+	timezones0.put("Africa/Bangui", tz);
+	timezones0.put("Africa/Brazzaville", tz);
+	timezones0.put("Africa/Douala", tz);
+	timezones0.put("Africa/Kinshasa", tz);
+	timezones0.put("Africa/Lagos", tz);
+	timezones0.put("Africa/Libreville", tz);
+	timezones0.put("Africa/Luanda", tz);
+	timezones0.put("Africa/Malabo", tz);
+	timezones0.put("Africa/Ndjamena", tz);
+	timezones0.put("Africa/Niamey", tz);
+	timezones0.put("Africa/Porto-Novo", tz);
+	tz = new SimpleTimeZone
+	  (1000 * 3600, "Africa/Windhoek",
+	   Calendar.SEPTEMBER, 1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600);
+	timezones0.put("Africa/Windhoek", tz);
+	tz = new SimpleTimeZone
+	  (1000 * 3600, "CET",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("CET", tz);
+	timezones0.put("ECT", tz);
+	timezones0.put("MET", tz);
+	timezones0.put("Africa/Ceuta", tz);
+	timezones0.put("Africa/Tunis", tz);
+	timezones0.put("Arctic/Longyearbyen", tz);
+	timezones0.put("Atlantic/Jan_Mayen", tz);
+	timezones0.put("Europe/Amsterdam", tz);
+	timezones0.put("Europe/Andorra", tz);
+	timezones0.put("Europe/Belgrade", tz);
+	timezones0.put("Europe/Berlin", tz);
+	timezones0.put("Europe/Bratislava", tz);
+	timezones0.put("Europe/Brussels", tz);
+	timezones0.put("Europe/Budapest", tz);
+	timezones0.put("Europe/Copenhagen", tz);
+	timezones0.put("Europe/Gibraltar", tz);
+	timezones0.put("Europe/Ljubljana", tz);
+	timezones0.put("Europe/Luxembourg", tz);
+	timezones0.put("Europe/Madrid", tz);
+	timezones0.put("Europe/Malta", tz);
+	timezones0.put("Europe/Monaco", tz);
+	timezones0.put("Europe/Oslo", tz);
+	timezones0.put("Europe/Paris", tz);
+	timezones0.put("Europe/Podgorica", tz);
+	timezones0.put("Europe/Prague", tz);
+	timezones0.put("Europe/Rome", tz);
+	timezones0.put("Europe/San_Marino", tz);
+	timezones0.put("Europe/Sarajevo", tz);
+	timezones0.put("Europe/Skopje", tz);
+	timezones0.put("Europe/Stockholm", tz);
+	timezones0.put("Europe/Tirane", tz);
+	timezones0.put("Europe/Vaduz", tz);
+	timezones0.put("Europe/Vatican", tz);
+	timezones0.put("Europe/Vienna", tz);
+	timezones0.put("Europe/Warsaw", tz);
+	timezones0.put("Europe/Zagreb", tz);
+	timezones0.put("Europe/Zurich", tz);
+	tz = new SimpleTimeZone
+	  (2000 * 3600, "ART",
+	   Calendar.APRIL, -1, Calendar.FRIDAY, 0 * 3600,
+	   Calendar.SEPTEMBER, -1, Calendar.THURSDAY, 24000 * 3600);
+	timezones0.put("ART", tz);
+	timezones0.put("Africa/Cairo", tz);
+	tz = new SimpleTimeZone(2000 * 3600, "CAT");
+	timezones0.put("CAT", tz);
+	timezones0.put("Africa/Blantyre", tz);
+	timezones0.put("Africa/Bujumbura", tz);
+	timezones0.put("Africa/Gaborone", tz);
+	timezones0.put("Africa/Harare", tz);
+	timezones0.put("Africa/Johannesburg", tz);
+	timezones0.put("Africa/Kigali", tz);
+	timezones0.put("Africa/Lubumbashi", tz);
+	timezones0.put("Africa/Lusaka", tz);
+	timezones0.put("Africa/Maputo", tz);
+	timezones0.put("Africa/Maseru", tz);
+	timezones0.put("Africa/Mbabane", tz);
+	timezones0.put("Africa/Tripoli", tz);
+	timezones0.put("Asia/Jerusalem", tz);
+	tz = new SimpleTimeZone
+	  (2000 * 3600, "Asia/Amman",
+	   Calendar.MARCH, -1, Calendar.THURSDAY, 0 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.FRIDAY, 1000 * 3600);
+	timezones0.put("Asia/Amman", tz);
+	tz = new SimpleTimeZone
+	  (2000 * 3600, "Asia/Beirut",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600);
+	timezones0.put("Asia/Beirut", tz);
+	tz = new SimpleTimeZone
+	  (2000 * 3600, "Asia/Damascus",
+	   Calendar.APRIL, 1, 0, 0 * 3600,
+	   Calendar.OCTOBER, 1, 0, 0 * 3600);
+	timezones0.put("Asia/Damascus", tz);
+	tz = new SimpleTimeZone
+	  (2000 * 3600, "Asia/Gaza",
+	   Calendar.APRIL, 1, 0, 0 * 3600,
+	   Calendar.OCTOBER, 3, Calendar.FRIDAY, 0 * 3600);
+	timezones0.put("Asia/Gaza", tz);
+	tz = new SimpleTimeZone
+	  (2000 * 3600, "EET",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 4000 * 3600);
+	timezones0.put("EET", tz);
+	timezones0.put("Asia/Istanbul", tz);
+	timezones0.put("Asia/Nicosia", tz);
+	timezones0.put("Europe/Athens", tz);
+	timezones0.put("Europe/Bucharest", tz);
+	timezones0.put("Europe/Chisinau", tz);
+	timezones0.put("Europe/Helsinki", tz);
+	timezones0.put("Europe/Istanbul", tz);
+	timezones0.put("Europe/Kiev", tz);
+	timezones0.put("Europe/Mariehamn", tz);
+	timezones0.put("Europe/Nicosia", tz);
+	timezones0.put("Europe/Riga", tz);
+	timezones0.put("Europe/Simferopol", tz);
+	timezones0.put("Europe/Sofia", tz);
+	timezones0.put("Europe/Tallinn", tz);
+	timezones0.put("Europe/Uzhgorod", tz);
+	timezones0.put("Europe/Vilnius", tz);
+	timezones0.put("Europe/Zaporozhye", tz);
+	tz = new SimpleTimeZone
+	  (2000 * 3600, "Europe/Kaliningrad",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Europe/Kaliningrad", tz);
+	timezones0.put("Europe/Minsk", tz);
+	tz = new SimpleTimeZone
+	  (3000 * 3600, "Asia/Baghdad",
+	   Calendar.APRIL, 1, 0, 3000 * 3600,
+	   Calendar.OCTOBER, 1, 0, 4000 * 3600);
+	timezones0.put("Asia/Baghdad", tz);
+	tz = new SimpleTimeZone
+	  (3000 * 3600, "Europe/Moscow",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Europe/Moscow", tz);
+	timezones0.put("Europe/Volgograd", tz);
+	tz = new SimpleTimeZone(3000 * 3600, "EAT");
+	timezones0.put("EAT", tz);
+	timezones0.put("Africa/Addis_Ababa", tz);
+	timezones0.put("Africa/Asmara", tz);
+	timezones0.put("Africa/Dar_es_Salaam", tz);
+	timezones0.put("Africa/Djibouti", tz);
+	timezones0.put("Africa/Kampala", tz);
+	timezones0.put("Africa/Khartoum", tz);
+	timezones0.put("Africa/Mogadishu", tz);
+	timezones0.put("Africa/Nairobi", tz);
+	timezones0.put("Antarctica/Syowa", tz);
+	timezones0.put("Asia/Aden", tz);
+	timezones0.put("Asia/Bahrain", tz);
+	timezones0.put("Asia/Kuwait", tz);
+	timezones0.put("Asia/Qatar", tz);
+	timezones0.put("Asia/Riyadh", tz);
+	timezones0.put("Indian/Antananarivo", tz);
+	timezones0.put("Indian/Comoro", tz);
+	timezones0.put("Indian/Mayotte", tz);
+	tz = new SimpleTimeZone(3500 * 3600, "Asia/Tehran");
+	timezones0.put("Asia/Tehran", tz);
+	tz = new SimpleTimeZone
+	  (4000 * 3600, "Asia/Baku",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 4000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 5000 * 3600);
+	timezones0.put("Asia/Baku", tz);
+	tz = new SimpleTimeZone
+	  (4000 * 3600, "Asia/Yerevan",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Yerevan", tz);
+	timezones0.put("Europe/Samara", tz);
+	tz = new SimpleTimeZone(4000 * 3600, "NET");
+	timezones0.put("NET", tz);
+	timezones0.put("Asia/Dubai", tz);
+	timezones0.put("Asia/Muscat", tz);
+	timezones0.put("Asia/Tbilisi", tz);
+	timezones0.put("Indian/Mahe", tz);
+	timezones0.put("Indian/Mauritius", tz);
+	timezones0.put("Indian/Reunion", tz);
+	tz = new SimpleTimeZone(4500 * 3600, "Asia/Kabul");
+	timezones0.put("Asia/Kabul", tz);
+	tz = new SimpleTimeZone
+	  (5000 * 3600, "Asia/Yekaterinburg",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Yekaterinburg", tz);
+	tz = new SimpleTimeZone(5000 * 3600, "PLT");
+	timezones0.put("PLT", tz);
+	timezones0.put("Asia/Aqtau", tz);
+	timezones0.put("Asia/Aqtobe", tz);
+	timezones0.put("Asia/Ashgabat", tz);
+	timezones0.put("Asia/Dushanbe", tz);
+	timezones0.put("Asia/Karachi", tz);
+	timezones0.put("Asia/Oral", tz);
+	timezones0.put("Asia/Samarkand", tz);
+	timezones0.put("Asia/Tashkent", tz);
+	timezones0.put("Indian/Kerguelen", tz);
+	timezones0.put("Indian/Maldives", tz);
+	tz = new SimpleTimeZone(5500 * 3600, "BST");
+	timezones0.put("BST", tz);
+	timezones0.put("IST", tz);
+	timezones0.put("Asia/Calcutta", tz);
+	timezones0.put("Asia/Colombo", tz);
+	tz = new SimpleTimeZone(5750 * 3600, "Asia/Katmandu");
+	timezones0.put("Asia/Katmandu", tz);
+	tz = new SimpleTimeZone(6000 * 3600, "Antarctica/Mawson");
+	timezones0.put("Antarctica/Mawson", tz);
+	timezones0.put("Antarctica/Vostok", tz);
+	timezones0.put("Asia/Almaty", tz);
+	timezones0.put("Asia/Bishkek", tz);
+	timezones0.put("Asia/Dhaka", tz);
+	timezones0.put("Asia/Qyzylorda", tz);
+	timezones0.put("Asia/Thimphu", tz);
+	timezones0.put("Indian/Chagos", tz);
+	tz = new SimpleTimeZone
+	  (6000 * 3600, "Asia/Novosibirsk",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Novosibirsk", tz);
+	timezones0.put("Asia/Omsk", tz);
+	tz = new SimpleTimeZone(6500 * 3600, "Asia/Rangoon");
+	timezones0.put("Asia/Rangoon", tz);
+	timezones0.put("Indian/Cocos", tz);
+	tz = new SimpleTimeZone(7000 * 3600, "VST");
+	timezones0.put("VST", tz);
+	timezones0.put("Antarctica/Davis", tz);
+	timezones0.put("Asia/Bangkok", tz);
+	timezones0.put("Asia/Jakarta", tz);
+	timezones0.put("Asia/Phnom_Penh", tz);
+	timezones0.put("Asia/Pontianak", tz);
+	timezones0.put("Asia/Saigon", tz);
+	timezones0.put("Asia/Vientiane", tz);
+	timezones0.put("Indian/Christmas", tz);
+	tz = new SimpleTimeZone
+	  (7000 * 3600, "Asia/Hovd",
+	   Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600,
+	   Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600);
+	timezones0.put("Asia/Hovd", tz);
+	tz = new SimpleTimeZone
+	  (7000 * 3600, "Asia/Krasnoyarsk",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Krasnoyarsk", tz);
+	tz = new SimpleTimeZone(8000 * 3600, "CTT");
+	timezones0.put("CTT", tz);
+	timezones0.put("Antarctica/Casey", tz);
+	timezones0.put("Asia/Brunei", tz);
+	timezones0.put("Asia/Chongqing", tz);
+	timezones0.put("Asia/Harbin", tz);
+	timezones0.put("Asia/Hong_Kong", tz);
+	timezones0.put("Asia/Kashgar", tz);
+	timezones0.put("Asia/Kuala_Lumpur", tz);
+	timezones0.put("Asia/Kuching", tz);
+	timezones0.put("Asia/Macau", tz);
+	timezones0.put("Asia/Makassar", tz);
+	timezones0.put("Asia/Manila", tz);
+	timezones0.put("Asia/Shanghai", tz);
+	timezones0.put("Asia/Singapore", tz);
+	timezones0.put("Asia/Taipei", tz);
+	timezones0.put("Asia/Urumqi", tz);
+	timezones0.put("Australia/Perth", tz);
+	tz = new SimpleTimeZone
+	  (8000 * 3600, "Asia/Irkutsk",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Irkutsk", tz);
+	tz = new SimpleTimeZone
+	  (8000 * 3600, "Asia/Ulaanbaatar",
+	   Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600,
+	   Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600);
+	timezones0.put("Asia/Ulaanbaatar", tz);
+	tz = new SimpleTimeZone(8750 * 3600, "Australia/Eucla");
+	timezones0.put("Australia/Eucla", tz);
+	tz = new SimpleTimeZone
+	  (9000 * 3600, "Asia/Choibalsan",
+	   Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600,
+	   Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600);
+	timezones0.put("Asia/Choibalsan", tz);
+	tz = new SimpleTimeZone(9000 * 3600, "JST");
+	timezones0.put("JST", tz);
+	timezones0.put("Asia/Dili", tz);
+	timezones0.put("Asia/Jayapura", tz);
+	timezones0.put("Asia/Pyongyang", tz);
+	timezones0.put("Asia/Seoul", tz);
+	timezones0.put("Asia/Tokyo", tz);
+	timezones0.put("Pacific/Palau", tz);
+	tz = new SimpleTimeZone
+	  (9000 * 3600, "Asia/Yakutsk",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Yakutsk", tz);
+	tz = new SimpleTimeZone
+	  (9500 * 3600, "Australia/Adelaide",
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Australia/Adelaide", tz);
+	timezones0.put("Australia/Broken_Hill", tz);
+	tz = new SimpleTimeZone(9500 * 3600, "ACT");
+	timezones0.put("ACT", tz);
+	timezones0.put("Australia/Darwin", tz);
+	tz = new SimpleTimeZone(10000 * 3600, "Antarctica/DumontDUrville");
+	timezones0.put("Antarctica/DumontDUrville", tz);
+	timezones0.put("Australia/Brisbane", tz);
+	timezones0.put("Australia/Lindeman", tz);
+	timezones0.put("Pacific/Guam", tz);
+	timezones0.put("Pacific/Port_Moresby", tz);
+	timezones0.put("Pacific/Saipan", tz);
+	timezones0.put("Pacific/Truk", tz);
+	tz = new SimpleTimeZone
+	  (10000 * 3600, "Asia/Sakhalin",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Sakhalin", tz);
+	timezones0.put("Asia/Vladivostok", tz);
+	tz = new SimpleTimeZone
+	  (10000 * 3600, "Australia/Currie",
+	   Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Australia/Currie", tz);
+	timezones0.put("Australia/Hobart", tz);
+	tz = new SimpleTimeZone
+	  (10000 * 3600, "AET",
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("AET", tz);
+	timezones0.put("Australia/Melbourne", tz);
+	timezones0.put("Australia/Sydney", tz);
+	tz = new SimpleTimeZone
+	  (10500 * 3600, "Australia/Lord_Howe",
+	  Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600,
+	  Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, 500 * 3600);
+	timezones0.put("Australia/Lord_Howe", tz);
+	tz = new SimpleTimeZone
+	  (11000 * 3600, "Asia/Magadan",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Magadan", tz);
+	tz = new SimpleTimeZone(11000 * 3600, "SST");
+	timezones0.put("SST", tz);
+	timezones0.put("Pacific/Efate", tz);
+	timezones0.put("Pacific/Guadalcanal", tz);
+	timezones0.put("Pacific/Kosrae", tz);
+	timezones0.put("Pacific/Noumea", tz);
+	timezones0.put("Pacific/Ponape", tz);
+	tz = new SimpleTimeZone(11500 * 3600, "Pacific/Norfolk");
+	timezones0.put("Pacific/Norfolk", tz);
+	tz = new SimpleTimeZone
+	  (12000 * 3600, "NST",
+	   Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.MARCH, 3, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("NST", tz);
+	timezones0.put("Antarctica/McMurdo", tz);
+	timezones0.put("Antarctica/South_Pole", tz);
+	timezones0.put("Pacific/Auckland", tz);
+	tz = new SimpleTimeZone
+	  (12000 * 3600, "Asia/Anadyr",
+	   Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600,
+	   Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600);
+	timezones0.put("Asia/Anadyr", tz);
+	timezones0.put("Asia/Kamchatka", tz);
+	tz = new SimpleTimeZone(12000 * 3600, "Pacific/Fiji");
+	timezones0.put("Pacific/Fiji", tz);
+	timezones0.put("Pacific/Funafuti", tz);
+	timezones0.put("Pacific/Kwajalein", tz);
+	timezones0.put("Pacific/Majuro", tz);
+	timezones0.put("Pacific/Nauru", tz);
+	timezones0.put("Pacific/Tarawa", tz);
+	timezones0.put("Pacific/Wake", tz);
+	timezones0.put("Pacific/Wallis", tz);
+	tz = new SimpleTimeZone
+	  (12750 * 3600, "Pacific/Chatham",
+	   Calendar.OCTOBER, 1, Calendar.SUNDAY, 2750 * 3600,
+	   Calendar.MARCH, 3, Calendar.SUNDAY, 3750 * 3600);
+	timezones0.put("Pacific/Chatham", tz);
+	tz = new SimpleTimeZone(13000 * 3600, "Pacific/Enderbury");
+	timezones0.put("Pacific/Enderbury", tz);
+	timezones0.put("Pacific/Tongatapu", tz);
+	tz = new SimpleTimeZone(14000 * 3600, "Pacific/Kiritimati");
+	timezones0.put("Pacific/Kiritimati", tz);
+      }
+    return timezones0;
+  }
+
+  /**
+   * Maps a time zone name (with optional GMT offset and daylight time
+   * zone name) to one of the known time zones.  This method called
+   * with the result of <code>System.getProperty("user.timezone")</code>
+   * or <code>getDefaultTimeZoneId()</code>.  Note that giving one of
+   * the standard tz data names from ftp://elsie.nci.nih.gov/pub/ is
+   * preferred.  
+   * The time zone name can be given as follows:
+   * <code>(standard zone name)[(GMT offset)[(DST zone name)[DST offset]]]
+   * </code>
+   * <p>
+   * If only a (standard zone name) is given (no numbers in the
+   * String) then it gets mapped directly to the TimeZone with that
+   * name, if that fails null is returned.
+   * <p>
+   * Alternately, a POSIX-style TZ string can be given, defining the time zone:
+   * <code>std offset dst offset,date/time,date/time</code>
+   * See the glibc manual, or the man page for <code>tzset</code> for details
+   * of this format.
+   * <p>
+   * A GMT offset is the offset to add to the local time to get GMT.
+   * If a (GMT offset) is included (either in seconds or hours) then
+   * an attempt is made to find a TimeZone name matching both the name
+   * and the offset (that doesn't observe daylight time, if the
+   * timezone observes daylight time then you must include a daylight
+   * time zone name after the offset), if that fails then a TimeZone
+   * with the given GMT offset is returned (whether or not the
+   * TimeZone observes daylight time is ignored), if that also fails
+   * the GMT TimeZone is returned.
+   * <p>
+   * If the String ends with (GMT offset)(daylight time zone name)
+   * then an attempt is made to find a TimeZone with the given name and
+   * GMT offset that also observes (the daylight time zone name is not
+   * currently used in any other way), if that fails a TimeZone with
+   * the given GMT offset that observes daylight time is returned, if
+   * that also fails the GMT TimeZone is returned.
+   * <p>
+   * Examples: In Chicago, the time zone id could be "CST6CDT", but
+   * the preferred name would be "America/Chicago".  In Indianapolis
+   * (which does not have Daylight Savings Time) the string could be
+   * "EST5", but the preferred name would be "America/Indianapolis".
+   * The standard time zone name for The Netherlands is "Europe/Amsterdam",
+   * but can also be given as "CET-1CEST".
+   */
+  static TimeZone getDefaultTimeZone(String sysTimeZoneId)
+  {
+    String stdName = null;
+    String dstName;
+    int stdOffs;
+    int dstOffs;
+    try
+      {
+	int idLength = sysTimeZoneId.length();
+
+	int index = 0;
+	int prevIndex;
+	char c;
+
+	// get std
+	do
+	  c = sysTimeZoneId.charAt(index++);
+	while (c != '+' && c != '-' && c != ',' && c != ':'
+	       && ! Character.isDigit(c) && c != '\0' && index < idLength);
+
+	if (index >= idLength)
+	  return (TimeZone)timezones().get(sysTimeZoneId);
+
+	stdName = sysTimeZoneId.substring(0, --index);
+	prevIndex = index;
+
+	// get the std offset
+	do
+	  c = sysTimeZoneId.charAt(index++);
+	while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
+	       && index < idLength);
+	if (index < idLength)
+	  index--;
+
+	{ // convert the dst string to a millis number
+	    String offset = sysTimeZoneId.substring(prevIndex, index);
+	    prevIndex = index;
+
+	    if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
+	      stdOffs = parseTime(offset.substring(1));
+	    else
+	      stdOffs = parseTime(offset);
+
+	    if (offset.charAt(0) == '-')
+	      stdOffs = -stdOffs;
+
+	    // TZ timezone offsets are positive when WEST of the meridian.
+	    stdOffs = -stdOffs;
+	}
+
+	// Done yet? (Format: std offset)
+	if (index >= idLength)
+	  {
+	    // Do we have an existing timezone with that name and offset?
+	    TimeZone tz = (TimeZone) timezones().get(stdName);
+	    if (tz != null)
+	      if (tz.getRawOffset() == stdOffs)
+		return tz;
+
+	    // Custom then.
+	    return new SimpleTimeZone(stdOffs, stdName);
+	  }
+
+	// get dst
+	do
+	  c = sysTimeZoneId.charAt(index++);
+	while (c != '+' && c != '-' && c != ',' && c != ':'
+	       && ! Character.isDigit(c) && c != '\0' && index < idLength);
+
+	// Done yet? (Format: std offset dst)
+	if (index >= idLength)
+	  {
+	    // Do we have an existing timezone with that name and offset 
+	    // which has DST?
+	    TimeZone tz = (TimeZone) timezones().get(stdName);
+	    if (tz != null)
+	      if (tz.getRawOffset() == stdOffs && tz.useDaylightTime())
+		return tz;
+
+	    // Custom then.
+	    return new SimpleTimeZone(stdOffs, stdName);
+	  }
+
+	// get the dst offset
+	dstName = sysTimeZoneId.substring(prevIndex, --index);
+	prevIndex = index;
+	do
+	  c = sysTimeZoneId.charAt(index++);
+	while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
+	       && index < idLength);
+	if (index < idLength)
+	  index--;
+
+	{ // convert the dst string to a millis number
+	    String offset = sysTimeZoneId.substring(prevIndex, index);
+	    prevIndex = index;
+
+	    if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
+	      dstOffs = parseTime(offset.substring(1));
+	    else
+	      dstOffs = parseTime(offset);
+
+	    if (offset.charAt(0) == '-')
+	      dstOffs = -dstOffs;
+
+	    // TZ timezone offsets are positive when WEST of the meridian.
+	    dstOffs = -dstOffs;
+	}
+
+	// Done yet? (Format: std offset dst offset)
+	// FIXME: We don't support DST without a rule given. Should we?
+	if (index >= idLength)
+	  {
+	    // Time Zone existing with same name, dst and offsets?
+	    TimeZone tz = (TimeZone) timezones().get(stdName);
+	    if (tz != null)
+	      if (tz.getRawOffset() == stdOffs && tz.useDaylightTime()
+	          && tz.getDSTSavings() == (dstOffs - stdOffs))
+		return tz;
+
+	    return new SimpleTimeZone(stdOffs, stdName);
+	  }
+
+	// get the DST rule
+	if (sysTimeZoneId.charAt(index) == ','
+	    || sysTimeZoneId.charAt(index) == ';')
+	  {
+	    index++;
+	    int offs = index;
+	    while (sysTimeZoneId.charAt(index) != ','
+	           && sysTimeZoneId.charAt(index) != ';')
+	      index++;
+	    String startTime = sysTimeZoneId.substring(offs, index);
+	    index++;
+	    String endTime = sysTimeZoneId.substring(index);
+
+	    index = startTime.indexOf('/');
+	    int startMillis;
+	    int endMillis;
+	    String startDate;
+	    String endDate;
+	    if (index != -1)
+	      {
+		startDate = startTime.substring(0, index);
+		startMillis = parseTime(startTime.substring(index + 1));
+	      }
+	    else
+	      {
+		startDate = startTime;
+		// if time isn't given, default to 2:00:00 AM.
+		startMillis = 2 * 60 * 60 * 1000;
+	      }
+	    index = endTime.indexOf('/');
+	    if (index != -1)
+	      {
+		endDate = endTime.substring(0, index);
+		endMillis = parseTime(endTime.substring(index + 1));
+	      }
+	    else
+	      {
+		endDate = endTime;
+		// if time isn't given, default to 2:00:00 AM.
+		endMillis = 2 * 60 * 60 * 1000;
+	      }
+
+	    int[] start = getDateParams(startDate);
+	    int[] end = getDateParams(endDate);
+	    return new SimpleTimeZone(stdOffs, stdName, start[0], start[1],
+	                              start[2], startMillis, end[0], end[1],
+	                              end[2], endMillis, (dstOffs - stdOffs));
+	  }
+      }
+
+    // FIXME: Produce a warning here?
+    catch (IndexOutOfBoundsException _)
+      {
+      }
+    catch (NumberFormatException _)
+      {
+      }
+
+    return null;
+  }
+
+  /**
+   * Parses and returns the params for a POSIX TZ date field,
+   * in the format int[]{ month, day, dayOfWeek }, following the
+   * SimpleTimeZone constructor rules.
+   */
+  private static int[] getDateParams(String date)
+  {
+    int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+    int month;
+
+    if (date.charAt(0) == 'M' || date.charAt(0) == 'm')
+      {
+	int day;
+
+	// Month, week of month, day of week
+	month = Integer.parseInt(date.substring(1, date.indexOf('.')));
+	int week = Integer.parseInt(date.substring(date.indexOf('.') + 1,
+	                                           date.lastIndexOf('.')));
+	int dayOfWeek = Integer.parseInt(date.substring(date.lastIndexOf('.')
+	                                                + 1));
+	if (week == 5)
+	  day = -1; // last day of month is -1 in java, 5 in TZ
+	else
+	  // first day of week starting on or after.
+	  day = (week - 1) * 7 + 1;
+
+	dayOfWeek++; // Java day of week is one-based, Sunday is first day.
+	month--; // Java month is zero-based.
+	return new int[] { month, day, dayOfWeek };
+      }
+
+    // julian day, either zero-based 0<=n<=365 (incl feb 29)
+    // or one-based 1<=n<=365 (no feb 29)
+    int julianDay; // Julian day, 
+
+    if (date.charAt(0) != 'J' || date.charAt(0) != 'j')
+      {
+	julianDay = Integer.parseInt(date.substring(1));
+	julianDay++; // make 1-based
+	// Adjust day count to include feb 29.
+	dayCount = new int[]
+	           {
+	             0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
+	           };
+      }
+    else
+      // 1-based julian day
+      julianDay = Integer.parseInt(date);
+
+    int i = 11;
+    while (i > 0)
+      if (dayCount[i] < julianDay)
+	break;
+      else
+	i--;
+    julianDay -= dayCount[i];
+    month = i;
+    return new int[] { month, julianDay, 0 };
+  }
+
+  /**
+   * Parses a time field hh[:mm[:ss]], returning the result
+   * in milliseconds. No leading sign.
+   */
+  private static int parseTime(String time)
+  {
+    int millis = 0;
+    int i = 0;
+
+    while (i < time.length())
+      if (time.charAt(i) == ':')
+	break;
+      else
+	i++;
+    millis = 60 * 60 * 1000 * Integer.parseInt(time.substring(0, i));
+    if (i >= time.length())
+      return millis;
+
+    int iprev = ++i;
+    while (i < time.length())
+      if (time.charAt(i) == ':')
+	break;
+      else
+	i++;
+    if (i >= time.length())
+      return millis;
+
+    millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i));
+    millis += 1000 * Integer.parseInt(time.substring(++i));
+    return millis;
+  }
+
+  /**
+   * Gets the time zone offset, for current date, modified in case of 
+   * daylight savings.  This is the offset to add to UTC to get the local
+   * time.
+   * @param era the era of the given date
+   * @param year the year of the given date
+   * @param month the month of the given date, 0 for January.
+   * @param day the day of month
+   * @param dayOfWeek the day of week
+   * @param milliseconds the millis in the day (in local standard time)
+   * @return the time zone offset in milliseconds.
+   */
+  public abstract int getOffset(int era, int year, int month,
+				int day, int dayOfWeek, int milliseconds);
+
+  /**
+   * Get the time zone offset for the specified date, modified in case of
+   * daylight savings.  This is the offset to add to UTC to get the local
+   * time.
+   * @param date the date represented in millisecends
+   * since January 1, 1970 00:00:00 GMT.
+   * @since 1.4
+   */
+  public int getOffset(long date)
+  {
+    return (inDaylightTime(new Date(date))
+            ? getRawOffset() + getDSTSavings()
+            : getRawOffset());
+  }
+  
+  /**
+   * Gets the time zone offset, ignoring daylight savings.  This is
+   * the offset to add to UTC to get the local time.
+   * @return the time zone offset in milliseconds.  
+   */
+  public abstract int getRawOffset();
+
+  /**
+   * Sets the time zone offset, ignoring daylight savings.  This is
+   * the offset to add to UTC to get the local time.
+   * @param offsetMillis the time zone offset to GMT.
+   */
+  public abstract void setRawOffset(int offsetMillis);
+
+  /**
+   * Gets the identifier of this time zone. For instance, PST for
+   * Pacific Standard Time.
+   * @returns the ID of this time zone.  
+   */
+  public String getID()
+  {
+    return ID;
+  }
+
+  /**
+   * Sets the identifier of this time zone. For instance, PST for
+   * Pacific Standard Time.
+   * @param id the new time zone ID.
+   * @throws NullPointerException if <code>id</code> is <code>null</code>
+   */
+  public void setID(String id)
+  {
+    if (id == null)
+      throw new NullPointerException();
+    
+    this.ID = id;
+  }
+
+  /**
+   * This method returns a string name of the time zone suitable
+   * for displaying to the user.  The string returned will be the long
+   * description of the timezone in the current locale.  The name
+   * displayed will assume daylight savings time is not in effect.
+   *
+   * @return The name of the time zone.
+   */
+  public final String getDisplayName()
+  {
+    return (getDisplayName(false, LONG, Locale.getDefault()));
+  }
+
+  /**
+   * This method returns a string name of the time zone suitable
+   * for displaying to the user.  The string returned will be the long
+   * description of the timezone in the specified locale. The name
+   * displayed will assume daylight savings time is not in effect.
+   *
+   * @param locale The locale for this timezone name.
+   *
+   * @return The name of the time zone.
+   */
+  public final String getDisplayName(Locale locale)
+  {
+    return (getDisplayName(false, LONG, locale));
+  }
+
+  /**
+   * This method returns a string name of the time zone suitable
+   * for displaying to the user.  The string returned will be of the
+   * specified type in the current locale. 
+   *
+   * @param dst Whether or not daylight savings time is in effect.
+   * @param style <code>LONG</code> for a long name, <code>SHORT</code> for
+   * a short abbreviation.
+   *
+   * @return The name of the time zone.
+   */
+  public final String getDisplayName(boolean dst, int style)
+  {
+    return (getDisplayName(dst, style, Locale.getDefault()));
+  }
+
+
+  /**
+   * This method returns a string name of the time zone suitable
+   * for displaying to the user.  The string returned will be of the
+   * specified type in the specified locale. 
+   *
+   * @param dst Whether or not daylight savings time is in effect.
+   * @param style <code>LONG</code> for a long name, <code>SHORT</code> for
+   * a short abbreviation.
+   * @param locale The locale for this timezone name.
+   *
+   * @return The name of the time zone.
+   */
+  public String getDisplayName(boolean dst, int style, Locale locale)
+  {
+    DateFormatSymbols dfs;
+    try
+      {
+	dfs = new DateFormatSymbols(locale);
+
+	// The format of the value returned is defined by us.
+	String[][]zoneinfo = dfs.getZoneStrings();
+	for (int i = 0; i < zoneinfo.length; i++)
+	  {
+	    if (zoneinfo[i][0].equals(getID()))
+	      {
+		if (!dst)
+		  {
+		    if (style == SHORT)
+		      return (zoneinfo[i][2]);
+		    else
+		      return (zoneinfo[i][1]);
+		  }
+		else
+		  {
+		    if (style == SHORT)
+		      return (zoneinfo[i][4]);
+		    else
+		      return (zoneinfo[i][3]);
+		  }
+	      }
+	  }
+      }
+    catch (MissingResourceException e)
+      {
+      }
+
+    return getDefaultDisplayName(dst);
+  }
+
+  private String getDefaultDisplayName(boolean dst)
+  {
+    int offset = getRawOffset();
+    if (dst && this instanceof SimpleTimeZone)
+      {
+	// ugly, but this is a design failure of the API:
+	// getDisplayName takes a dst parameter even though
+	// TimeZone knows nothing about daylight saving offsets.
+	offset += ((SimpleTimeZone) this).getDSTSavings();
+      }
+
+    StringBuffer sb = new StringBuffer(9);
+    sb.append("GMT");
+
+    offset = offset / (1000 * 60);
+    int hours = Math.abs(offset) / 60;
+    int minutes = Math.abs(offset) % 60;
+
+    if (minutes != 0 || hours != 0)
+      {
+	sb.append(offset >= 0 ? '+' : '-');
+	sb.append((char) ('0' + hours / 10));
+	sb.append((char) ('0' + hours % 10));
+	sb.append(':');
+	sb.append((char) ('0' + minutes / 10));
+	sb.append((char) ('0' + minutes % 10));
+      }
+
+    return sb.toString();
+  }
+
+  /** 
+   * Returns true, if this time zone uses Daylight Savings Time.
+   */
+  public abstract boolean useDaylightTime();
+
+  /**
+   * Returns true, if the given date is in Daylight Savings Time in this
+   * time zone.
+   * @param date the given Date.
+   */
+  public abstract boolean inDaylightTime(Date date);
+
+  /**
+   * Gets the daylight savings offset.  This is a positive offset in
+   * milliseconds with respect to standard time.  Typically this
+   * is one hour, but for some time zones this may be half an our.
+   * <p>The default implementation returns 3600000 milliseconds
+   * (one hour) if the time zone uses daylight savings time
+   * (as specified by {@link #useDaylightTime()}), otherwise
+   * it returns 0.
+   * @return the daylight savings offset in milliseconds.
+   * @since 1.4
+   */
+  public int getDSTSavings ()
+  {
+    return useDaylightTime () ? 3600000 : 0;
+  }
+
+  /**
+   * Gets the TimeZone for the given ID.
+   * @param ID the time zone identifier.
+   * @return The time zone for the identifier or GMT, if no such time
+   * zone exists.
+   */
+  // FIXME: XXX: JCL indicates this and other methods are synchronized.
+  public static TimeZone getTimeZone(String ID)
+  {
+    // First check timezones hash
+    TimeZone tz = (TimeZone) timezones().get(ID);
+    if (tz != null)
+      {
+	if (tz.getID().equals(ID))
+	  return tz;
+
+	// We always return a timezone with the requested ID.
+	// This is the same behaviour as with JDK1.2.
+	tz = (TimeZone) tz.clone();
+	tz.setID(ID);
+	// We also save the alias, so that we return the same
+	// object again if getTimeZone is called with the same
+	// alias.
+	timezones().put(ID, tz);
+	return tz;
+      }
+
+    // See if the ID is really a GMT offset form.
+    // Note that GMT is in the table so we know it is different.
+    if (ID.startsWith("GMT"))
+      {
+	int pos = 3;
+	int offset_direction = 1;
+
+	if (ID.charAt(pos) == '-')
+	  {
+	    offset_direction = -1;
+	    pos++;
+	  }
+	else if (ID.charAt(pos) == '+')
+	  {
+	    pos++;
+	  }
+
+	try
+	  {
+	    int hour, minute;
+
+	    String offset_str = ID.substring(pos);
+	    int idx = offset_str.indexOf(":");
+	    if (idx != -1)
+	      {
+		hour = Integer.parseInt(offset_str.substring(0, idx));
+		minute = Integer.parseInt(offset_str.substring(idx + 1));
+	      }
+	    else
+	      {
+		int offset_length = offset_str.length();
+		if (offset_length <= 2)
+		  {
+		    // Only hour
+		    hour = Integer.parseInt(offset_str);
+		    minute = 0;
+		  }
+		else
+		  {
+		    // hour and minute, not separated by colon
+		    hour = Integer.parseInt
+		      (offset_str.substring(0, offset_length - 2));
+		    minute = Integer.parseInt
+		      (offset_str.substring(offset_length - 2));
+		  }
+	      }
+
+	    return new SimpleTimeZone((hour * (60 * 60 * 1000) +
+				       minute * (60 * 1000))
+				      * offset_direction, ID);
+	  }
+	catch (NumberFormatException e)
+	  {
+	  }
+      }
+
+    // Finally, return GMT per spec
+    return getTimeZone("GMT");
+  }
+
+  /**
+   * Gets the available IDs according to the given time zone
+   * offset.  
+   * @param rawOffset the given time zone GMT offset.
+   * @return An array of IDs, where the time zone has the specified GMT
+   * offset. For example <code>{"Phoenix", "Denver"}</code>, since both have
+   * GMT-07:00, but differ in daylight savings behaviour.
+   */
+  public static String[] getAvailableIDs(int rawOffset)
+  {
+    int count = 0;
+    Iterator iter = timezones().entrySet().iterator();
+    while (iter.hasNext())
+      {
+	// Don't iterate the values, since we want to count 
+	// doubled values (aliases)
+	Map.Entry entry = (Map.Entry) iter.next();
+	if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
+	  count++;
+      }
+
+    String[] ids = new String[count];
+    count = 0;
+    iter = timezones().entrySet().iterator();
+    while (iter.hasNext())
+      {
+	Map.Entry entry = (Map.Entry) iter.next();
+	if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset)
+	  ids[count++] = (String) entry.getKey();
+      }
+    return ids;
+  }
+
+  /**
+   * Gets all available IDs.
+   * @return An array of all supported IDs.
+   */
+  public static String[] getAvailableIDs()
+  {
+    return (String[])
+      timezones().keySet().toArray(new String[timezones().size()]);
+  }
+
+  /**
+   * Returns the time zone under which the host is running.  This
+   * can be changed with setDefault.
+   *
+   * @return A clone of the current default time zone for this host.
+   * @see #setDefault
+   */
+  public static TimeZone getDefault()
+  {
+    return (TimeZone) defaultZone().clone();
+  }
+
+  public static void setDefault(TimeZone zone)
+  {
+    // Hmmmm. No Security checks?
+    defaultZone0 = zone;
+  }
+
+  /**
+   * Test if the other time zone uses the same rule and only
+   * possibly differs in ID.  This implementation for this particular
+   * class will return true if the raw offsets are identical.  Subclasses
+   * should override this method if they use daylight savings.
+   * @return true if this zone has the same raw offset
+   */
+  public boolean hasSameRules(TimeZone other)
+  {
+    return other.getRawOffset() == getRawOffset();
+  }
+
+  /**
+   * Returns a clone of this object.  I can't imagine, why this is
+   * useful for a time zone.
+   */
+  public Object clone()
+  {
+    try
+      {
+	return super.clone();
+      }
+    catch (CloneNotSupportedException ex)
+      {
+	return null;
+      }
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/Timer.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/Timer.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/Timer.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/Timer.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,704 @@
+/* Timer.java -- Timer that runs TimerTasks at a later time.
+   Copyright (C) 2000, 2001, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+/**
+ * Timer that can run TimerTasks at a later time.
+ * TimerTasks can be scheduled for one time execution at some time in the
+ * future. They can be scheduled to be rescheduled at a time period after the
+ * task was last executed. Or they can be scheduled to be executed repeatedly
+ * at a fixed rate.
+ * <p>
+ * The normal scheduling will result in a more or less even delay in time
+ * between successive executions, but the executions could drift in time if
+ * the task (or other tasks) takes a long time to execute. Fixed delay
+ * scheduling guarantees more or less that the task will be executed at a
+ * specific time, but if there is ever a delay in execution then the period
+ * between successive executions will be shorter. The first method of
+ * repeated scheduling is preferred for repeated tasks in response to user
+ * interaction, the second method of repeated scheduling is preferred for tasks
+ * that act like alarms.
+ * <p>
+ * The Timer keeps a binary heap as a task priority queue which means that
+ * scheduling and serving of a task in a queue of n tasks costs O(log n).
+ *
+ * @see TimerTask
+ * @since 1.3
+ * @author Mark Wielaard (mark at klomp.org)
+ */
+public class Timer
+{
+  /**
+   * Priority Task Queue.
+   * TimerTasks are kept in a binary heap.
+   * The scheduler calls sleep() on the queue when it has nothing to do or
+   * has to wait. A sleeping scheduler can be notified by calling interrupt()
+   * which is automatically called by the enqueue(), cancel() and
+   * timerFinalized() methods.
+   */
+  private static final class TaskQueue
+  {
+    /** Default size of this queue */
+    private static final int DEFAULT_SIZE = 32;
+
+    /** Whether to return null when there is nothing in the queue */
+    private boolean nullOnEmpty;
+
+    /**
+     * The heap containing all the scheduled TimerTasks
+     * sorted by the TimerTask.scheduled field.
+     * Null when the stop() method has been called.
+     */
+    private TimerTask heap[];
+
+    /**
+     * The actual number of elements in the heap
+     * Can be less then heap.length.
+     * Note that heap[0] is used as a sentinel.
+     */
+    private int elements;
+
+    /**
+     * Creates a TaskQueue of default size without any elements in it.
+     */
+    public TaskQueue()
+    {
+      heap = new TimerTask[DEFAULT_SIZE];
+      elements = 0;
+      nullOnEmpty = false;
+    }
+
+    /**
+     * Adds a TimerTask at the end of the heap.
+     * Grows the heap if necessary by doubling the heap in size.
+     */
+    private void add(TimerTask task)
+    {
+      elements++;
+      if (elements == heap.length)
+	{
+	  TimerTask new_heap[] = new TimerTask[heap.length * 2];
+	  System.arraycopy(heap, 0, new_heap, 0, heap.length);
+	  heap = new_heap;
+	}
+      heap[elements] = task;
+    }
+
+    /**
+     * Removes the last element from the heap.
+     * Shrinks the heap in half if
+     * elements+DEFAULT_SIZE/2 <= heap.length/4.
+     */
+    private void remove()
+    {
+      // clear the entry first
+      heap[elements] = null;
+      elements--;
+      if (elements + DEFAULT_SIZE / 2 <= (heap.length / 4))
+	{
+	  TimerTask new_heap[] = new TimerTask[heap.length / 2];
+	  System.arraycopy(heap, 0, new_heap, 0, elements + 1);
+	  heap = new_heap;
+	}
+    }
+
+    /**
+     * Adds a task to the queue and puts it at the correct place
+     * in the heap.
+     */
+    public synchronized void enqueue(TimerTask task)
+    {
+      // Check if it is legal to add another element
+      if (heap == null)
+	{
+	  throw new IllegalStateException
+	    ("cannot enqueue when stop() has been called on queue");
+	}
+
+      heap[0] = task;		// sentinel
+      add(task);		// put the new task at the end
+      // Now push the task up in the heap until it has reached its place
+      int child = elements;
+      int parent = child / 2;
+      while (heap[parent].scheduled > task.scheduled)
+	{
+	  heap[child] = heap[parent];
+	  child = parent;
+	  parent = child / 2;
+	}
+      // This is the correct place for the new task
+      heap[child] = task;
+      heap[0] = null;		// clear sentinel
+      // Maybe sched() is waiting for a new element
+      this.notify();
+    }
+
+    /**
+     * Returns the top element of the queue.
+     * Can return null when no task is in the queue.
+     */
+    private TimerTask top()
+    {
+      if (elements == 0)
+	{
+	  return null;
+	}
+      else
+	{
+	  return heap[1];
+	}
+    }
+
+    /**
+     * Returns the top task in the Queue.
+     * Removes the element from the heap and reorders the heap first.
+     * Can return null when there is nothing in the queue.
+     */
+    public synchronized TimerTask serve()
+    {
+      // The task to return
+      TimerTask task = null;
+
+      while (task == null)
+	{
+	  // Get the next task
+	  task = top();
+
+	  // return null when asked to stop
+	  // or if asked to return null when the queue is empty
+	  if ((heap == null) || (task == null && nullOnEmpty))
+	    {
+	      return null;
+	    }
+
+	  // Do we have a task?
+	  if (task != null)
+	    {
+	      // The time to wait until the task should be served
+	      long time = task.scheduled - System.currentTimeMillis();
+	      if (time > 0)
+		{
+		  // This task should not yet be served
+		  // So wait until this task is ready
+		  // or something else happens to the queue
+		  task = null;	// set to null to make sure we call top()
+		  try
+		    {
+		      this.wait(time);
+		    }
+		  catch (InterruptedException _)
+		    {
+		    }
+		}
+	    }
+	  else
+	    {
+	      // wait until a task is added
+	      // or something else happens to the queue
+	      try
+		{
+		  this.wait();
+		}
+	      catch (InterruptedException _)
+		{
+		}
+	    }
+	}
+
+      // reconstruct the heap
+      TimerTask lastTask = heap[elements];
+      remove();
+
+      // drop lastTask at the beginning and move it down the heap
+      int parent = 1;
+      int child = 2;
+      heap[1] = lastTask;
+      while (child <= elements)
+	{
+	  if (child < elements)
+	    {
+	      if (heap[child].scheduled > heap[child + 1].scheduled)
+		{
+		  child++;
+		}
+	    }
+
+	  if (lastTask.scheduled <= heap[child].scheduled)
+	    break;		// found the correct place (the parent) - done
+
+	  heap[parent] = heap[child];
+	  parent = child;
+	  child = parent * 2;
+	}
+
+      // this is the correct new place for the lastTask
+      heap[parent] = lastTask;
+
+      // return the task
+      return task;
+    }
+
+    /**
+     * When nullOnEmpty is true the serve() method will return null when
+     * there are no tasks in the queue, otherwise it will wait until
+     * a new element is added to the queue. It is used to indicate to
+     * the scheduler that no new tasks will ever be added to the queue.
+     */
+    public synchronized void setNullOnEmpty(boolean nullOnEmpty)
+    {
+      this.nullOnEmpty = nullOnEmpty;
+      this.notify();
+    }
+
+    /**
+     * When this method is called the current and all future calls to
+     * serve() will return null. It is used to indicate to the Scheduler
+     * that it should stop executing since no more tasks will come.
+     */
+    public synchronized void stop()
+    {
+      this.heap = null;
+      this.elements = 0;
+      this.notify();
+    }
+
+    /**
+     * Remove all canceled tasks from the queue.
+     */
+    public synchronized int purge()
+    {
+      int removed = 0;
+      // Null out any elements that are canceled.  Skip element 0 as
+      // it is the sentinel.
+      for (int i = elements; i > 0; --i)
+        {
+          if (heap[i].scheduled < 0)
+            {
+              ++removed;
+              
+              // Remove an element by pushing the appropriate child
+              // into place, and then iterating to the bottom of the
+              // tree.
+              int index = i;
+              while (heap[index] != null)
+                {
+                  int child = 2 * index;
+                  if (child >= heap.length)
+                    {
+                      // Off end; we're done.
+                      heap[index] = null;
+                      break;
+                    }
+                  
+                  if (child + 1 >= heap.length || heap[child + 1] == null)
+                    {
+                      // Nothing -- we're done.
+                    }
+                  else if (heap[child] == null
+                      || (heap[child].scheduled
+                          > heap[child + 1].scheduled))
+                    ++child;
+                  heap[index] = heap[child];
+                  index = child;
+                }
+            }
+        }
+      
+      // Make a new heap if we shrank enough.
+      int newLen = heap.length;
+      while (elements - removed + DEFAULT_SIZE / 2 <= newLen / 4)
+        newLen /= 2;
+      if (newLen != heap.length)
+        {
+          TimerTask[] newHeap = new TimerTask[newLen];
+          System.arraycopy(heap, 0, newHeap, 0, elements + 1);
+          heap = newHeap;
+        }
+      
+      return removed;
+    }
+  }				// TaskQueue
+
+  /**
+   * The scheduler that executes all the tasks on a particular TaskQueue,
+   * reschedules any repeating tasks and that waits when no task has to be
+   * executed immediately. Stops running when canceled or when the parent
+   * Timer has been finalized and no more tasks have to be executed.
+   */
+  private static final class Scheduler implements Runnable
+  {
+    // The priority queue containing all the TimerTasks.
+    private TaskQueue queue;
+
+    /**
+     * Creates a new Scheduler that will schedule the tasks on the
+     * given TaskQueue.
+     */
+    public Scheduler(TaskQueue queue)
+    {
+      this.queue = queue;
+    }
+
+    public void run()
+    {
+      TimerTask task;
+      while ((task = queue.serve()) != null)
+	{
+	  // If this task has not been canceled
+	  if (task.scheduled >= 0)
+	    {
+
+	      // Mark execution time
+	      task.lastExecutionTime = task.scheduled;
+
+	      // Repeatable task?
+	      if (task.period < 0)
+		{
+		  // Last time this task is executed
+		  task.scheduled = -1;
+		}
+
+	      // Run the task
+	      try
+		{
+		  task.run();
+		}
+              catch (ThreadDeath death)
+                {
+                  // If an exception escapes, the Timer becomes invalid.
+                  queue.stop();
+                  throw death;
+                }
+	      catch (Throwable t)
+		{
+		  // If an exception escapes, the Timer becomes invalid.
+                  queue.stop();
+		}
+	    }
+
+	  // Calculate next time and possibly re-enqueue.
+	  if (task.scheduled >= 0)
+	    {
+	      if (task.fixed)
+		{
+		  task.scheduled += task.period;
+		}
+	      else
+		{
+		  task.scheduled = task.period + System.currentTimeMillis();
+		}
+
+	      try
+	        {
+	          queue.enqueue(task);
+		}
+	      catch (IllegalStateException ise)
+	        {
+		  // Ignore. Apparently the Timer queue has been stopped.
+		}
+	    }
+	}
+    }
+  }				// Scheduler
+
+  // Number of Timers created.
+  // Used for creating nice Thread names.
+  private static int nr;
+
+  // The queue that all the tasks are put in.
+  // Given to the scheduler
+  private TaskQueue queue;
+
+  // The Scheduler that does all the real work
+  private Scheduler scheduler;
+
+  // Used to run the scheduler.
+  // Also used to checked if the Thread is still running by calling
+  // thread.isAlive(). Sometimes a Thread is suddenly killed by the system
+  // (if it belonged to an Applet).
+  private Thread thread;
+
+  // When cancelled we don't accept any more TimerTasks.
+  private boolean canceled;
+
+  /**
+   * Creates a new Timer with a non daemon Thread as Scheduler, with normal
+   * priority and a default name.
+   */
+  public Timer()
+  {
+    this(false);
+  }
+
+  /**
+   * Creates a new Timer with a daemon Thread as scheduler if daemon is true,
+   * with normal priority and a default name.
+   */
+  public Timer(boolean daemon)
+  {
+    this(daemon, Thread.NORM_PRIORITY);
+  }
+
+  /**
+   * Create a new Timer whose Thread has the indicated name.  It will have 
+   * normal priority and will not be a daemon thread. 
+   * @param name the name of the Thread
+   * @since 1.5
+   */
+  public Timer(String name)
+  {
+    this(false, Thread.NORM_PRIORITY, name);
+  }
+
+  /**
+   * Create a new Timer whose Thread has the indicated name.  It will have 
+   * normal priority.  The boolean argument controls whether or not it
+   * will be a daemon thread.
+   * @param name the name of the Thread
+   * @param daemon true if the Thread should be a daemon thread
+   * @since 1.5
+   */
+  public Timer(String name, boolean daemon)
+  {
+    this(daemon, Thread.NORM_PRIORITY, name);
+  }
+
+  /**
+   * Creates a new Timer with a daemon Thread as scheduler if daemon is true,
+   * with the priority given and a default name.
+   */
+  private Timer(boolean daemon, int priority)
+  {
+    this(daemon, priority, "Timer-" + (++nr));
+  }
+
+  /**
+   * Creates a new Timer with a daemon Thread as scheduler if daemon is true,
+   * with the priority and name given.E
+   */
+  private Timer(boolean daemon, int priority, String name)
+  {
+    canceled = false;
+    queue = new TaskQueue();
+    scheduler = new Scheduler(queue);
+    thread = new Thread(scheduler, name);
+    thread.setDaemon(daemon);
+    thread.setPriority(priority);
+    thread.start();
+  }
+
+  /**
+   * Cancels the execution of the scheduler. If a task is executing it will
+   * normally finish execution, but no other tasks will be executed and no
+   * more tasks can be scheduled.
+   */
+  public void cancel()
+  {
+    canceled = true;
+    queue.stop();
+  }
+
+  /**
+   * Schedules the task at Time time, repeating every period
+   * milliseconds if period is positive and at a fixed rate if fixed is true.
+   *
+   * @exception IllegalArgumentException if time is negative
+   * @exception IllegalStateException if the task was already scheduled or
+   * canceled or this Timer is canceled or the scheduler thread has died
+   */
+  private void schedule(TimerTask task, long time, long period, boolean fixed)
+  {
+    if (time < 0)
+      throw new IllegalArgumentException("negative time");
+
+    if (task.scheduled == 0 && task.lastExecutionTime == -1)
+      {
+	task.scheduled = time;
+	task.period = period;
+	task.fixed = fixed;
+      }
+    else
+      {
+	throw new IllegalStateException
+	  ("task was already scheduled or canceled");
+      }
+
+    if (!this.canceled && this.thread != null)
+      {
+	queue.enqueue(task);
+      }
+    else
+      {
+	throw new IllegalStateException
+	  ("timer was canceled or scheduler thread has died");
+      }
+  }
+
+  private static void positiveDelay(long delay)
+  {
+    if (delay < 0)
+      {
+	throw new IllegalArgumentException("delay is negative");
+      }
+  }
+
+  private static void positivePeriod(long period)
+  {
+    if (period < 0)
+      {
+	throw new IllegalArgumentException("period is negative");
+      }
+  }
+
+  /**
+   * Schedules the task at the specified data for one time execution.
+   *
+   * @exception IllegalArgumentException if date.getTime() is negative
+   * @exception IllegalStateException if the task was already scheduled or
+   * canceled or this Timer is canceled or the scheduler thread has died
+   */
+  public void schedule(TimerTask task, Date date)
+  {
+    long time = date.getTime();
+    schedule(task, time, -1, false);
+  }
+
+  /**
+   * Schedules the task at the specified date and reschedules the task every
+   * period milliseconds after the last execution of the task finishes until
+   * this timer or the task is canceled.
+   *
+   * @exception IllegalArgumentException if period or date.getTime() is
+   * negative
+   * @exception IllegalStateException if the task was already scheduled or
+   * canceled or this Timer is canceled or the scheduler thread has died
+   */
+  public void schedule(TimerTask task, Date date, long period)
+  {
+    positivePeriod(period);
+    long time = date.getTime();
+    schedule(task, time, period, false);
+  }
+
+  /**
+   * Schedules the task after the specified delay milliseconds for one time
+   * execution.
+   *
+   * @exception IllegalArgumentException if delay or
+   * System.currentTimeMillis + delay is negative
+   * @exception IllegalStateException if the task was already scheduled or
+   * canceled or this Timer is canceled or the scheduler thread has died
+   */
+  public void schedule(TimerTask task, long delay)
+  {
+    positiveDelay(delay);
+    long time = System.currentTimeMillis() + delay;
+    schedule(task, time, -1, false);
+  }
+
+  /**
+   * Schedules the task after the delay milliseconds and reschedules the
+   * task every period milliseconds after the last execution of the task
+   * finishes until this timer or the task is canceled.
+   *
+   * @exception IllegalArgumentException if delay or period is negative
+   * @exception IllegalStateException if the task was already scheduled or
+   * canceled or this Timer is canceled or the scheduler thread has died
+   */
+  public void schedule(TimerTask task, long delay, long period)
+  {
+    positiveDelay(delay);
+    positivePeriod(period);
+    long time = System.currentTimeMillis() + delay;
+    schedule(task, time, period, false);
+  }
+
+  /**
+   * Schedules the task at the specified date and reschedules the task at a
+   * fixed rate every period milliseconds until this timer or the task is
+   * canceled.
+   *
+   * @exception IllegalArgumentException if period or date.getTime() is
+   * negative
+   * @exception IllegalStateException if the task was already scheduled or
+   * canceled or this Timer is canceled or the scheduler thread has died
+   */
+  public void scheduleAtFixedRate(TimerTask task, Date date, long period)
+  {
+    positivePeriod(period);
+    long time = date.getTime();
+    schedule(task, time, period, true);
+  }
+
+  /**
+   * Schedules the task after the delay milliseconds and reschedules the task
+   * at a fixed rate every period milliseconds until this timer or the task
+   * is canceled.
+   *
+   * @exception IllegalArgumentException if delay or
+   * System.currentTimeMillis + delay is negative
+   * @exception IllegalStateException if the task was already scheduled or
+   * canceled or this Timer is canceled or the scheduler thread has died
+   */
+  public void scheduleAtFixedRate(TimerTask task, long delay, long period)
+  {
+    positiveDelay(delay);
+    positivePeriod(period);
+    long time = System.currentTimeMillis() + delay;
+    schedule(task, time, period, true);
+  }
+
+  /**
+   * Tells the scheduler that the Timer task died
+   * so there will be no more new tasks scheduled.
+   */
+  protected void finalize() throws Throwable
+  {
+    queue.setNullOnEmpty(true);
+  }
+  
+  /**
+   * Removes all cancelled tasks from the queue.
+   * @return the number of tasks removed
+   * @since 1.5
+   */
+  public int purge()
+  {
+    return queue.purge();
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/TimerTask.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/TimerTask.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/TimerTask.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/TimerTask.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,145 @@
+/* TimerTask.java -- Task that can be run at a later time if given to a Timer.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+/**
+ * Task that can be run at a later time if given to a Timer.
+ * The TimerTask must implement a run method that will be called by the
+ * Timer when the task is scheduled for execution. The task can check when
+ * it should have been scheduled and cancel itself when no longer needed.
+ * <p>
+ * Example:
+ * <pre>
+ *  Timer timer = new Timer();
+ *  TimerTask task = new TimerTask() {
+ *      public void run() {
+ *      if (this.scheduledExecutionTime() < System.currentTimeMillis() + 500)
+ *          // Do something
+ *      else
+ *          // Complain: We are more then half a second late!
+ *      if (someStopCondition)
+ *          this.cancel(); // This was our last execution
+ *  };
+ *  timer.scheduleAtFixedRate(task, 1000, 1000); // schedule every second
+ * </pre>
+ * <p>
+ * Note that a TimerTask object is a one shot object and can only given once
+ * to a Timer. (The Timer will use the TimerTask object for bookkeeping,
+ * in this implementation).
+ * <p>
+ * This class also implements <code>Runnable</code> to make it possible to
+ * give a TimerTask directly as a target to a <code>Thread</code>.
+ *
+ * @see Timer
+ * @since 1.3
+ * @author Mark Wielaard (mark at klomp.org)
+ */
+public abstract class TimerTask implements Runnable
+{
+  /**
+   * If positive the next time this task should be run.
+   * If negative this TimerTask is canceled or executed for the last time.
+   */
+  long scheduled;
+
+  /**
+   * If positive the last time this task was run.
+   * If negative this TimerTask has not yet been scheduled.
+   */
+  long lastExecutionTime;
+
+  /**
+   * If positive the number of milliseconds between runs of this task.
+   * If -1 this task doesn't have to be run more then once.
+   */
+  long period;
+
+  /**
+   * If true the next time this task should be run is relative to
+   * the last scheduled time, otherwise it can drift in time.
+   */
+  boolean fixed;
+
+  /**
+   * Creates a TimerTask and marks it as not yet scheduled.
+   */
+  protected TimerTask()
+  {
+    this.scheduled = 0;
+    this.lastExecutionTime = -1;
+  }
+
+  /**
+   * Marks the task as canceled and prevents any further execution.
+   * Returns true if the task was scheduled for any execution in the future
+   * and this cancel operation prevents that execution from happening.
+   * <p>
+   * A task that has been canceled can never be scheduled again.
+   * <p>
+   * In this implementation the TimerTask it is possible that the Timer does
+   * keep a reference to the TimerTask until the first time the TimerTask
+   * is actually scheduled. But the reference will disappear immediatly when
+   * cancel is called from within the TimerTask run method.
+   */
+  public boolean cancel()
+  {
+    boolean prevented_execution = (this.scheduled >= 0);
+    this.scheduled = -1;
+    return prevented_execution;
+  }
+
+  /**
+   * Method that is called when this task is scheduled for execution.
+   */
+  public abstract void run();
+
+  /**
+   * Returns the last time this task was scheduled or (when called by the
+   * task from the run method) the time the current execution of the task
+   * was scheduled. When the task has not yet run the return value is
+   * undefined.
+   * <p>
+   * Can be used (when the task is scheduled at fixed rate) to see the
+   * difference between the requested schedule time and the actual time
+   * that can be found with <code>System.currentTimeMillis()</code>.
+   */
+  public long scheduledExecutionTime()
+  {
+    return lastExecutionTime;
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/TooManyListenersException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/TooManyListenersException.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/TooManyListenersException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/TooManyListenersException.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,78 @@
+/* TooManyListenersException.java -- thrown when a unicast event can't accept
+   another Listener
+   Copyright (C) 1998, 1999, 2001, 2002, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+/**
+ * This exception is part of the java event model.  It is thrown if an
+ * event listener is added via the addXyzEventListener method, but the
+ * object doesn't support any more listeners, e.g. it only supports a
+ * single event listener.
+ *
+ * @author Jochen Hoenicke
+ * @author Warren Levy (warrenl at cygnus.com)
+ * @see EventListener
+ * @see EventObject
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class TooManyListenersException extends Exception
+{
+  /**
+   * Compatible with JDK 1.1+.
+   */
+  private static final long serialVersionUID = 5074640544770687831L;
+
+  /**
+   * Constructs a TooManyListenersException with no detail message.
+   */
+  public TooManyListenersException()
+  {
+  }
+
+  /**
+   * Constructs a TooManyListenersException with a detail message.
+   *
+   * @param detail the detail message
+   */
+  public TooManyListenersException(String detail)
+  {
+    super(detail);
+  }
+}

Added: llvm-gcc-4.2/trunk/libjava/classpath/java/util/TreeMap.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/java/util/TreeMap.java?rev=43913&view=auto

==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/java/util/TreeMap.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/java/util/TreeMap.java Thu Nov  8 16:56:19 2007
@@ -0,0 +1,1778 @@
+/* TreeMap.java -- a class providing a basic Red-Black Tree data structure,
+   mapping Object --> Object
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * This class provides a red-black tree implementation of the SortedMap
+ * interface.  Elements in the Map will be sorted by either a user-provided
+ * Comparator object, or by the natural ordering of the keys.
+ *
+ * The algorithms are adopted from Corman, Leiserson, and Rivest's
+ * <i>Introduction to Algorithms.</i>  TreeMap guarantees O(log n)
+ * insertion and deletion of elements.  That being said, there is a large
+ * enough constant coefficient in front of that "log n" (overhead involved
+ * in keeping the tree balanced), that TreeMap may not be the best choice
+ * for small collections. If something is already sorted, you may want to
+ * just use a LinkedHashMap to maintain the order while providing O(1) access.
+ *
+ * TreeMap is a part of the JDK1.2 Collections API.  Null keys are allowed
+ * only if a Comparator is used which can deal with them; natural ordering
+ * cannot cope with null.  Null values are always allowed. Note that the
+ * ordering must be <i>consistent with equals</i> to correctly implement
+ * the Map interface. If this condition is violated, the map is still
+ * well-behaved, but you may have suprising results when comparing it to
+ * other maps.<p>
+ *
+ * This implementation is not synchronized. If you need to share this between
+ * multiple threads, do something like:<br>
+ * <code>SortedMap m
+ *       = Collections.synchronizedSortedMap(new TreeMap(...));</code><p>
+ *
+ * The iterators are <i>fail-fast</i>, meaning that any structural
+ * modification, except for <code>remove()</code> called on the iterator
+ * itself, cause the iterator to throw a
+ * <code>ConcurrentModificationException</code> rather than exhibit
+ * non-deterministic behavior.
+ *
+ * @author Jon Zeppieri
+ * @author Bryce McKinlay
+ * @author Eric Blake (ebb9 at email.byu.edu)
+ * @see Map
+ * @see HashMap
+ * @see Hashtable
+ * @see LinkedHashMap
+ * @see Comparable
+ * @see Comparator
+ * @see Collection
+ * @see Collections#synchronizedSortedMap(SortedMap)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class TreeMap extends AbstractMap
+  implements SortedMap, Cloneable, Serializable
+{
+  // Implementation note:
+  // A red-black tree is a binary search tree with the additional properties
+  // that all paths to a leaf node visit the same number of black nodes,
+  // and no red node has red children. To avoid some null-pointer checks,
+  // we use the special node nil which is always black, has no relatives,
+  // and has key and value of null (but is not equal to a mapping of null).
+
+  /**
+   * Compatible with JDK 1.2.
+   */
+  private static final long serialVersionUID = 919286545866124006L;
+
+  /**
+   * Color status of a node. Package visible for use by nested classes.
+   */
+  static final int RED = -1,
+                   BLACK = 1;
+
+  /**
+   * Sentinal node, used to avoid null checks for corner cases and make the
+   * delete rebalance code simpler. The rebalance code must never assign
+   * the parent, left, or right of nil, but may safely reassign the color
+   * to be black. This object must never be used as a key in a TreeMap, or
+   * it will break bounds checking of a SubMap.
+   */
+  static final Node nil = new Node(null, null, BLACK);
+  static
+    {
+      // Nil is self-referential, so we must initialize it after creation.
+      nil.parent = nil;
+      nil.left = nil;
+      nil.right = nil;
+    }
+
+  /**
+   * The root node of this TreeMap.
+   */
+  private transient Node root;
+
+  /**
+   * The size of this TreeMap. Package visible for use by nested classes.
+   */
+  transient int size;
+
+  /**
+   * The cache for {@link #entrySet()}.
+   */
+  private transient Set entries;
+
+  /**
+   * Counts the number of modifications this TreeMap has undergone, used
+   * by Iterators to know when to throw ConcurrentModificationExceptions.
+   * Package visible for use by nested classes.
+   */
+  transient int modCount;
+
+  /**
+   * This TreeMap's comparator, or null for natural ordering.
+   * Package visible for use by nested classes.
+   * @serial the comparator ordering this tree, or null
+   */
+  final Comparator comparator;
+
+  /**
+   * Class to represent an entry in the tree. Holds a single key-value pair,
+   * plus pointers to parent and child nodes.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private static final class Node extends AbstractMap.BasicMapEntry
+  {
+    // All fields package visible for use by nested classes.
+    /** The color of this node. */
+    int color;
+
+    /** The left child node. */
+    Node left = nil;
+    /** The right child node. */
+    Node right = nil;
+    /** The parent node. */
+    Node parent = nil;
+
+    /**
+     * Simple constructor.
+     * @param key the key
+     * @param value the value
+     */
+    Node(Object key, Object value, int color)
+    {
+      super(key, value);
+      this.color = color;
+    }
+  }
+
+  /**
+   * Instantiate a new TreeMap with no elements, using the keys' natural
+   * ordering to sort. All entries in the map must have a key which implements
+   * Comparable, and which are <i>mutually comparable</i>, otherwise map
+   * operations may throw a {@link ClassCastException}. Attempts to use
+   * a null key will throw a {@link NullPointerException}.
+   *
+   * @see Comparable
+   */
+  public TreeMap()
+  {
+    this((Comparator) null);
+  }
+
+  /**
+   * Instantiate a new TreeMap with no elements, using the provided comparator
+   * to sort. All entries in the map must have keys which are mutually
+   * comparable by the Comparator, otherwise map operations may throw a
+   * {@link ClassCastException}.
+   *
+   * @param c the sort order for the keys of this map, or null
+   *        for the natural order
+   */
+  public TreeMap(Comparator c)
+  {
+    comparator = c;
+    fabricateTree(0);
+  }
+
+  /**
+   * Instantiate a new TreeMap, initializing it with all of the elements in
+   * the provided Map.  The elements will be sorted using the natural
+   * ordering of the keys. This algorithm runs in n*log(n) time. All entries
+   * in the map must have keys which implement Comparable and are mutually
+   * comparable, otherwise map operations may throw a
+   * {@link ClassCastException}.
+   *
+   * @param map a Map, whose entries will be put into this TreeMap
+   * @throws ClassCastException if the keys in the provided Map are not
+   *         comparable
+   * @throws NullPointerException if map is null
+   * @see Comparable
+   */
+  public TreeMap(Map map)
+  {
+    this((Comparator) null);
+    putAll(map);
+  }
+
+  /**
+   * Instantiate a new TreeMap, initializing it with all of the elements in
+   * the provided SortedMap.  The elements will be sorted using the same
+   * comparator as in the provided SortedMap. This runs in linear time.
+   *
+   * @param sm a SortedMap, whose entries will be put into this TreeMap
+   * @throws NullPointerException if sm is null
+   */
+  public TreeMap(SortedMap sm)
+  {
+    this(sm.comparator());
+    int pos = sm.size();
+    Iterator itr = sm.entrySet().iterator();
+
+    fabricateTree(pos);
+    Node node = firstNode();
+
+    while (--pos >= 0)
+      {
+        Map.Entry me = (Map.Entry) itr.next();
+        node.key = me.getKey();
+        node.value = me.getValue();
+        node = successor(node);
+      }
+  }
+
+  /**
+   * Clears the Map so it has no keys. This is O(1).
+   */
+  public void clear()
+  {
+    if (size > 0)
+      {
+        modCount++;
+        root = nil;
+        size = 0;
+      }
+  }
+
+  /**
+   * Returns a shallow clone of this TreeMap. The Map itself is cloned,
+   * but its contents are not.
+   *
+   * @return the clone
+   */
+  public Object clone()
+  {
+    TreeMap copy = null;
+    try
+      {
+        copy = (TreeMap) super.clone();
+      }
+    catch (CloneNotSupportedException x)
+      {
+      }
+    copy.entries = null;
+    copy.fabricateTree(size);
+
+    Node node = firstNode();
+    Node cnode = copy.firstNode();
+
+    while (node != nil)
+      {
+        cnode.key = node.key;
+        cnode.value = node.value;
+        node = successor(node);
+        cnode = copy.successor(cnode);
+      }
+    return copy;
+  }
+
+  /**
+   * Return the comparator used to sort this map, or null if it is by
+   * natural order.
+   *
+   * @return the map's comparator
+   */
+  public Comparator comparator()
+  {
+    return comparator;
+  }
+
+  /**
+   * Returns true if the map contains a mapping for the given key.
+   *
+   * @param key the key to look for
+   * @return true if the key has a mapping
+   * @throws ClassCastException if key is not comparable to map elements
+   * @throws NullPointerException if key is null and the comparator is not
+   *         tolerant of nulls
+   */
+  public boolean containsKey(Object key)
+  {
+    return getNode(key) != nil;
+  }
+
+  /**
+   * Returns true if the map contains at least one mapping to the given value.
+   * This requires linear time.
+   *
+   * @param value the value to look for
+   * @return true if the value appears in a mapping
+   */
+  public boolean containsValue(Object value)
+  {
+    Node node = firstNode();
+    while (node != nil)
+      {
+        if (equals(value, node.value))
+          return true;
+        node = successor(node);
+      }
+    return false;
+  }
+
+  /**
+   * Returns a "set view" of this TreeMap's entries. The set is backed by
+   * the TreeMap, so changes in one show up in the other.  The set supports
+   * element removal, but not element addition.<p>
+   *
+   * Note that the iterators for all three views, from keySet(), entrySet(),
+   * and values(), traverse the TreeMap in sorted sequence.
+   *
+   * @return a set view of the entries
+   * @see #keySet()
+   * @see #values()
+   * @see Map.Entry
+   */
+  public Set entrySet()
+  {
+    if (entries == null)
+      // Create an AbstractSet with custom implementations of those methods
+      // that can be overriden easily and efficiently.
+      entries = new AbstractSet()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          return new TreeIterator(ENTRIES);
+        }
+
+        public void clear()
+        {
+          TreeMap.this.clear();
+        }
+
+        public boolean contains(Object o)
+        {
+          if (! (o instanceof Map.Entry))
+            return false;
+          Map.Entry me = (Map.Entry) o;
+          Node n = getNode(me.getKey());
+          return n != nil && AbstractSet.equals(me.getValue(), n.value);
+      }
+
+        public boolean remove(Object o)
+        {
+          if (! (o instanceof Map.Entry))
+            return false;
+          Map.Entry me = (Map.Entry) o;
+          Node n = getNode(me.getKey());
+          if (n != nil && AbstractSet.equals(me.getValue(), n.value))
+            {
+              removeNode(n);
+              return true;
+            }
+          return false;
+        }
+      };
+    return entries;
+  }
+
+  /**
+   * Returns the first (lowest) key in the map.
+   *
+   * @return the first key
+   * @throws NoSuchElementException if the map is empty
+   */
+  public Object firstKey()
+  {
+    if (root == nil)
+      throw new NoSuchElementException();
+    return firstNode().key;
+  }
+
+  /**
+   * Return the value in this TreeMap associated with the supplied key,
+   * or <code>null</code> if the key maps to nothing.  NOTE: Since the value
+   * could also be null, you must use containsKey to see if this key
+   * actually maps to something.
+   *
+   * @param key the key for which to fetch an associated value
+   * @return what the key maps to, if present
+   * @throws ClassCastException if key is not comparable to elements in the map
+   * @throws NullPointerException if key is null but the comparator does not
+   *         tolerate nulls
+   * @see #put(Object, Object)
+   * @see #containsKey(Object)
+   */
+  public Object get(Object key)
+  {
+    // Exploit fact that nil.value == null.
+    return getNode(key).value;
+  }
+
+  /**
+   * Returns a view of this Map including all entries with keys less than
+   * <code>toKey</code>. The returned map is backed by the original, so changes
+   * in one appear in the other. The submap will throw an
+   * {@link IllegalArgumentException} for any attempt to access or add an
+   * element beyond the specified cutoff. The returned map does not include
+   * the endpoint; if you want inclusion, pass the successor element.
+   *
+   * @param toKey the (exclusive) cutoff point
+   * @return a view of the map less than the cutoff
+   * @throws ClassCastException if <code>toKey</code> is not compatible with
+   *         the comparator (or is not Comparable, for natural ordering)
+   * @throws NullPointerException if toKey is null, but the comparator does not
+   *         tolerate null elements
+   */
+  public SortedMap headMap(Object toKey)
+  {
+    return new SubMap(nil, toKey);
+  }
+
+  /**
+   * Returns a "set view" of this TreeMap's keys. The set is backed by the
+   * TreeMap, so changes in one show up in the other.  The set supports
+   * element removal, but not element addition.
+   *
+   * @return a set view of the keys
+   * @see #values()
+   * @see #entrySet()
+   */
+  public Set keySet()
+  {
+    if (keys == null)
+      // Create an AbstractSet with custom implementations of those methods
+      // that can be overriden easily and efficiently.
+      keys = new AbstractSet()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          return new TreeIterator(KEYS);
+        }
+
+        public void clear()
+        {
+          TreeMap.this.clear();
+        }
+
+        public boolean contains(Object o)
+        {
+          return containsKey(o);
+        }
+
+        public boolean remove(Object key)
+        {
+          Node n = getNode(key);
+          if (n == nil)
+            return false;
+          removeNode(n);
+          return true;
+        }
+      };
+    return keys;
+  }
+
+  /**
+   * Returns the last (highest) key in the map.
+   *
+   * @return the last key
+   * @throws NoSuchElementException if the map is empty
+   */
+  public Object lastKey()
+  {
+    if (root == nil)
+      throw new NoSuchElementException("empty");
+    return lastNode().key;
+  }
+
+  /**
+   * Puts the supplied value into the Map, mapped by the supplied key.
+   * The value may be retrieved by any object which <code>equals()</code>
+   * this key. NOTE: Since the prior value could also be null, you must
+   * first use containsKey if you want to see if you are replacing the
+   * key's mapping.
+   *
+   * @param key the key used to locate the value
+   * @param value the value to be stored in the Map
+   * @return the prior mapping of the key, or null if there was none
+   * @throws ClassCastException if key is not comparable to current map keys
+   * @throws NullPointerException if key is null, but the comparator does
+   *         not tolerate nulls
+   * @see #get(Object)
+   * @see Object#equals(Object)
+   */
+  public Object put(Object key, Object value)
+  {
+    Node current = root;
+    Node parent = nil;
+    int comparison = 0;
+
+    // Find new node's parent.
+    while (current != nil)
+      {
+        parent = current;
+        comparison = compare(key, current.key);
+        if (comparison > 0)
+          current = current.right;
+        else if (comparison < 0)
+          current = current.left;
+        else // Key already in tree.
+          return current.setValue(value);
+      }
+
+    // Set up new node.
+    Node n = new Node(key, value, RED);
+    n.parent = parent;
+
+    // Insert node in tree.
+    modCount++;
+    size++;
+    if (parent == nil)
+      {
+        // Special case inserting into an empty tree.
+        root = n;
+        return null;
+      }
+    if (comparison > 0)
+      parent.right = n;
+    else
+      parent.left = n;
+
+    // Rebalance after insert.
+    insertFixup(n);
+    return null;
+  }
+
+  /**
+   * Copies all elements of the given map into this TreeMap.  If this map
+   * already has a mapping for a key, the new mapping replaces the current
+   * one.
+   *
+   * @param m the map to be added
+   * @throws ClassCastException if a key in m is not comparable with keys
+   *         in the map
+   * @throws NullPointerException if a key in m is null, and the comparator
+   *         does not tolerate nulls
+   */
+  public void putAll(Map m)
+  {
+    Iterator itr = m.entrySet().iterator();
+    int pos = m.size();
+    while (--pos >= 0)
+      {
+        Map.Entry e = (Map.Entry) itr.next();
+        put(e.getKey(), e.getValue());
+      }
+  }
+
+  /**
+   * Removes from the TreeMap and returns the value which is mapped by the
+   * supplied key. If the key maps to nothing, then the TreeMap remains
+   * unchanged, and <code>null</code> is returned. NOTE: Since the value
+   * could also be null, you must use containsKey to see if you are
+   * actually removing a mapping.
+   *
+   * @param key the key used to locate the value to remove
+   * @return whatever the key mapped to, if present
+   * @throws ClassCastException if key is not comparable to current map keys
+   * @throws NullPointerException if key is null, but the comparator does
+   *         not tolerate nulls
+   */
+  public Object remove(Object key)
+  {
+    Node n = getNode(key);
+    if (n == nil)
+      return null;
+    // Note: removeNode can alter the contents of n, so save value now.
+    Object result = n.value;
+    removeNode(n);
+    return result;
+  }
+
+  /**
+   * Returns the number of key-value mappings currently in this Map.
+   *
+   * @return the size
+   */
+  public int size()
+  {
+    return size;
+  }
+
+  /**
+   * Returns a view of this Map including all entries with keys greater or
+   * equal to <code>fromKey</code> and less than <code>toKey</code> (a
+   * half-open interval). The returned map is backed by the original, so
+   * changes in one appear in the other. The submap will throw an
+   * {@link IllegalArgumentException} for any attempt to access or add an
+   * element beyond the specified cutoffs. The returned map includes the low
+   * endpoint but not the high; if you want to reverse this behavior on
+   * either end, pass in the successor element.
+   *
+   * @param fromKey the (inclusive) low cutoff point
+   * @param toKey the (exclusive) high cutoff point
+   * @return a view of the map between the cutoffs
+   * @throws ClassCastException if either cutoff is not compatible with
+   *         the comparator (or is not Comparable, for natural ordering)
+   * @throws NullPointerException if fromKey or toKey is null, but the
+   *         comparator does not tolerate null elements
+   * @throws IllegalArgumentException if fromKey is greater than toKey
+   */
+  public SortedMap subMap(Object fromKey, Object toKey)
+  {
+    return new SubMap(fromKey, toKey);
+  }
+
+  /**
+   * Returns a view of this Map including all entries with keys greater or
+   * equal to <code>fromKey</code>. The returned map is backed by the
+   * original, so changes in one appear in the other. The submap will throw an
+   * {@link IllegalArgumentException} for any attempt to access or add an
+   * element beyond the specified cutoff. The returned map includes the
+   * endpoint; if you want to exclude it, pass in the successor element.
+   *
+   * @param fromKey the (inclusive) low cutoff point
+   * @return a view of the map above the cutoff
+   * @throws ClassCastException if <code>fromKey</code> is not compatible with
+   *         the comparator (or is not Comparable, for natural ordering)
+   * @throws NullPointerException if fromKey is null, but the comparator
+   *         does not tolerate null elements
+   */
+  public SortedMap tailMap(Object fromKey)
+  {
+    return new SubMap(fromKey, nil);
+  }
+
+  /**
+   * Returns a "collection view" (or "bag view") of this TreeMap's values.
+   * The collection is backed by the TreeMap, so changes in one show up
+   * in the other.  The collection supports element removal, but not element
+   * addition.
+   *
+   * @return a bag view of the values
+   * @see #keySet()
+   * @see #entrySet()
+   */
+  public Collection values()
+  {
+    if (values == null)
+      // We don't bother overriding many of the optional methods, as doing so
+      // wouldn't provide any significant performance advantage.
+      values = new AbstractCollection()
+      {
+        public int size()
+        {
+          return size;
+        }
+
+        public Iterator iterator()
+        {
+          return new TreeIterator(VALUES);
+        }
+
+        public void clear()
+        {
+          TreeMap.this.clear();
+        }
+      };
+    return values;
+  }
+
+  /**
+   * Compares two elements by the set comparator, or by natural ordering.
+   * Package visible for use by nested classes.
+   *
+   * @param o1 the first object
+   * @param o2 the second object
+   * @throws ClassCastException if o1 and o2 are not mutually comparable,
+   *         or are not Comparable with natural ordering
+   * @throws NullPointerException if o1 or o2 is null with natural ordering
+   */
+  final int compare(Object o1, Object o2)
+  {
+    return (comparator == null
+            ? ((Comparable) o1).compareTo(o2)
+            : comparator.compare(o1, o2));
+  }
+
+  /**
+   * Maintain red-black balance after deleting a node.
+   *
+   * @param node the child of the node just deleted, possibly nil
+   * @param parent the parent of the node just deleted, never nil
+   */
+  private void deleteFixup(Node node, Node parent)
+  {
+    // if (parent == nil)
+    //   throw new InternalError();
+    // If a black node has been removed, we need to rebalance to avoid
+    // violating the "same number of black nodes on any path" rule. If
+    // node is red, we can simply recolor it black and all is well.
+    while (node != root && node.color == BLACK)
+      {
+        if (node == parent.left)
+          {
+            // Rebalance left side.
+            Node sibling = parent.right;
+            // if (sibling == nil)
+            //   throw new InternalError();
+            if (sibling.color == RED)
+              {
+                // Case 1: Sibling is red.
+                // Recolor sibling and parent, and rotate parent left.
+                sibling.color = BLACK;
+                parent.color = RED;
+                rotateLeft(parent);
+                sibling = parent.right;
+              }
+
+            if (sibling.left.color == BLACK && sibling.right.color == BLACK)
+              {
+                // Case 2: Sibling has no red children.
+                // Recolor sibling, and move to parent.
+                sibling.color = RED;
+                node = parent;
+                parent = parent.parent;
+              }
+            else
+              {
+                if (sibling.right.color == BLACK)
+                  {
+                    // Case 3: Sibling has red left child.
+                    // Recolor sibling and left child, rotate sibling right.
+                    sibling.left.color = BLACK;
+                    sibling.color = RED;
+                    rotateRight(sibling);
+                    sibling = parent.right;
+                  }
+                // Case 4: Sibling has red right child. Recolor sibling,
+                // right child, and parent, and rotate parent left.
+                sibling.color = parent.color;
+                parent.color = BLACK;
+                sibling.right.color = BLACK;
+                rotateLeft(parent);
+                node = root; // Finished.
+              }
+          }
+        else
+          {
+            // Symmetric "mirror" of left-side case.
+            Node sibling = parent.left;
+            // if (sibling == nil)
+            //   throw new InternalError();
+            if (sibling.color == RED)
+              {
+                // Case 1: Sibling is red.
+                // Recolor sibling and parent, and rotate parent right.
+                sibling.color = BLACK;
+                parent.color = RED;
+                rotateRight(parent);
+                sibling = parent.left;
+              }
+
+            if (sibling.right.color == BLACK && sibling.left.color == BLACK)
+              {
+                // Case 2: Sibling has no red children.
+                // Recolor sibling, and move to parent.
+                sibling.color = RED;
+                node = parent;
+                parent = parent.parent;
+              }
+            else
+              {
+                if (sibling.left.color == BLACK)
+                  {
+                    // Case 3: Sibling has red right child.
+                    // Recolor sibling and right child, rotate sibling left.
+                    sibling.right.color = BLACK;
+                    sibling.color = RED;
+                    rotateLeft(sibling);
+                    sibling = parent.left;
+                  }
+                // Case 4: Sibling has red left child. Recolor sibling,
+                // left child, and parent, and rotate parent right.
+                sibling.color = parent.color;
+                parent.color = BLACK;
+                sibling.left.color = BLACK;
+                rotateRight(parent);
+                node = root; // Finished.
+              }
+          }
+      }
+    node.color = BLACK;
+  }
+
+  /**
+   * Construct a perfectly balanced tree consisting of n "blank" nodes. This
+   * permits a tree to be generated from pre-sorted input in linear time.
+   *
+   * @param count the number of blank nodes, non-negative
+   */
+  private void fabricateTree(final int count)
+  {
+    if (count == 0)
+      {
+	root = nil;
+	size = 0;
+	return;
+      }
+
+    // We color every row of nodes black, except for the overflow nodes.
+    // I believe that this is the optimal arrangement. We construct the tree
+    // in place by temporarily linking each node to the next node in the row,
+    // then updating those links to the children when working on the next row.
+
+    // Make the root node.
+    root = new Node(null, null, BLACK);
+    size = count;
+    Node row = root;
+    int rowsize;
+
+    // Fill each row that is completely full of nodes.
+    for (rowsize = 2; rowsize + rowsize <= count; rowsize <<= 1)
+      {
+        Node parent = row;
+        Node last = null;
+        for (int i = 0; i < rowsize; i += 2)
+          {
+            Node left = new Node(null, null, BLACK);
+            Node right = new Node(null, null, BLACK);
+            left.parent = parent;
+            left.right = right;
+            right.parent = parent;
+            parent.left = left;
+            Node next = parent.right;
+            parent.right = right;
+            parent = next;
+            if (last != null)
+              last.right = left;
+            last = right;
+          }
+        row = row.left;
+      }
+
+    // Now do the partial final row in red.
+    int overflow = count - rowsize;
+    Node parent = row;
+    int i;
+    for (i = 0; i < overflow; i += 2)
+      {
+        Node left = new Node(null, null, RED);
+        Node right = new Node(null, null, RED);
+        left.parent = parent;
+        right.parent = parent;
+        parent.left = left;
+        Node next = parent.right;
+        parent.right = right;
+        parent = next;
+      }
+    // Add a lone left node if necessary.
+    if (i - overflow == 0)
+      {
+        Node left = new Node(null, null, RED);
+        left.parent = parent;
+        parent.left = left;
+        parent = parent.right;
+        left.parent.right = nil;
+      }
+    // Unlink the remaining nodes of the previous row.
+    while (parent != nil)
+      {
+        Node next = parent.right;
+        parent.right = nil;
+        parent = next;
+      }
+  }
+
+  /**
+   * Returns the first sorted node in the map, or nil if empty. Package
+   * visible for use by nested classes.
+   *
+   * @return the first node
+   */
+  final Node firstNode()
+  {
+    // Exploit fact that nil.left == nil.
+    Node node = root;
+    while (node.left != nil)
+      node = node.left;
+    return node;
+  }
+
+  /**
+   * Return the TreeMap.Node associated with key, or the nil node if no such
+   * node exists in the tree. Package visible for use by nested classes.
+   *
+   * @param key the key to search for
+   * @return the node where the key is found, or nil
+   */
+  final Node getNode(Object key)
+  {
+    Node current = root;
+    while (current != nil)
+      {
+        int comparison = compare(key, current.key);
+        if (comparison > 0)
+          current = current.right;
+        else if (comparison < 0)
+          current = current.left;
+        else
+          return current;
+      }
+    return current;
+  }
+
+  /**
+   * Find the "highest" node which is < key. If key is nil, return last
+   * node. Package visible for use by nested classes.
+   *
+   * @param key the upper bound, exclusive
+   * @return the previous node
+   */
+  final Node highestLessThan(Object key)
+  {
+    if (key == nil)
+      return lastNode();
+
+    Node last = nil;
+    Node current = root;
+    int comparison = 0;
+
+    while (current != nil)
+      {
+        last = current;
+        comparison = compare(key, current.key);
+        if (comparison > 0)
+          current = current.right;
+        else if (comparison < 0)
+          current = current.left;
+        else // Exact match.
+          return predecessor(last);
+      }
+    return comparison <= 0 ? predecessor(last) : last;
+  }
+
+  /**
+   * Maintain red-black balance after inserting a new node.
+   *
+   * @param n the newly inserted node
+   */
+  private void insertFixup(Node n)
+  {
+    // Only need to rebalance when parent is a RED node, and while at least
+    // 2 levels deep into the tree (ie: node has a grandparent). Remember
+    // that nil.color == BLACK.
+    while (n.parent.color == RED && n.parent.parent != nil)
+      {
+        if (n.parent == n.parent.parent.left)
+          {
+            Node uncle = n.parent.parent.right;
+            // Uncle may be nil, in which case it is BLACK.
+            if (uncle.color == RED)
+              {
+                // Case 1. Uncle is RED: Change colors of parent, uncle,
+                // and grandparent, and move n to grandparent.
+                n.parent.color = BLACK;
+                uncle.color = BLACK;
+                uncle.parent.color = RED;
+                n = uncle.parent;
+              }
+            else
+              {
+                if (n == n.parent.right)
+                  {
+                    // Case 2. Uncle is BLACK and x is right child.
+                    // Move n to parent, and rotate n left.
+                    n = n.parent;
+                    rotateLeft(n);
+                  }
+                // Case 3. Uncle is BLACK and x is left child.
+                // Recolor parent, grandparent, and rotate grandparent right.
+                n.parent.color = BLACK;
+                n.parent.parent.color = RED;
+                rotateRight(n.parent.parent);
+              }
+          }
+        else
+          {
+            // Mirror image of above code.
+            Node uncle = n.parent.parent.left;
+            // Uncle may be nil, in which case it is BLACK.
+            if (uncle.color == RED)
+              {
+                // Case 1. Uncle is RED: Change colors of parent, uncle,
+                // and grandparent, and move n to grandparent.
+                n.parent.color = BLACK;
+                uncle.color = BLACK;
+                uncle.parent.color = RED;
+                n = uncle.parent;
+              }
+            else
+              {
+                if (n == n.parent.left)
+                {
+                    // Case 2. Uncle is BLACK and x is left child.
+                    // Move n to parent, and rotate n right.
+                    n = n.parent;
+                    rotateRight(n);
+                  }
+                // Case 3. Uncle is BLACK and x is right child.
+                // Recolor parent, grandparent, and rotate grandparent left.
+                n.parent.color = BLACK;
+                n.parent.parent.color = RED;
+                rotateLeft(n.parent.parent);
+              }
+          }
+      }
+    root.color = BLACK;
+  }
+
+  /**
+   * Returns the last sorted node in the map, or nil if empty.
+   *
+   * @return the last node
+   */
+  private Node lastNode()
+  {
+    // Exploit fact that nil.right == nil.
+    Node node = root;
+    while (node.right != nil)
+      node = node.right;
+    return node;
+  }
+
+  /**
+   * Find the "lowest" node which is >= key. If key is nil, return either
+   * nil or the first node, depending on the parameter first.
+   * Package visible for use by nested classes.
+   *
+   * @param key the lower bound, inclusive
+   * @param first true to return the first element instead of nil for nil key
+   * @return the next node
+   */
+  final Node lowestGreaterThan(Object key, boolean first)
+  {
+    if (key == nil)
+      return first ? firstNode() : nil;
+
+    Node last = nil;
+    Node current = root;
+    int comparison = 0;
+
+    while (current != nil)
+      {
+        last = current;
+        comparison = compare(key, current.key);
+        if (comparison > 0)
+          current = current.right;
+        else if (comparison < 0)
+          current = current.left;
+        else
+          return current;
+      }
+    return comparison > 0 ? successor(last) : last;
+  }
+
+  /**
+   * Return the node preceding the given one, or nil if there isn't one.
+   *
+   * @param node the current node, not nil
+   * @return the prior node in sorted order
+   */
+  private Node predecessor(Node node)
+  {
+    if (node.left != nil)
+      {
+        node = node.left;
+        while (node.right != nil)
+          node = node.right;
+        return node;
+      }
+
+    Node parent = node.parent;
+    // Exploit fact that nil.left == nil and node is non-nil.
+    while (node == parent.left)
+      {
+        node = parent;
+        parent = node.parent;
+      }
+    return parent;
+  }
+
+  /**
+   * Construct a tree from sorted keys in linear time. Package visible for
+   * use by TreeSet.
+   *
+   * @param s the stream to read from
+   * @param count the number of keys to read
+   * @param readValues true to read values, false to insert "" as the value
+   * @throws ClassNotFoundException if the underlying stream fails
+   * @throws IOException if the underlying stream fails
+   * @see #readObject(ObjectInputStream)
+   * @see TreeSet#readObject(ObjectInputStream)
+   */
+  final void putFromObjStream(ObjectInputStream s, int count,
+                              boolean readValues)
+    throws IOException, ClassNotFoundException
+  {
+    fabricateTree(count);
+    Node node = firstNode();
+
+    while (--count >= 0)
+      {
+        node.key = s.readObject();
+        node.value = readValues ? s.readObject() : "";
+        node = successor(node);
+      }
+  }
+
+  /**
+   * Construct a tree from sorted keys in linear time, with values of "".
+   * Package visible for use by TreeSet.
+   *
+   * @param keys the iterator over the sorted keys
+   * @param count the number of nodes to insert
+   * @see TreeSet#TreeSet(SortedSet)
+   */
+  final void putKeysLinear(Iterator keys, int count)
+  {
+    fabricateTree(count);
+    Node node = firstNode();
+
+    while (--count >= 0)
+      {
+        node.key = keys.next();
+        node.value = "";
+        node = successor(node);
+      }
+  }
+
+  /**
+   * Deserializes this object from the given stream.
+   *
+   * @param s the stream to read from
+   * @throws ClassNotFoundException if the underlying stream fails
+   * @throws IOException if the underlying stream fails
+   * @serialData the <i>size</i> (int), followed by key (Object) and value
+   *             (Object) pairs in sorted order
+   */
+  private void readObject(ObjectInputStream s)
+    throws IOException, ClassNotFoundException
+  {
+    s.defaultReadObject();
+    int size = s.readInt();
+    putFromObjStream(s, size, true);
+  }
+
+  /**
+   * Remove node from tree. This will increment modCount and decrement size.
+   * Node must exist in the tree. Package visible for use by nested classes.
+   *
+   * @param node the node to remove
+   */
+  final void removeNode(Node node)
+  {
+    Node splice;
+    Node child;
+
+    modCount++;
+    size--;
+
+    // Find splice, the node at the position to actually remove from the tree.
+    if (node.left == nil)
+      {
+        // Node to be deleted has 0 or 1 children.
+        splice = node;
+        child = node.right;
+      }
+    else if (node.right == nil)
+      {
+        // Node to be deleted has 1 child.
+        splice = node;
+        child = node.left;
+      }
+    else
+      {
+        // Node has 2 children. Splice is node's predecessor, and we swap
+        // its contents into node.
+        splice = node.left;
+        while (splice.right != nil)
+          splice = splice.right;
+        child = splice.left;
+        node.key = splice.key;
+        node.value = splice.value;
+      }
+
+    // Unlink splice from the tree.
+    Node parent = splice.parent;
+    if (child != nil)
+      child.parent = parent;
+    if (parent == nil)
+      {
+        // Special case for 0 or 1 node remaining.
+        root = child;
+        return;
+      }
+    if (splice == parent.left)
+      parent.left = child;
+    else
+      parent.right = child;
+
+    if (splice.color == BLACK)
+      deleteFixup(child, parent);
+  }
+
+  /**
+   * Rotate node n to the left.
+   *
+   * @param node the node to rotate
+   */
+  private void rotateLeft(Node node)
+  {
+    Node child = node.right;
+    // if (node == nil || child == nil)
+    //   throw new InternalError();
+
+    // Establish node.right link.
+    node.right = child.left;
+    if (child.left != nil)
+      child.left.parent = node;
+
+    // Establish child->parent link.
+    child.parent = node.parent;
+    if (node.parent != nil)
+      {
+        if (node == node.parent.left)
+          node.parent.left = child;
+        else
+          node.parent.right = child;
+      }
+    else
+      root = child;
+
+    // Link n and child.
+    child.left = node;
+    node.parent = child;
+  }
+
+  /**
+   * Rotate node n to the right.
+   *
+   * @param node the node to rotate
+   */
+  private void rotateRight(Node node)
+  {
+    Node child = node.left;
+    // if (node == nil || child == nil)
+    //   throw new InternalError();
+
+    // Establish node.left link.
+    node.left = child.right;
+    if (child.right != nil)
+      child.right.parent = node;
+
+    // Establish child->parent link.
+    child.parent = node.parent;
+    if (node.parent != nil)
+      {
+        if (node == node.parent.right)
+          node.parent.right = child;
+        else
+          node.parent.left = child;
+      }
+    else
+      root = child;
+
+    // Link n and child.
+    child.right = node;
+    node.parent = child;
+  }
+
+  /**
+   * Return the node following the given one, or nil if there isn't one.
+   * Package visible for use by nested classes.
+   *
+   * @param node the current node, not nil
+   * @return the next node in sorted order
+   */
+  final Node successor(Node node)
+  {
+    if (node.right != nil)
+      {
+        node = node.right;
+        while (node.left != nil)
+          node = node.left;
+        return node;
+      }
+
+    Node parent = node.parent;
+    // Exploit fact that nil.right == nil and node is non-nil.
+    while (node == parent.right)
+      {
+        node = parent;
+        parent = parent.parent;
+      }
+    return parent;
+  }
+
+  /**
+   * Serializes this object to the given stream.
+   *
+   * @param s the stream to write to
+   * @throws IOException if the underlying stream fails
+   * @serialData the <i>size</i> (int), followed by key (Object) and value
+   *             (Object) pairs in sorted order
+   */
+  private void writeObject(ObjectOutputStream s) throws IOException
+  {
+    s.defaultWriteObject();
+
+    Node node = firstNode();
+    s.writeInt(size);
+    while (node != nil)
+      {
+        s.writeObject(node.key);
+        s.writeObject(node.value);
+        node = successor(node);
+      }
+  }
+
+  /**
+   * Iterate over TreeMap's entries. This implementation is parameterized
+   * to give a sequential view of keys, values, or entries.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private final class TreeIterator implements Iterator
+  {
+    /**
+     * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
+     * or {@link #ENTRIES}.
+     */
+    private final int type;
+    /** The number of modifications to the backing Map that we know about. */
+    private int knownMod = modCount;
+    /** The last Entry returned by a next() call. */
+    private Node last;
+    /** The next entry that should be returned by next(). */
+    private Node next;
+    /**
+     * The last node visible to this iterator. This is used when iterating
+     * on a SubMap.
+     */
+    private final Node max;
+
+    /**
+     * Construct a new TreeIterator with the supplied type.
+     * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+     */
+    TreeIterator(int type)
+    {
+      // FIXME gcj cannot handle this. Bug java/4695
+      // this(type, firstNode(), nil);
+      this.type = type;
+      this.next = firstNode();
+      this.max = nil;
+    }
+
+    /**
+     * Construct a new TreeIterator with the supplied type. Iteration will
+     * be from "first" (inclusive) to "max" (exclusive).
+     *
+     * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+     * @param first where to start iteration, nil for empty iterator
+     * @param max the cutoff for iteration, nil for all remaining nodes
+     */
+    TreeIterator(int type, Node first, Node max)
+    {
+      this.type = type;
+      this.next = first;
+      this.max = max;
+    }
+
+    /**
+     * Returns true if the Iterator has more elements.
+     * @return true if there are more elements
+     */
+    public boolean hasNext()
+    {
+      return next != max;
+    }
+
+    /**
+     * Returns the next element in the Iterator's sequential view.
+     * @return the next element
+     * @throws ConcurrentModificationException if the TreeMap was modified
+     * @throws NoSuchElementException if there is none
+     */
+    public Object next()
+    {
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+      if (next == max)
+        throw new NoSuchElementException();
+      last = next;
+      next = successor(last);
+
+      if (type == VALUES)
+        return last.value;
+      else if (type == KEYS)
+        return last.key;
+      return last;
+    }
+
+    /**
+     * Removes from the backing TreeMap the last element which was fetched
+     * with the <code>next()</code> method.
+     * @throws ConcurrentModificationException if the TreeMap was modified
+     * @throws IllegalStateException if called when there is no last element
+     */
+    public void remove()
+    {
+      if (last == null)
+        throw new IllegalStateException();
+      if (knownMod != modCount)
+        throw new ConcurrentModificationException();
+
+      removeNode(last);
+      last = null;
+      knownMod++;
+    }
+  } // class TreeIterator
+
+  /**
+   * Implementation of {@link #subMap(Object, Object)} and other map
+   * ranges. This class provides a view of a portion of the original backing
+   * map, and throws {@link IllegalArgumentException} for attempts to
+   * access beyond that range.
+   *
+   * @author Eric Blake (ebb9 at email.byu.edu)
+   */
+  private final class SubMap extends AbstractMap implements SortedMap
+  {
+    /**
+     * The lower range of this view, inclusive, or nil for unbounded.
+     * Package visible for use by nested classes.
+     */
+    final Object minKey;
+
+    /**
+     * The upper range of this view, exclusive, or nil for unbounded.
+     * Package visible for use by nested classes.
+     */
+    final Object maxKey;
+
+    /**
+     * The cache for {@link #entrySet()}.
+     */
+    private Set entries;
+
+    /**
+     * Create a SubMap representing the elements between minKey (inclusive)
+     * and maxKey (exclusive). If minKey is nil, SubMap has no lower bound
+     * (headMap). If maxKey is nil, the SubMap has no upper bound (tailMap).
+     *
+     * @param minKey the lower bound
+     * @param maxKey the upper bound
+     * @throws IllegalArgumentException if minKey > maxKey
+     */
+    SubMap(Object minKey, Object maxKey)
+    {
+      if (minKey != nil && maxKey != nil && compare(minKey, maxKey) > 0)
+        throw new IllegalArgumentException("fromKey > toKey");
+      this.minKey = minKey;
+      this.maxKey = maxKey;
+    }
+
+    /**
+     * Check if "key" is in within the range bounds for this SubMap. The
+     * lower ("from") SubMap range is inclusive, and the upper ("to") bound
+     * is exclusive. Package visible for use by nested classes.
+     *
+     * @param key the key to check
+     * @return true if the key is in range
+     */
+    boolean keyInRange(Object key)
+    {
+      return ((minKey == nil || compare(key, minKey) >= 0)
+              && (maxKey == nil || compare(key, maxKey) < 0));
+    }
+
+    public void clear()
+    {
+      Node next = lowestGreaterThan(minKey, true);
+      Node max = lowestGreaterThan(maxKey, false);
+      while (next != max)
+        {
+          Node current = next;
+          next = successor(current);
+          removeNode(current);
+        }
+    }
+
+    public Comparator comparator()
+    {
+      return comparator;
+    }
+
+    public boolean containsKey(Object key)
+    {
+      return keyInRange(key) && TreeMap.this.containsKey(key);
+    }
+
+    public boolean containsValue(Object value)
+    {
+      Node node = lowestGreaterThan(minKey, true);
+      Node max = lowestGreaterThan(maxKey, false);
+      while (node != max)
+        {
+          if (equals(value, node.getValue()))
+            return true;
+          node = successor(node);
+        }
+      return false;
+    }
+
+    public Set entrySet()
+    {
+      if (entries == null)
+        // Create an AbstractSet with custom implementations of those methods
+        // that can be overriden easily and efficiently.
+        entries = new AbstractSet()
+        {
+          public int size()
+          {
+            return SubMap.this.size();
+          }
+
+          public Iterator iterator()
+          {
+            Node first = lowestGreaterThan(minKey, true);
+            Node max = lowestGreaterThan(maxKey, false);
+            return new TreeIterator(ENTRIES, first, max);
+          }
+
+          public void clear()
+          {
+            SubMap.this.clear();
+          }
+
+          public boolean contains(Object o)
+          {
+            if (! (o instanceof Map.Entry))
+              return false;
+            Map.Entry me = (Map.Entry) o;
+            Object key = me.getKey();
+            if (! keyInRange(key))
+              return false;
+            Node n = getNode(key);
+            return n != nil && AbstractSet.equals(me.getValue(), n.value);
+          }
+
+          public boolean remove(Object o)
+          {
+            if (! (o instanceof Map.Entry))
+              return false;
+            Map.Entry me = (Map.Entry) o;
+            Object key = me.getKey();
+            if (! keyInRange(key))
+              return false;
+            Node n = getNode(key);
+            if (n != nil && AbstractSet.equals(me.getValue(), n.value))
+              {
+                removeNode(n);
+                return true;
+              }
+            return false;
+          }
+        };
+      return entries;
+    }
+
+    public Object firstKey()
+    {
+      Node node = lowestGreaterThan(minKey, true);
+      if (node == nil || ! keyInRange(node.key))
+        throw new NoSuchElementException();
+      return node.key;
+    }
+
+    public Object get(Object key)
+    {
+      if (keyInRange(key))
+        return TreeMap.this.get(key);
+      return null;
+    }
+
+    public SortedMap headMap(Object toKey)
+    {
+      if (! keyInRange(toKey))
+        throw new IllegalArgumentException("key outside range");
+      return new SubMap(minKey, toKey);
+    }
+
+    public Set keySet()
+    {
+      if (this.keys == null)
+        // Create an AbstractSet with custom implementations of those methods
+        // that can be overriden easily and efficiently.
+        this.keys = new AbstractSet()
+        {
+          public int size()
+          {
+            return SubMap.this.size();
+          }
+
+          public Iterator iterator()
+          {
+            Node first = lowestGreaterThan(minKey, true);
+            Node max = lowestGreaterThan(maxKey, false);
+            return new TreeIterator(KEYS, first, max);
+          }
+
+          public void clear()
+          {
+            SubMap.this.clear();
+          }
+
+          public boolean contains(Object o)
+          {
+            if (! keyInRange(o))
+              return false;
+            return getNode(o) != nil;
+          }
+
+          public boolean remove(Object o)
+          {
+            if (! keyInRange(o))
+              return false;
+            Node n = getNode(o);
+            if (n != nil)
+              {
+                removeNode(n);
+                return true;
+              }
+            return false;
+          }
+        };
+      return this.keys;
+    }
+
+    public Object lastKey()
+    {
+      Node node = highestLessThan(maxKey);
+      if (node == nil || ! keyInRange(node.key))
+        throw new NoSuchElementException();
+      return node.key;
+    }
+
+    public Object put(Object key, Object value)
+    {
+      if (! keyInRange(key))
+        throw new IllegalArgumentException("Key outside range");
+      return TreeMap.this.put(key, value);
+    }
+
+    public Object remove(Object key)
+    {
+      if (keyInRange(key))
+        return TreeMap.this.remove(key);
+      return null;
+    }
+
+    public int size()
+    {
+      Node node = lowestGreaterThan(minKey, true);
+      Node max = lowestGreaterThan(maxKey, false);
+      int count = 0;
+      while (node != max)
+        {
+          count++;
+          node = successor(node);
+        }
+      return count;
+    }
+
+    public SortedMap subMap(Object fromKey, Object toKey)
+    {
+      if (! keyInRange(fromKey) || ! keyInRange(toKey))
+        throw new IllegalArgumentException("key outside range");
+      return new SubMap(fromKey, toKey);
+    }
+
+    public SortedMap tailMap(Object fromKey)
+    {
+      if (! keyInRange(fromKey))
+        throw new IllegalArgumentException("key outside range");
+      return new SubMap(fromKey, maxKey);
+    }
+
+    public Collection values()
+    {
+      if (this.values == null)
+        // Create an AbstractCollection with custom implementations of those
+        // methods that can be overriden easily and efficiently.
+        this.values = new AbstractCollection()
+        {
+          public int size()
+          {
+            return SubMap.this.size();
+          }
+
+          public Iterator iterator()
+          {
+            Node first = lowestGreaterThan(minKey, true);
+            Node max = lowestGreaterThan(maxKey, false);
+            return new TreeIterator(VALUES, first, max);
+          }
+
+          public void clear()
+          {
+            SubMap.this.clear();
+          }
+        };
+      return this.values;
+    }
+  } // class SubMap  
+} // class TreeMap





More information about the llvm-commits mailing list