aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/util
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2002-06-18 15:40:16 +0000
committerTom Tromey <tromey@gcc.gnu.org>2002-06-18 15:40:16 +0000
commit3831381763ca5f41d6f7406d590e1e38a8531e1c (patch)
tree6b8dcd38b7dbb7c4c618080eb1958b6f042d581c /libjava/java/util
parent0fd534ed06e92a7232b2373321f113ee8dd482c4 (diff)
downloadgcc-3831381763ca5f41d6f7406d590e1e38a8531e1c.zip
gcc-3831381763ca5f41d6f7406d590e1e38a8531e1c.tar.gz
gcc-3831381763ca5f41d6f7406d590e1e38a8531e1c.tar.bz2
javaprims.h: Updated class declaration list.
* gcj/javaprims.h: Updated class declaration list. * Makefile.in: Rebuilt. * Makefile.am (core_java_source_files): Added PropertyPermissionCollection.java. * java/lang/Thread.java (group, name): Now package-private. * java/lang/ThreadGroup.java: Re-merge with Classpath. * java/util/AbstractList.java: Likewise. * java/util/AbstractMap.java: Likewise. * java/util/Calendar.java: Likewise. * java/util/Collections.java: Likewise. * java/util/HashMap.java: Likewise. * java/util/Hashtable.java: Likewise. * java/util/LinkedHashMap.java: Likewise. * java/util/LinkedList.java: Likewise. * java/util/List.java: Likewise. * java/util/ListResourceBundle.java: Likewise. * java/util/Map.java: Likewise. * java/util/Observable.java: Likewise. * java/util/Properties.java: Likewise. * java/util/PropertyPermission.java: Likewise. * java/util/PropertyPermissionCollection.java: Likewise. * java/util/PropertyResourceBundle.java: Likewise. * java/util/Random.java: Likewise. * java/util/SimpleTimeZone.java: Likewise. * java/util/StringTokenizer.java: Likewise. * java/util/TimerTask.java: Likewise. * java/util/TreeMap.java: Likewise. * java/util/WeakHashMap.java: Likewise. * java/util/jar/Attributes.java: Likewise. * java/util/jar/JarException.java: Likewise. * java/util/jar/Manifest.java: Likewise. From-SVN: r54743
Diffstat (limited to 'libjava/java/util')
-rw-r--r--libjava/java/util/AbstractList.java46
-rw-r--r--libjava/java/util/AbstractMap.java128
-rw-r--r--libjava/java/util/Calendar.java13
-rw-r--r--libjava/java/util/Collections.java288
-rw-r--r--libjava/java/util/HashMap.java24
-rw-r--r--libjava/java/util/Hashtable.java31
-rw-r--r--libjava/java/util/LinkedHashMap.java39
-rw-r--r--libjava/java/util/LinkedList.java10
-rw-r--r--libjava/java/util/List.java28
-rw-r--r--libjava/java/util/ListResourceBundle.java117
-rw-r--r--libjava/java/util/Map.java30
-rw-r--r--libjava/java/util/Observable.java98
-rw-r--r--libjava/java/util/Properties.java696
-rw-r--r--libjava/java/util/PropertyPermission.java247
-rw-r--r--libjava/java/util/PropertyPermissionCollection.java164
-rw-r--r--libjava/java/util/PropertyResourceBundle.java123
-rw-r--r--libjava/java/util/Random.java359
-rw-r--r--libjava/java/util/SimpleTimeZone.java9
-rw-r--r--libjava/java/util/StringTokenizer.java191
-rw-r--r--libjava/java/util/TimerTask.java6
-rw-r--r--libjava/java/util/TreeMap.java10
-rw-r--r--libjava/java/util/WeakHashMap.java70
-rw-r--r--libjava/java/util/jar/Attributes.java2
-rw-r--r--libjava/java/util/jar/JarException.java19
-rw-r--r--libjava/java/util/jar/Manifest.java13
25 files changed, 1693 insertions, 1068 deletions
diff --git a/libjava/java/util/AbstractList.java b/libjava/java/util/AbstractList.java
index 1c2d1de..be0bc30 100644
--- a/libjava/java/util/AbstractList.java
+++ b/libjava/java/util/AbstractList.java
@@ -1,5 +1,5 @@
/* AbstractList.java -- Abstract implementation of most of List
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -237,20 +237,22 @@ public abstract class AbstractList extends AbstractCollection implements List
}
/**
- * Obtain 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:
- * <pre>
- * hashCode = 1;
- * Iterator i = list.iterator();
- * while (i.hasNext())
- * {
- * Object obj = i.next();
- * hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
- * }
- * </pre>
+ * 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:
+ *
+<pre>hashCode = 1;
+Iterator i = list.iterator();
+while (i.hasNext())
+{
+ Object obj = i.next();
+ hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
+}</pre>
+ *
* 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)
*/
@@ -611,19 +613,21 @@ public abstract class AbstractList extends AbstractCollection implements List
/**
* This class follows the implementation requirements set forth in
- * {@link AbstractList#subList(int, int)}. Some compilers have problems
- * with AbstractList.this.modCount if this class is nested in AbstractList,
- * even though the JLS defines that to be legal, so we make it a top-level
- * class.
+ * {@link AbstractList#subList(int, int)}. It matches Sun's implementation
+ * by using a non-public top-level class in the same package.
*
* @author Original author unknown
* @author Eric Blake <ebb9@email.byu.edu>
*/
class SubList extends AbstractList
{
- private final AbstractList backingList;
- private final int offset;
- private int size;
+ // Package visible, for use by iterator.
+ /** The original list. */
+ final AbstractList backingList;
+ /** The index of the first element of the sublist. */
+ final int offset;
+ /** The size of the sublist. */
+ int size;
/**
* Construct the sublist.
@@ -647,8 +651,8 @@ class SubList extends AbstractList
* @throws ConcurrentModificationException if the backing list has been
* modified externally to this sublist
*/
- // This will get inlined, since it is private.
- private void checkMod()
+ // This can be inlined. Package visible, for use by iterator.
+ void checkMod()
{
if (modCount != backingList.modCount)
throw new ConcurrentModificationException();
diff --git a/libjava/java/util/AbstractMap.java b/libjava/java/util/AbstractMap.java
index 555d055..11c8f5b 100644
--- a/libjava/java/util/AbstractMap.java
+++ b/libjava/java/util/AbstractMap.java
@@ -1,5 +1,5 @@
/* AbstractMap.java -- Abstract implementation of most of Map
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -518,4 +518,130 @@ public abstract class AbstractMap implements Map
{
return o == null ? 0 : o.hashCode();
}
+
+ /**
+ * A class which implements Map.Entry. It is shared by HashMap, TreeMap,
+ * Hashtable, and Collections. It is not specified by the JDK, but makes
+ * life much easier.
+ *
+ * @author Jon Zeppieri
+ * @author Eric Blake <ebb9@email.byu.edu>
+ */
+ static class BasicMapEntry implements Map.Entry
+ { // XXX - FIXME Use fully qualified implements as gcj 3.1 workaround.
+ /**
+ * The key. Package visible for direct manipulation.
+ */
+ Object key;
+
+ /**
+ * The value. Package visible for direct manipulation.
+ */
+ Object value;
+
+ /**
+ * Basic constructor initializes the fields.
+ * @param newKey the key
+ * @param newValue the value
+ */
+ BasicMapEntry(Object newKey, Object newValue)
+ {
+ key = newKey;
+ value = newValue;
+ }
+
+ /**
+ * 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:
+ *
+<pre>(o instanceof Map.Entry) &&
+(getKey() == null ? ((HashMap) o).getKey() == null
+ : getKey().equals(((HashMap) o).getKey())) &&
+(getValue() == null ? ((HashMap) o).getValue() == null
+ : getValue().equals(((HashMap) o).getValue()))</pre>
+ *
+ * @param o the object to compare
+ *
+ * @return <code>true</code> if it is equal
+ */
+ public final boolean equals(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ // Optimize for our own entries.
+ if (o instanceof BasicMapEntry)
+ {
+ BasicMapEntry e = (BasicMapEntry) o;
+ return (AbstractMap.equals(key, e.key)
+ && AbstractMap.equals(value, e.value));
+ }
+ Map.Entry e = (Map.Entry) o;
+ return (AbstractMap.equals(key, e.getKey())
+ && AbstractMap.equals(value, e.getValue()));
+ }
+
+ /**
+ * Get the key corresponding to this entry.
+ *
+ * @return the key
+ */
+ public final Object getKey()
+ {
+ return key;
+ }
+
+ /**
+ * Get the value corresponding to this entry. If you already called
+ * Iterator.remove(), the behavior undefined, but in this case it works.
+ *
+ * @return the value
+ */
+ public final Object getValue()
+ {
+ return 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 null). In other
+ * words, this must be:
+ *
+<pre>(getKey() == null ? 0 : getKey().hashCode())
+^ (getValue() == null ? 0 : getValue().hashCode())</pre>
+ *
+ * @return the hash code
+ */
+ public final int hashCode()
+ {
+ return (AbstractMap.hashCode(key) ^ AbstractMap.hashCode(value));
+ }
+
+ /**
+ * Replaces the value with the specified object. This writes through
+ * to the map, unless you have already called Iterator.remove(). It
+ * may be overridden to restrict a null value.
+ *
+ * @param newVal the new value to store
+ * @return the old value
+ * @throws NullPointerException if the map forbids null values
+ */
+ public Object setValue(Object newVal)
+ {
+ Object r = value;
+ value = newVal;
+ 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
+ */
+ public final String toString()
+ {
+ return key + "=" + value;
+ }
+ } // class BasicMapEntry
}
diff --git a/libjava/java/util/Calendar.java b/libjava/java/util/Calendar.java
index 8271779..999f105 100644
--- a/libjava/java/util/Calendar.java
+++ b/libjava/java/util/Calendar.java
@@ -73,13 +73,12 @@ import java.io.*;
* and for the first line all fields are set, that line is used to
* compute the day. <br>
*
- * <pre>
- * month + day_of_month
- * month + week_of_month + day_of_week
- * month + day_of_week_of_month + day_of_week
- * day_of_year
- * day_of_week + week_of_year
- * </pre>
+ *
+<pre>month + day_of_month
+month + week_of_month + day_of_week
+month + day_of_week_of_month + day_of_week
+day_of_year
+day_of_week + week_of_year</pre>
*
* The hour_of_day-field takes precedence over the ampm and
* hour_of_ampm fields. <br>
diff --git a/libjava/java/util/Collections.java b/libjava/java/util/Collections.java
index 9c10a4b..815afcc 100644
--- a/libjava/java/util/Collections.java
+++ b/libjava/java/util/Collections.java
@@ -1,5 +1,5 @@
/* Collections.java -- Utility class with methods to operate on collections
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -60,7 +60,6 @@ import java.io.Serializable;
* modify the set.
*
* @author Original author unknown
- * @author Bryce McKinlay
* @author Eric Blake <ebb9@email.byu.edu>
* @see Collection
* @see Set
@@ -108,24 +107,6 @@ public class Collections
*/
public static final Set EMPTY_SET = new EmptySet();
- private static final Iterator EMPTY_ITERATOR = new Iterator()
- {
- public boolean hasNext()
- {
- return false;
- }
-
- public Object next()
- {
- throw new NoSuchElementException();
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- };
-
/**
* The implementation of {@link #EMPTY_SET}. This class name is required
* for compatibility with Sun's JDK serializability.
@@ -158,9 +139,94 @@ public class Collections
/**
* Returns an iterator that does not iterate.
*/
+ // This is really cheating! I think it's perfectly valid, though.
public Iterator iterator()
{
- return EMPTY_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.
+ */
+ public boolean contains(Object o)
+ {
+ return false;
+ }
+
+ /**
+ * This is true only if the given collection is also empty.
+ */
+ public boolean containsAll(Collection c)
+ {
+ return c.isEmpty();
+ }
+
+ /**
+ * Equal only if the other set is empty.
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof Set && ((Set) o).isEmpty();
+ }
+
+ /**
+ * The hashcode is always 0.
+ */
+ public int hashCode()
+ {
+ return 0;
+ }
+
+ /**
+ * Always succeeds with false result.
+ */
+ public boolean remove(Object o)
+ {
+ return false;
+ }
+
+ /**
+ * Always succeeds with false result.
+ */
+ public boolean removeAll(Collection c)
+ {
+ return false;
+ }
+
+ /**
+ * Always succeeds with false result.
+ */
+ public boolean retainAll(Collection c)
+ {
+ return false;
+ }
+
+ /**
+ * The array is always empty.
+ */
+ public Object[] toArray()
+ {
+ return new Object[0];
+ }
+
+ /**
+ * We don't even need to use reflection!
+ */
+ public Object[] toArray(Object[] a)
+ {
+ if (a.length > 0)
+ a[0] = null;
+ return a;
+ }
+
+ /**
+ * The string never changes.
+ */
+ public String toString()
+ {
+ return "[]";
}
} // class EmptySet
@@ -207,15 +273,106 @@ public class Collections
{
throw new IndexOutOfBoundsException();
}
-
+
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractList.
/**
- * Returns an iterator that does not iterate. Optional, but avoids
- * allocation of an iterator in AbstractList.
+ * Never contains anything.
*/
- public Iterator iterator()
+ public boolean contains(Object o)
{
- return EMPTY_ITERATOR;
- }
+ return false;
+ }
+
+ /**
+ * This is true only if the given collection is also empty.
+ */
+ public boolean containsAll(Collection c)
+ {
+ return c.isEmpty();
+ }
+
+ /**
+ * Equal only if the other set is empty.
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof List && ((List) o).isEmpty();
+ }
+
+ /**
+ * The hashcode is always 1.
+ */
+ public int hashCode()
+ {
+ return 1;
+ }
+
+ /**
+ * Returns -1.
+ */
+ public int indexOf(Object o)
+ {
+ return -1;
+ }
+
+ /**
+ * Returns -1.
+ */
+ public int lastIndexOf(Object o)
+ {
+ return -1;
+ }
+
+ /**
+ * Always succeeds with false result.
+ */
+ public boolean remove(Object o)
+ {
+ return false;
+ }
+
+ /**
+ * Always succeeds with false result.
+ */
+ public boolean removeAll(Collection c)
+ {
+ return false;
+ }
+
+ /**
+ * Always succeeds with false result.
+ */
+ public boolean retainAll(Collection c)
+ {
+ return false;
+ }
+
+ /**
+ * The array is always empty.
+ */
+ public Object[] toArray()
+ {
+ return new Object[0];
+ }
+
+ /**
+ * We don't even need to use reflection!
+ */
+ public Object[] toArray(Object[] a)
+ {
+ if (a.length > 0)
+ a[0] = null;
+ return a;
+ }
+
+ /**
+ * The string never changes.
+ */
+ public String toString()
+ {
+ return "[]";
+ }
} // class EmptyList
/**
@@ -253,6 +410,64 @@ public class Collections
return EMPTY_SET;
}
+ // The remaining methods are optional, but provide a performance
+ // advantage by not allocating unnecessary iterators in AbstractMap.
+ /**
+ * No entries!
+ */
+ public boolean containsKey(Object key)
+ {
+ return false;
+ }
+
+ /**
+ * No entries!
+ */
+ public boolean containsValue(Object value)
+ {
+ return false;
+ }
+
+ /**
+ * Equal to all empty maps.
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof Map && ((Map) o).isEmpty();
+ }
+
+ /**
+ * No mappings, so this returns null.
+ */
+ public Object get(Object o)
+ {
+ return null;
+ }
+
+ /**
+ * The hashcode is always 0.
+ */
+ public int hashCode()
+ {
+ return 0;
+ }
+
+ /**
+ * No entries.
+ */
+ public Set keySet()
+ {
+ return EMPTY_SET;
+ }
+
+ /**
+ * Remove always succeeds, with null result.
+ */
+ public Object remove(Object o)
+ {
+ return null;
+ }
+
/**
* Size is always 0.
*/
@@ -269,8 +484,17 @@ public class Collections
{
return EMPTY_SET;
}
+
+ /**
+ * The string never changes.
+ */
+ 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
@@ -502,7 +726,7 @@ public class Collections
}
/**
- * Returns an array list holding the elements visited by a given
+ * Returns an ArrayList holding the elements visited by a given
* Enumeration. This method exists for interoperability between legacy
* APIs and the new Collection API.
*
@@ -511,9 +735,9 @@ public class Collections
* @see ArrayList
* @since 1.4
*/
- public static List list(Enumeration e)
+ public static ArrayList list(Enumeration e)
{
- List l = new ArrayList();
+ ArrayList l = new ArrayList();
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
@@ -1353,7 +1577,7 @@ public class Collections
public Set entrySet()
{
if (entries == null)
- entries = singleton(new BasicMapEntry(k, v)
+ entries = singleton(new AbstractMap.BasicMapEntry(k, v)
{
public Object setValue(Object o)
{
@@ -1500,6 +1724,7 @@ public class Collections
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
@@ -2682,6 +2907,7 @@ public class Collections
}
} // class SynchronizedSortedSet
+
/**
* Returns an unmodifiable view of the given collection. This allows
* "read-only" access, although changes in the backing collection show up
diff --git a/libjava/java/util/HashMap.java b/libjava/java/util/HashMap.java
index 9451744..a78eb9a 100644
--- a/libjava/java/util/HashMap.java
+++ b/libjava/java/util/HashMap.java
@@ -1,6 +1,6 @@
/* HashMap.java -- a class providing a basic hashtable data structure,
mapping Object --> Object
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -162,7 +162,7 @@ public class HashMap extends AbstractMap
*
* @author Eric Blake <ebb9@email.byu.edu>
*/
- static class HashEntry extends BasicMapEntry
+ static class HashEntry extends AbstractMap.BasicMapEntry
{
/**
* The next entry in the linked list. Package visible for use by subclass.
@@ -373,9 +373,9 @@ public class HashMap extends AbstractMap
{
Map.Entry e = (Map.Entry) itr.next();
// Optimize in case the Entry is one of our own.
- if (e instanceof BasicMapEntry)
+ if (e instanceof AbstractMap.BasicMapEntry)
{
- BasicMapEntry entry = (BasicMapEntry) e;
+ AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
put(entry.key, entry.value);
}
else
@@ -647,7 +647,8 @@ public class HashMap extends AbstractMap
* @return the matching entry, if found, or null
* @see #entrySet()
*/
- private HashEntry getEntry(Object o)
+ // Package visible, for use in nested classes.
+ HashEntry getEntry(Object o)
{
if (!(o instanceof Map.Entry))
return null;
@@ -710,14 +711,13 @@ public class HashMap extends AbstractMap
}
/**
- * 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>
+ * 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() &gt; threshold. Note that the existing Entry
+ * objects are reused in the new hash table.
*
- * This is not specified, but the new size is twice the current size plus
- * one; this number is not always prime, unfortunately.
+ * <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()
{
diff --git a/libjava/java/util/Hashtable.java b/libjava/java/util/Hashtable.java
index 71ec4b80..a94143b 100644
--- a/libjava/java/util/Hashtable.java
+++ b/libjava/java/util/Hashtable.java
@@ -1,6 +1,6 @@
/* Hashtable.java -- a class providing a basic hashtable data structure,
mapping Object --> Object
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -102,6 +102,9 @@ import java.io.ObjectOutputStream;
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.
*/
@@ -176,7 +179,7 @@ public class Hashtable extends Dictionary
* 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 BasicMapEntry
+ private static final class HashEntry extends AbstractMap.BasicMapEntry
{
/** The next entry in the linked list. */
HashEntry next;
@@ -340,9 +343,9 @@ public class Hashtable extends Dictionary
*
* @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 #contains(Object)
* @see #containsKey(Object)
+ * @throws NullPointerException if <code>value</code> is null
* @since 1.2
*/
public boolean containsValue(Object value)
@@ -361,7 +364,7 @@ public class Hashtable extends Dictionary
// Must throw on null argument even if the table is empty
if (value == null)
throw new NullPointerException();
-
+
return false;
}
@@ -511,9 +514,9 @@ public class Hashtable extends Dictionary
{
Map.Entry e = (Map.Entry) itr.next();
// Optimize in case the Entry is one of our own.
- if (e instanceof BasicMapEntry)
+ if (e instanceof AbstractMap.BasicMapEntry)
{
- BasicMapEntry entry = (BasicMapEntry) e;
+ AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
put(entry.key, entry.value);
}
else
@@ -763,9 +766,9 @@ public class Hashtable extends Dictionary
/**
* Returns true if this Hashtable equals the supplied Object <code>o</code>.
* As specified by Map, this is:
- * <pre>
+ * <code>
* (o instanceof Map) && entrySet().equals(((Map) o).entrySet());
- * </pre>
+ * </code>
*
* @param o the object to compare to
* @return true if o is an equal map
@@ -812,7 +815,10 @@ public class Hashtable extends Dictionary
*/
private int hash(Object key)
{
- return Math.abs(key.hashCode() % buckets.length);
+ // 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;
}
/**
@@ -823,7 +829,8 @@ public class Hashtable extends Dictionary
* @return the matching entry, if found, or null
* @see #entrySet()
*/
- private HashEntry getEntry(Object o)
+ // Package visible, for use in nested classes.
+ HashEntry getEntry(Object o)
{
if (! (o instanceof Map.Entry))
return null;
@@ -869,7 +876,7 @@ public class Hashtable extends Dictionary
/**
* 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
+ * size() &gt; threshold. Note that the existing Entry objects are reused in
* the new hash table.
* <p>
*
@@ -1139,4 +1146,4 @@ public class Hashtable extends Dictionary
return type == VALUES ? e.value : e.key;
}
} // class Enumerator
-}
+} // class Hashtable
diff --git a/libjava/java/util/LinkedHashMap.java b/libjava/java/util/LinkedHashMap.java
index 0709bdf..2716ac1 100644
--- a/libjava/java/util/LinkedHashMap.java
+++ b/libjava/java/util/LinkedHashMap.java
@@ -71,7 +71,7 @@ package java.util;
* <p>
*
* Under ideal circumstances (no collisions), LinkedHashMap offers O(1)
- * performance on most operations (<pre>containsValue()</pre> is,
+ * 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>
@@ -87,7 +87,7 @@ package java.util;
* {@link ConcurrentModificationException} rather than exhibit
* non-deterministic behavior.
*
- * @author Eric Blake <ebb9@email.byu.edu>
+ * @author Eric Blake (ebb9@email.byu.edu)
* @see Object#hashCode()
* @see Collection
* @see Map
@@ -256,8 +256,9 @@ public class LinkedHashMap extends HashMap
* @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)
+ *
+ * @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
+ * ! (loadFactor &gt; 0.0)
*/
public LinkedHashMap(int initialCapacity, float loadFactor,
boolean accessOrder)
@@ -277,11 +278,12 @@ public class LinkedHashMap extends HashMap
}
/**
- * Returns true if this HashMap contains a value <pre>o</pre>, such that
- * <pre>o.equals(value)</pre>.
+ * 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 true if at least one key maps to the value
+ *
+ * @return <code>true</code> if at least one key maps to the value
*/
public boolean containsValue(Object value)
{
@@ -297,7 +299,7 @@ public class LinkedHashMap extends HashMap
/**
* Return the value in this Map associated with the supplied key,
- * or <pre>null</pre> if the key maps to nothing. If this is an
+ * 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
@@ -350,14 +352,14 @@ public class LinkedHashMap extends HashMap
* <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>
+ *
+<pre>private static final int MAX_ENTRIES = 100;
+
+protected boolean removeEldestEntry(Map.Entry eldest)
+{
+ return size() &gt; 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.
@@ -376,6 +378,7 @@ public class LinkedHashMap extends HashMap
* 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)
@@ -467,8 +470,10 @@ public class LinkedHashMap extends HashMap
/**
* Removes from the backing HashMap the last element which was fetched
- * with the <pre>next()</pre> method.
+ * 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()
diff --git a/libjava/java/util/LinkedList.java b/libjava/java/util/LinkedList.java
index d87e95a..c891f82 100644
--- a/libjava/java/util/LinkedList.java
+++ b/libjava/java/util/LinkedList.java
@@ -1,5 +1,5 @@
/* LinkedList.java -- Linked list implementation of the List interface
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -125,12 +125,13 @@ public class LinkedList extends AbstractSequentialList
* 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).
+ * Incorrect values will be returned if (n &lt; 0) or (n &gt;= size).
*
* @param n the number of the entry to get
* @return the entry at position n
*/
- private Entry getEntry(int n)
+ // Package visible for use in nested classes.
+ Entry getEntry(int n)
{
Entry e;
if (n < size / 2)
@@ -156,7 +157,8 @@ public class LinkedList extends AbstractSequentialList
*
* @param e the entry to remove
*/
- private void removeEntry(Entry e)
+ // Package visible for use in nested classes.
+ void removeEntry(Entry e)
{
modCount++;
size--;
diff --git a/libjava/java/util/List.java b/libjava/java/util/List.java
index 0d8df5d1..22a6b83 100644
--- a/libjava/java/util/List.java
+++ b/libjava/java/util/List.java
@@ -201,7 +201,7 @@ public interface List extends Collection
* @see Object#equals(Object)
* @see #hashCode()
*/
- /* boolean equals(Object o);*/
+ boolean equals(Object o);
/**
* Get the element at a given index in this list.
@@ -213,18 +213,20 @@ public interface List extends Collection
Object get(int index);
/**
- * Obtain 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:
- * <pre>
- * hashCode = 1;
- * Iterator i = list.iterator();
- * while (i.hasNext())
- * {
- * Object obj = i.next();
- * hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
- * }
- * </pre>
- * This ensures that the general contract of Object.hashCode() is adhered to.
+ * 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()
diff --git a/libjava/java/util/ListResourceBundle.java b/libjava/java/util/ListResourceBundle.java
index 45508c7..b7b32c2 100644
--- a/libjava/java/util/ListResourceBundle.java
+++ b/libjava/java/util/ListResourceBundle.java
@@ -1,5 +1,5 @@
-/* java.util.ListResourceBundle
- Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+/* ListResourceBundle -- a resource bundle build around a list
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,73 +39,102 @@ 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.
- * <br>
- * 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.
- * <br>
- * XXX Example!
+ * 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@email.byu.edu>
* @see Locale
* @see PropertyResourceBundle
- * @author Jochen Hoenicke */
+ * @since 1.1
+ * @status updated to 1.4
+ */
public abstract class ListResourceBundle extends ResourceBundle
{
/**
- * The constructor. It does nothing special.
+ * The constructor. It does nothing special.
*/
public ListResourceBundle()
{
}
/**
- * Gets the key/value list. You must override this method.
- * @return a two dimensional list of Objects. The first dimension
- * ranges over the objects, and the second dimension ranges from
- * zero (key) to one (value).
- */
- protected abstract Object[][] getContents();
-
- /**
- * Override this method to provide the resource for a keys. This gets
- * called by <code>getObject</code>.
- * @param key The key of the resource.
- * @return The resource for the key or null if it doesn't exists.
+ * 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();
- for (int i = 0; i < contents.length; i++)
- {
- if (key.equals(contents[i][0]))
- return contents[i][1];
- }
+ 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.
+ *
+ * @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();
-
- return new Enumeration()
- {
- int i = 0;
- public boolean hasMoreElements()
- {
- return i < contents.length;
- }
- public Object nextElement()
+ 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)
{
- return contents[i++][0];
+ 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
diff --git a/libjava/java/util/Map.java b/libjava/java/util/Map.java
index 5918a41..01f9b23 100644
--- a/libjava/java/util/Map.java
+++ b/libjava/java/util/Map.java
@@ -296,14 +296,14 @@ public interface Map
*/
public 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 null). In other
- * words, this must be:
- * <pre>
- * (getKey() == null ? 0 : getKey().hashCode()) ^
- * (getValue() == null ? 0 : getValue().hashCode())
- * </pre>
+ * 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
*/
@@ -313,16 +313,16 @@ public interface Map
* 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:
- * <pre>
- * (o instanceof Map.Entry)
- * && (getKey() == null ? ((HashMap) o).getKey() == null
- * : getKey().equals(((HashMap) o).getKey()))
- * && (getValue() == null ? ((HashMap) o).getValue() == null
- * : getValue().equals(((HashMap) o).getValue()))
- * </pre>
+ *
+<p><pre>(o instanceof Map.Entry)
+&& (getKey() == null ? ((HashMap) o).getKey() == null
+ : getKey().equals(((HashMap) o).getKey()))
+&& (getValue() == null ? ((HashMap) o).getValue() == null
+ : getValue().equals(((HashMap) o).getValue()))</pre>
*
* @param o the object to compare
- * @return true if it is equal
+ *
+ * @return <code>true</code> if it is equal
*/
public boolean equals(Object o);
}
diff --git a/libjava/java/util/Observable.java b/libjava/java/util/Observable.java
index 4760713..7616f51 100644
--- a/libjava/java/util/Observable.java
+++ b/libjava/java/util/Observable.java
@@ -1,5 +1,5 @@
-/* java.util.Observable
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Observable.java -- an object to be observed
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,55 +38,53 @@ 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.
- */
-
/**
+ * 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@cygnus.com>
- * @date September 2, 1998.
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @see Observer
+ * @status updated to 1.4
*/
public class Observable
{
- /** tracks whether this object has changed */
+ /** Tracks whether this object has changed. */
private boolean changed;
- /* list of the Observers registered as interested in this Observable */
- private Vector observers;
-
- /* TBD: This might be better implemented as an Observer[]
- * but that would mean writing more code rather than making use of
- * the existing Vector class (this also implies a larger text code
- * space in resulting executables). The tradeoff is one of speed
- * (manipulating the Observer[] directly) vs. size/reuse. In the future,
- * we may decide to make the tradeoff and reimplement with an Observer[].
- */
+ /* List of the Observers registered as interested in this Observable. */
+ private LinkedHashSet observers;
/**
* Constructs an Observable with zero Observers.
*/
public Observable()
{
- changed = false;
- observers = new Vector();
+ observers = new LinkedHashSet();
}
/**
* Adds an Observer. If the observer was already added this method does
* nothing.
*
- * @param observer Observer to add.
+ * @param observer Observer to add
+ * @throws NullPointerException if observer is null
*/
public synchronized void addObserver(Observer observer)
{
- if (!observers.contains(observer))
- observers.addElement(observer);
+ observers.add(observer);
}
/**
- * Reset this Observable's state to unchanged.
+ * 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()
{
@@ -94,7 +92,9 @@ public class Observable
}
/**
- * @return Number of Observers for this Observable.
+ * Returns the number of observers for this object.
+ *
+ * @return number of Observers for this
*/
public synchronized int countObservers()
{
@@ -104,11 +104,11 @@ public class Observable
/**
* Deletes an Observer of this Observable.
*
- * @param victim Observer to delete.
+ * @param victim Observer to delete
*/
public synchronized void deleteObserver(Observer victim)
{
- observers.removeElement(victim);
+ observers.remove(victim);
}
/**
@@ -116,11 +116,14 @@ public class Observable
*/
public synchronized void deleteObservers()
{
- observers.removeAllElements();
+ observers.clear();
}
/**
- * @return Whether or not this Observable has changed.
+ * 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()
{
@@ -129,7 +132,10 @@ public class Observable
/**
* If the Observable has actually changed then tell all Observers about it,
- * then resets state to unchanged.
+ * then reset state to unchanged.
+ *
+ * @see #notifyObservers(Object)
+ * @see Observer#update(Observable, Object)
*/
public void notifyObservers()
{
@@ -138,21 +144,29 @@ public class Observable
/**
* If the Observable has actually changed then tell all Observers about it,
- * then resets state to unchanged.
- * Note that though the order of notification is unspecified in subclasses,
- * in Observable it is in the order of registration.
+ * 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 Arguement to Observer's update method.
+ * @param obj argument to Observer's update method
+ * @see Observer#update(Observable, Object)
*/
public void notifyObservers(Object obj)
{
- if (!hasChanged())
+ if (! hasChanged())
return;
- Vector ob1 = (Vector) observers.clone();
-
- for (int i = 0; i < ob1.size(); i++)
- ((Observer) ob1.elementAt(i)).update(this, obj);
-
+ // 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();
}
diff --git a/libjava/java/util/Properties.java b/libjava/java/util/Properties.java
index fa3a754..adad250 100644
--- a/libjava/java/util/Properties.java
+++ b/libjava/java/util/Properties.java
@@ -1,5 +1,5 @@
-/* java.util.Properties
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Properties.java -- a set of persistent properties
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,64 +37,88 @@ exception statement from your version. */
package java.util;
-import java.io.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.PrintStream;
+import java.io.OutputStreamWriter;
/**
+ * 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 &auml;)
+ *
*
- * <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>
+<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>
*
- * Although this is a sub class of a hash table, you should never
+ * <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>.
*
- * @see PropertyResourceBundle
+ * 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@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.
+ * 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.
+ * Creates a new empty property list with no default values.
*/
public Properties()
{
- this.defaults = null;
}
/**
* Create a new empty property list with the specified default values.
- * @param defaults a Properties object containing the default values.
+ *
+ * @param defaults a Properties object containing the default values
*/
public Properties(Properties defaults)
{
@@ -102,6 +126,21 @@ public class Properties extends Hashtable
}
/**
+ * 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>
*
@@ -120,173 +159,176 @@ public class Properties extends Hashtable
*
* Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a
* space), and unicode characters with the
- * <code>\</code><code>u</code>xxxx notation are detected, and
+ * <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:\<code></code>u0020
- * </pre>
+ *
+<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 in the input stream
- * @exception IOException if an error occurred when reading
- * from the input. */
+ * @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;
- while (pos < line.length()
- && Character.isWhitespace(c = line.charAt(pos)))
- pos++;
+ char c = 0;
+ int pos = 0;
+ while (pos < line.length()
+ && Character.isWhitespace(c = line.charAt(pos)))
+ pos++;
- // If line is empty or begins with a comment character,
- // skip this line.
- if (pos == line.length() || c == '#' || c == '!')
- continue;
+ // If line is empty or begins with a comment character,
+ // skip this line.
+ if (pos == line.length() || c == '#' || c == '!')
+ continue;
- // The characters up to the next Whitespace, ':', or '='
- // describe the key. But look for escape sequences.
- StringBuffer key = new StringBuffer();
- while (pos < line.length()
- && !Character.isWhitespace(c = line.charAt(pos++))
- && c != '=' && c != ':')
- {
- if (c == '\\')
- {
- if (pos == line.length())
- {
- // The line continues on the next line.
- line = reader.readLine();
- 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
- key.append(c);
- }
+ // The characters up to the next Whitespace, ':', or '='
+ // describe the key. But look for escape sequences.
+ StringBuffer key = new StringBuffer();
+ while (pos < line.length()
+ && ! Character.isWhitespace(c = line.charAt(pos++))
+ && c != '=' && c != ':')
+ {
+ if (c == '\\')
+ {
+ if (pos == line.length())
+ {
+ // The line continues on the next line.
+ line = reader.readLine();
+ 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
+ key.append(c);
+ }
- boolean isDelim = (c == ':' || c == '=');
- while (pos < line.length()
- && Character.isWhitespace(c = line.charAt(pos)))
- pos++;
+ boolean isDelim = (c == ':' || c == '=');
+ 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++;
- }
+ if (! isDelim && (c == ':' || c == '='))
+ {
+ pos++;
+ while (pos < line.length()
+ && Character.isWhitespace(c = line.charAt(pos)))
+ pos++;
+ }
- StringBuffer element = new StringBuffer(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();
- 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(key.toString(), element.toString());
+ StringBuffer element = new StringBuffer(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();
+ 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(key.toString(), element.toString());
}
}
/**
* Calls <code>store(OutputStream out, String header)</code> and
* ignores the IOException that may be thrown.
- * @deprecated use store instead.
- * @exception ClassCastException if this property contains any key or
- * value that isn't a string.
+ *
+ * @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);
+ store(out, header);
}
catch (IOException ex)
{
@@ -294,13 +336,14 @@ public class Properties extends Hashtable
}
/**
- * Writes the key/value pairs to the given output stream. <br>
+ * 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>
+ * 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.
@@ -308,47 +351,42 @@ public class Properties extends Hashtable
* 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.
+ * <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.
- * @exception ClassCastException if this property contains any key or
- * value that isn't a string.
+ * @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"));
+ = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
if (header != null)
writer.println("#" + header);
- writer.println("#" + new Date().toString());
+ writer.println("#" + new Date());
list(writer);
writer.flush();
}
/**
- * 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.
- * @since JDK1.2 */
- public Object setProperty(String key, String value)
- {
- return put(key, value);
- }
-
- /**
* 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 default or the default of
- * default, null is returned.
- * @param key The key for this property.
- * @param defaulValue A default value
- * @return The value for the given key, or null if not found.
- * @exception ClassCastException if this property contains any key or
- * value that isn't a string.
+ * 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)
{
@@ -358,13 +396,16 @@ public class Properties extends Hashtable
/**
* 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 default or the default of default, the
- * specified defaultValue is returned.
- * @param key The key for this property.
- * @param defaulValue A default value
- * @return The value for the given key.
- * @exception ClassCastException if this property contains any key or
- * value that isn't a string.
+ * 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)
{
@@ -372,184 +413,145 @@ public class Properties extends Hashtable
// Eliminate tail recursion.
do
{
- String value = (String) prop.get(key);
- if (value != null)
- return value;
- prop = prop.defaults;
+ String value = (String) prop.get(key);
+ if (value != null)
+ return value;
+ prop = prop.defaults;
}
while (prop != null);
return defaultValue;
}
- private final void addHashEntries(Hashtable base)
- {
- if (defaults != null)
- defaults.addHashEntries(base);
- Enumeration keys = keys();
- while (keys.hasMoreElements())
- base.put(keys.nextElement(), base);
- }
-
/**
* 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 Hashtable that holds all the keys. Then we
- // return an enumeration for this hash. We do this because we
- // don't want modifications to be reflected in the enumeration
- // (per JCL), and because there doesn't seem to be a
- // particularly better way to ensure that duplicates are
- // ignored.
- Hashtable t = new Hashtable();
- addHashEntries(t);
- return t.keys();
+ // 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);
}
/**
- * Formats a key/value pair for output in a properties file.
- * See store for a description of the format.
- * @param key the key.
- * @param value the value.
- * @see #store
+ * Writes the key/value pairs to the given print stream. They are
+ * written in the way described in the method store. This does not visit
+ * the keys in the default properties.
+ *
+ * @param out the stream, where the key/value pairs are written to
+ * @throws ClassCastException if this property contains any key or
+ * value that isn't a string
+ * @see #store(OutputStream, String)
*/
- private String formatForOutput(String key, String value)
+ public void list(PrintStream out)
{
- // This is a simple approximation of the expected line size.
- StringBuffer result =
- new StringBuffer(key.length() + value.length() + 16);
- boolean head = true;
- for (int i = 0; i < key.length(); i++)
+ Iterator iter = entrySet().iterator();
+ int i = size();
+ StringBuffer s = new StringBuffer(); // Reuse the same buffer.
+ while (--i >= 0)
{
- char c = key.charAt(i);
- switch (c)
- {
- case '\n':
- result.append("\\n");
- break;
- case '\r':
- result.append("\\r");
- break;
- case '\t':
- result.append("\\t");
- break;
- case '\\':
- result.append("\\\\");
- break;
- case '!':
- result.append("\\!");
- break;
- case '#':
- result.append("\\#");
- break;
- case '=':
- result.append("\\=");
- break;
- case ':':
- result.append("\\:");
- break;
- case ' ':
- result.append("\\ ");
- break;
- default:
- if (c < 32 || c > '~')
- {
- String hex = Integer.toHexString(c);
- result.append("\\u0000".substring(0, 6 - hex.length()));
- result.append(hex);
- }
- else
- result.append(c);
- }
- if (c != 32)
- head = false;
+ Map.Entry entry = (Map.Entry) iter.next();
+ formatForOutput((String) entry.getKey(), s, true);
+ s.append('=');
+ formatForOutput((String) entry.getValue(), s, false);
+ out.println(s);
}
- result.append('=');
- head = true;
- for (int i = 0; i < value.length(); i++)
- {
- char c = value.charAt(i);
- switch (c)
- {
- case '\n':
- result.append("\\n");
- break;
- case '\r':
- result.append("\\r");
- break;
- case '\t':
- result.append("\\t");
- break;
- case '\\':
- result.append("\\\\");
- break;
- case '!':
- result.append("\\!");
- break;
- case '#':
- result.append("\\#");
- break;
- case ' ':
- result.append(head ? "\\ " : " ");
- break;
- default:
- if (c < 32 || c > '~')
- {
- String hex = Integer.toHexString(c);
- result.append("\\u0000".substring(0, 6 - hex.length()));
- result.append(hex);
- }
- else
- result.append(c);
- }
- if (c != 32)
- head = false;
- }
- return result.toString();
}
/**
- * Writes the key/value pairs to the given print stream. They are
+ * Writes the key/value pairs to the given print writer. They are
* written in the way, described in the method store.
- * @param out the stream, where the key/value pairs are written to.
- * @exception ClassCastException if this property contains any key or
- * value that isn't a string.
- * @see #store
+ *
+ * @param out the writer, where the key/value pairs are written to
+ * @throws ClassCastException if this property contains any key or
+ * value that isn't a string
+ * @see #store(OutputStream, String)
+ * @see #list(PrintStream)
+ * @since 1.1
*/
- public void list(PrintStream out)
+ public void list(PrintWriter out)
{
- Enumeration keys = keys();
- Enumeration elts = elements();
- while (keys.hasMoreElements())
+ Iterator iter = entrySet().iterator();
+ int i = size();
+ StringBuffer s = new StringBuffer(); // Reuse the same buffer.
+ while (--i >= 0)
{
- String key = (String) keys.nextElement();
- String elt = (String) elts.nextElement();
- String output = formatForOutput(key, elt);
- out.println(output);
+ Map.Entry entry = (Map.Entry) iter.next();
+ formatForOutput((String) entry.getKey(), s, true);
+ s.append('=');
+ formatForOutput((String) entry.getValue(), s, false);
+ out.println(s);
}
}
/**
- * Writes the key/value pairs to the given print writer. They are
- * written in the way, described in the method store.
- * @param out the writer, where the key/value pairs are written to.
- * @exception ClassCastException if this property contains any key or
- * value that isn't a string.
- * @see #store
- * @see #list(java.io.PrintStream)
- * @since JDK1.1
+ * 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)
*/
- public void list(PrintWriter out)
+ private void formatForOutput(String str, StringBuffer buffer, boolean key)
{
- Enumeration keys = keys();
- Enumeration elts = elements();
- while (keys.hasMoreElements())
+ 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++)
{
- String key = (String) keys.nextElement();
- String elt = (String) elts.nextElement();
- String output = formatForOutput(key, elt);
- out.println(output);
+ 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);
+ 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;
}
}
-}
+} // class Properties
diff --git a/libjava/java/util/PropertyPermission.java b/libjava/java/util/PropertyPermission.java
index ec9673f..bb03e45 100644
--- a/libjava/java/util/PropertyPermission.java
+++ b/libjava/java/util/PropertyPermission.java
@@ -1,5 +1,5 @@
-/* java.util.PropertyPermission
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* PropertyPermission.java -- permission to get and set System properties
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,6 +37,7 @@ exception statement from your version. */
package java.util;
+
import java.security.Permission;
import java.security.BasicPermission;
import java.security.PermissionCollection;
@@ -49,79 +50,127 @@ import java.io.IOException;
* 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>
+ * use an asterisk "*" as described in BasicPermission.<br>
*
- * The action string is a comma-separated list if keywords. There are
+ * The action string is a comma-separated list of keywords. There are
* two possible actions:
* <dl>
- * <dt>read</dt>
+ * <dt>read</dt>
* <dd>Allows to read the property via <code>System.getProperty</code>.</dd>
- * <dt>write</dt>
+ * <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
- * @author Jochen Hoenicke
+ * @see SecurityManager
+ * @author Jochen Hoenicke
+ * @since 1.2
+ * @status updated to 1.4
*/
public final class PropertyPermission extends BasicPermission
{
/**
- * @serialField action String
- * The action string.
+ * 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;
- private transient int actions;
+ /** 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 witha he specified property. Possible
- * actions are read and write.
- * @param name the name of the property.
- * @param actions the action string.
- * @exception IllegalArgumentException if name string contains an
- * illegal wildcard or actions string contains an illegal action
+ * 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.toLowerCase());
}
/**
* Parse the action string and convert actions from external to internal
* form. This will set the internal actions field.
- * @param actions the action string.
- * @exception IllegalArgumentException if actions string contains an
- * illegal action */
- private void setActions(String actions)
+ *
+ * @param str the action string
+ * @throws IllegalArgumentException if actions string contains an
+ * illegal action
+ */
+ private void setActions(String str)
{
- this.actions = 0;
- StringTokenizer actionTokenizer = new StringTokenizer(actions, ",");
- while (actionTokenizer.hasMoreElements())
- {
- String anAction = actionTokenizer.nextToken();
- if ("read".equals(anAction))
- this.actions |= READ;
- else if ("write".equals(anAction))
- this.actions |= WRITE;
- else
- throw new IllegalArgumentException("illegal action " + anAction);
- }
+ 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
+ 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();
}
/**
@@ -129,134 +178,70 @@ public final class PropertyPermission extends BasicPermission
* the following conditions are true:
* <ul>
* <li> p is a PropertyPermission </li>
- * <li> this.getName() implies p.getName(),
+ * <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)
{
- if (!(p instanceof PropertyPermission))
- return false;
-
- // We have to check the actions.
- PropertyPermission pp = (PropertyPermission) p;
- if ((pp.actions & ~actions) != 0)
- return false;
-
- // BasicPermission checks for name.
- if (!super.implies(p))
- return false;
-
- return true;
- }
-
- /**
- * 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.
- */
- public String getActions()
- {
- return actionStrings[actions];
+ // 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.
+ * PropertyPermission object; this is true if it has the same name and
+ * actions.
*
- * @param obj The other object
+ * @param obj the other object
+ * @return true if the two are equivalent
*/
- public boolean equals (Object obj)
+ public boolean equals(Object obj)
{
- if (! (obj instanceof PropertyPermission))
- return false;
- PropertyPermission p = (PropertyPermission) obj;
- return actions == p.actions && super.equals (p);
+ return super.equals(obj) && actions == ((PropertyPermission) obj).actions;
}
/**
- * Reads an object from the stream. This converts the external to the
- * internal representation.
+ * Returns the hash code for this permission. It is equivalent to
+ * <code>getName().hashCode()</code>.
+ *
+ * @return the hash code
*/
- private void readObject(ObjectInputStream s)
- throws IOException, ClassNotFoundException
+ public int hashCode()
{
- ObjectInputStream.GetField fields = s.readFields();
- setActions((String) fields.get("actions", null));
+ return super.hashCode();
}
/**
- * Writes an object to the stream. This converts the internal to the
- * external representation.
+ * 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"
*/
- private void writeObject(ObjectOutputStream s) throws IOException
+ public String getActions()
{
- ObjectOutputStream.PutField fields = s.putFields();
- fields.put("actions", getActions());
- s.writeFields();
+ return actionStrings[actions];
}
/**
* Returns a permission collection suitable to take
* PropertyPermission objects.
- * @return a new empty PermissionCollection.
+ *
+ * @return a new empty PermissionCollection
*/
public PermissionCollection newPermissionCollection()
{
- return new PermissionCollection()
- {
- Hashtable permissions = new Hashtable();
- int allActions = 0;
-
- public void add(Permission permission)
- {
- if (isReadOnly())
- throw new IllegalStateException("readonly");
-
- // also check that permission is of correct type.
- PropertyPermission pp = (PropertyPermission) permission;
- String name = pp.getName();
- if (name.equals("*"))
- allActions |= pp.actions;
- permissions.put(name, pp);
- }
-
- public boolean implies(Permission permission)
- {
- if (!(permission instanceof PropertyPermission))
- return false;
-
- PropertyPermission toImply = (PropertyPermission) permission;
- if ((toImply.actions & ~allActions) == 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 && (toImply.actions & ~forName.actions) == 0)
- return true;
-
- prefixLength = name.lastIndexOf('.', prefixLength);
- if (prefixLength < 0)
- return false;
- name = name.substring(0, prefixLength + 1) + '*';
- }
- }
-
- public Enumeration elements()
- {
- return permissions.elements();
- }
- };
+ return new PropertyPermissionCollection();
}
}
diff --git a/libjava/java/util/PropertyPermissionCollection.java b/libjava/java/util/PropertyPermissionCollection.java
new file mode 100644
index 0000000..8f9c71d
--- /dev/null
+++ b/libjava/java/util/PropertyPermissionCollection.java
@@ -0,0 +1,164 @@
+/* PropertyPermissionCollection.java -- a collection of PropertyPermissions
+ Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 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@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:
+ * <p>
+<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);
+ 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();
+ }
+}
diff --git a/libjava/java/util/PropertyResourceBundle.java b/libjava/java/util/PropertyResourceBundle.java
index 55fb413..a3173cf 100644
--- a/libjava/java/util/PropertyResourceBundle.java
+++ b/libjava/java/util/PropertyResourceBundle.java
@@ -1,5 +1,5 @@
-/* java.util.PropertyResourceBundle
- Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+/* 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.
@@ -38,11 +38,13 @@ exception statement from your version. */
package java.util;
+import java.io.IOException;
+import java.io.InputStream;
import gnu.java.util.DoubleEnumeration;
/**
* This class is a concrete <code>ResourceBundle</code> that gets it
- * resources from a property file. This implies that the resources are
+ * resources from a property file. This implies that the resources are
* strings. For more information about resource bundles see the class
* <code>ResourceBundle</code>.
*
@@ -52,75 +54,68 @@ import gnu.java.util.DoubleEnumeration;
* file.
*
* If there is also a class for this resource and the same locale, the
- * class does win.
- *
- * 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
+ * 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>
*
- * XXX- move this to properties.
- * The file should have the following
- * format: An empty line or a line starting with <code>#</code> is
- * ignored. An backslash (<code>\</code>) at the end of the line
- * makes the line continueing on the next line. Otherwise, each line
- * describes a key/value pair. The chars up to the first whitespace,
- * = or : are the key. The key is followed by one or more
- * whitespaces, <code>=</code> or <code>:</code>. The rest of the
- * line is the resource belonging to the key. You can give unicode
- * characters with the <code>\\uxxxx</code> notation, where
- * <code>xxxx</code> is the hex encoding of the 16 bit unicode char
- * number.
- *
* An example of a properties file for the german language is given
- * here. This extends the example given in ListResourceBundle.
+ * 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<char> is the
+ * and put it in the CLASSPATH. (The char <code>\u00e4<char> is the
* german &auml;)
- *
- * <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>
*
+ *
+<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()
- * @author Jochen Hoenicke */
+ * @since 1.1
+ * @status updated to 1.4
+ */
public class PropertyResourceBundle extends ResourceBundle
{
- Properties properties;
+ /** 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.
+ *
+ * @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(java.io.InputStream stream)
- throws java.io.IOException
+ public PropertyResourceBundle(InputStream stream) throws IOException
{
properties = new Properties();
properties.load(stream);
}
/**
- * Called by <code>getObject</code> when a resource is needed. This
+ * 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 exists.
+ *
+ * @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)
{
@@ -129,16 +124,30 @@ public class PropertyResourceBundle extends ResourceBundle
/**
* This method should return all keys for which a resource exists.
- * @return An enumeration of the keys.
+ *
+ * @return an enumeration of the keys
*/
public Enumeration getKeys()
{
- // We must also return the keys of our parent.
- if (parent != null)
+ 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
{
- return new DoubleEnumeration(properties.propertyNames(),
- parent.getKeys());
+ e = bundle.getKeys();
+ while (e.hasMoreElements())
+ s.add(e.nextElement());
+ bundle = bundle.parent;
}
- return properties.propertyNames();
+ while (bundle != null);
+ return Collections.enumeration(s);
}
-}
+} // class PropertyResourceBundle
diff --git a/libjava/java/util/Random.java b/libjava/java/util/Random.java
index 1365acd..500a02d 100644
--- a/libjava/java/util/Random.java
+++ b/libjava/java/util/Random.java
@@ -1,5 +1,5 @@
-/* java.util.Random
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* 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.
@@ -38,13 +38,16 @@ 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.
+ * 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
@@ -57,7 +60,7 @@ package java.util;
* <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
+ * 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.
*
@@ -66,51 +69,65 @@ package java.util;
*
* @see java.security.SecureRandom
* @see Math#random()
- * @author Jochen Hoenicke */
-public class Random implements java.io.Serializable
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9@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.
- * @see #nextGaussian. */
+ * and returns the second on the second call.
+ *
+ * @serial whether nextNextGaussian is available
+ * @see #nextGaussian()
+ * @see #nextNextGaussian
+ */
private boolean haveNextNextGaussian;
+
/**
- * The next nextGaussian if available. This is used by nextGaussian,
+ * 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.
- * @see #nextGaussian.
+ *
+ * @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.
- * @see #next
+ *
+ * @serial the internal state of this generator
+ * @see #next()
*/
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 follows.
- * <pre>
- * setSeed(System.currentTimeMillis());
- * </pre>
+ * to the current time, as if by
+ * <code>setSeed(System.currentTimeMillis());</code>.
+ *
* @see System#currentTimeMillis()
*/
public Random()
{
- setSeed(System.currentTimeMillis());
+ this(System.currentTimeMillis());
}
/**
* Creates a new pseudorandom number generator, starting with the
- * specified seed. This does:
- * <pre>
- * setSeed(seed);
- * </pre>
- * @param seed the initial seed.
+ * specified seed, using <code>setSeed(seed);</code>.
+ *
+ * @param seed the initial seed
*/
public Random(long seed)
{
@@ -122,12 +139,14 @@ public class Random implements java.io.Serializable
* 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>
+ *
+<pre>public synchronized void setSeed(long seed)
+{
+ this.seed = (seed ^ 0x5DEECE66DL) & ((1L &lt;&lt; 48) - 1);
+ haveNextNextGaussian = false;
+}</pre>
+ *
+ * @param seed the new seed
*/
public synchronized void setSeed(long seed)
{
@@ -140,20 +159,18 @@ public class Random implements java.io.Serializable
* 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. Must be in range
- * 1..32.
- * @return the next pseudorandom value.
- * @since JDK1.1
+ *
+<pre>protected synchronized int next(int bits)
+{
+ seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L &lt;&lt; 48) - 1);
+ return (int) (seed &gt;&gt;&gt; (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)
- /*{ require { 1 <= bits && bits <=32 ::
- "bits "+bits+" not in range [1..32]" } } */
{
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int) (seed >>> (48 - bits));
@@ -163,42 +180,45 @@ public class Random implements java.io.Serializable
* 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.
- * @since JDK1.1
+ *
+<pre>public void nextBytes(byte[] bytes)
+{
+ for (int i = 0; i &lt; bytes.length; i += 4)
+ {
+ int random = next(32);
+ for (int j = 0; i + j &lt; bytes.length && j &lt; 4; j++)
+ {
+ bytes[i+j] = (byte) (random & 0xff)
+ random &gt;&gt;= 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)
- /*{ require { bytes != null :: "bytes is null"; } } */
{
int random;
- /* Do a little bit unrolling of the above algorithm. */
+ // 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);
+ 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;
- }
+ random = next(32);
+ for (int j = max; j < bytes.length; j++)
+ {
+ bytes[j] = (byte) random;
+ random >>= 8;
+ }
}
}
@@ -207,13 +227,14 @@ public class Random implements java.io.Serializable
* 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>
+ *
+<pre>public int nextInt()
+{
+ return next(32);
+}</pre>
*
- * @return the next pseudorandom value. */
+ * @return the next pseudorandom value
+ */
public int nextInt()
{
return next(32);
@@ -225,51 +246,58 @@ public class Random implements java.io.Serializable
* 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(32);
- * val = bits % n;
- * } while(bits - val + (n-1) < 0);
- * return val;
- * }
- * </pre>
- * This algorithm would return every value with exactly the same
+ *
+<pre>
+public int nextInt(int n)
+{
+ if (n &lt;= 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)) &gt;&gt; 31);
+
+ int bits, val;
+ do
+ {
+ bits = next(32);
+ val = bits % n;
+ }
+ while(bits - val + (n-1) &lt; 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 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
+ * 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.
- * @exception IllegalArgumentException if the given upper bound is negative
- * @return the next pseudorandom value.
+ * @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)
- /*{ require { n > 0 :: "n must be positive"; } } */
{
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
- if ((n & -n) == n) // i.e., n is a power of 2
+ 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(32);
- val = bits % n;
+ bits = next(32);
+ val = bits % n;
}
while (bits - val + (n - 1) < 0);
return val;
@@ -279,12 +307,13 @@ public class Random implements java.io.Serializable
* 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.
+ *
+<pre>public long nextLong()
+{
+ return ((long) next(32) &lt;&lt; 32) + next(32);
+}</pre>
+ *
+ * @return the next pseudorandom value
*/
public long nextLong()
{
@@ -294,12 +323,14 @@ public class Random implements java.io.Serializable
/**
* 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.
+ *
+<pre>public boolean nextBoolean()
+{
+ return next(1) != 0;
+}</pre>
+ *
+ * @return the next pseudorandom boolean
+ * @since 1.2
*/
public boolean nextBoolean()
{
@@ -308,83 +339,91 @@ public class Random implements java.io.Serializable
/**
* Generates the next pseudorandom float uniformly distributed
- * between 0.0f (inclusive) and 1.0 (exclusive). The
+ * 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. */
+ *
+<pre>public float nextFloat()
+{
+ return next(24) / ((float)(1 &lt;&lt; 24));
+}</pre>
+ *
+ * @return the next pseudorandom float
+ */
public float nextFloat()
{
- return next(24) / ((float) (1 << 24));
+ return next(24) / (float) (1 << 24);
}
/**
* Generates the next pseudorandom double uniformly distributed
- * between 0.0f (inclusive) and 1.0 (exclusive). The
+ * 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)(1 << 53);
- * }
- * </pre>
- * @return the next pseudorandom double. */
+ *
+<pre>public double nextDouble()
+{
+ return (((long) next(26) &lt;&lt; 27) + next(27)) / (double)(1L &lt;&lt; 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
+ * 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>
- * This is described in section 3.4.1 of <em>The Art of Computer
+ *
+<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.
+ * @return the next pseudorandom Gaussian distributed double
*/
public synchronized double nextGaussian()
{
if (haveNextNextGaussian)
{
- haveNextNextGaussian = false;
- return nextNextGaussian;
+ haveNextNextGaussian = false;
+ return nextNextGaussian;
}
- else
+ double v1, v2, s;
+ do
{
- 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;
+ 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;
}
}
diff --git a/libjava/java/util/SimpleTimeZone.java b/libjava/java/util/SimpleTimeZone.java
index 91d2d08..c2e2560 100644
--- a/libjava/java/util/SimpleTimeZone.java
+++ b/libjava/java/util/SimpleTimeZone.java
@@ -52,7 +52,8 @@ import java.text.DateFormatSymbols;
*
* @see Calendar
* @see GregorianCalender
- * @author Jochen Hoenicke */
+ * @author Jochen Hoenicke
+ */
public class SimpleTimeZone extends TimeZone
{
/**
@@ -436,9 +437,9 @@ public class SimpleTimeZone extends TimeZone
* 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:
- * <pre>
- * offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
- * </pre>
+ * <code>offset = cal.get(Calendar.ZONE_OFFSET)
+ * + cal.get(Calendar.DST_OFFSET);</code>
+ *
* You could also use in
*
* This version doesn't suffer this inaccuracy.
diff --git a/libjava/java/util/StringTokenizer.java b/libjava/java/util/StringTokenizer.java
index 707ddd4..e7fc6fd 100644
--- a/libjava/java/util/StringTokenizer.java
+++ b/libjava/java/util/StringTokenizer.java
@@ -1,5 +1,5 @@
-/* java.util.StringTokenizer
- Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+/* StringTokenizer -- breaks a String into tokens
+ Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,75 +39,79 @@ exception statement from your version. */
package java.util;
/**
- * This class splits a string into tokens. The caller can set on which
+ * 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.
+ * returned. This is much simpler than {@link java.io.StreamTokenizer}.
*
- * You may change the delimiter set on the fly by calling
+ * <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 returned.
+ * after the last token are candidates for being returned.
*
- * If you want to get the delimiters, you have to use the three argument
+ * <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.
+ * single character.
*
* @author Jochen Hoenicke
* @author Warren Levy <warrenl@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 String str;
+ 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 boolean retDelims;
-
- /*{
- invariant {
- pos >= 0 :: "position is negative";
- pos <= str.length() :: "position is out of string";
- str != null :: "String is null";
- delim != null :: "Delimiters are null";
- }
- } */
+ private final boolean retDelims;
/**
* Creates a new StringTokenizer for the string <code>str</code>,
- * that should split on the default delimiter set (space, tap,
+ * 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.
+ *
+ * @param str The string to split
+ * @throws NullPointerException if str is null
*/
public StringTokenizer(String str)
- /*{ require { str != null :: "str must not be null"; } } */
{
this(str, " \t\n\r\f", false);
}
/**
- * Create a new StringTokenizer, that splits the given string on
+ * 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.
+ * @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)
- /*{ require { str != null :: "str must not be null";
- delim != null :: "delim must not be null"; } } */
{
this(str, delim, false);
}
@@ -119,34 +123,34 @@ public class StringTokenizer implements Enumeration
* 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.
+ * @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)
- /*{ require { str != null :: "str must not be null";
- delim != null :: "delim must not be null"; } } */
{
+ len = str.length();
this.str = str;
- this.delim = delim;
+ // The toString() hack causes the NullPointerException.
+ this.delim = delim.toString();
this.retDelims = returnDelims;
this.pos = 0;
}
/**
* Tells if there are more tokens.
- * @return True, if the next call of nextToken() succeeds, false otherwise.
+ *
+ * @return true if the next call of nextToken() will succeed
*/
public boolean hasMoreTokens()
{
- if (!retDelims)
+ if (! retDelims)
{
- while (pos < str.length() && delim.indexOf(str.charAt(pos)) > -1)
- {
- pos++;
- }
+ while (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
+ pos++;
}
- return pos < str.length();
+ return pos < len;
}
/**
@@ -154,13 +158,13 @@ public class StringTokenizer implements Enumeration
* <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.
- * @exception NoSuchElementException if there are no more tokens.
+ *
+ * @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
- /*{ require { hasMoreTokens() :: "no more Tokens available";
- ensure { $return != null && $return.length() > 0; } } */
{
this.delim = delim;
return nextToken();
@@ -168,32 +172,24 @@ public class StringTokenizer implements Enumeration
/**
* Returns the nextToken of the string.
- * @param delim a string containing the new delimiter characters.
- * @return the next token with respect to the new delimiter characters.
- * @exception NoSuchElementException if there are no more tokens.
+ *
+ * @return the next token with respect to the current delimiter characters
+ * @throws NoSuchElementException if there are no more tokens
*/
public String nextToken() throws NoSuchElementException
- /*{ require { hasMoreTokens() :: "no more Tokens available";
- ensure { $return != null && $return.length() > 0; } } */
{
- if (pos < str.length() && delim.indexOf(str.charAt(pos)) > -1)
+ if (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
{
- if (retDelims)
- return str.substring(pos, ++pos);
-
- while (++pos < str.length() && delim.indexOf(str.charAt(pos)) > -1)
- {
- /* empty */
- }
+ if (retDelims)
+ return str.substring(pos, ++pos);
+ while (++pos < len && delim.indexOf(str.charAt(pos)) >= 0);
}
- if (pos < str.length())
+ if (pos < len)
{
- int start = pos;
- while (++pos < str.length() && delim.indexOf(str.charAt(pos)) == -1)
- {
- /* empty */
- }
- return str.substring(start, pos);
+ int start = pos;
+ while (++pos < len && delim.indexOf(str.charAt(pos)) < 0);
+
+ return str.substring(start, pos);
}
throw new NoSuchElementException();
}
@@ -201,9 +197,9 @@ public class StringTokenizer implements Enumeration
/**
* This does the same as hasMoreTokens. This is the
* <code>Enumeration</code interface method.
- * @return True, if the next call of nextElement() succeeds, false
- * otherwise.
- * @see #hasMoreTokens
+ *
+ * @return true, if the next call of nextElement() will succeed
+ * @see #hasMoreTokens()
*/
public boolean hasMoreElements()
{
@@ -213,9 +209,10 @@ public class StringTokenizer implements Enumeration
/**
* This does the same as nextTokens. This is the
* <code>Enumeration</code interface method.
- * @return the next token with respect to the new delimiter characters.
- * @exception NoSuchElementException if there are no more tokens.
- * @see #nextToken
+ *
+ * @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
{
@@ -225,49 +222,47 @@ public class StringTokenizer implements Enumeration
/**
* 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
+ *
+ * @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
+ 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 < str.length())
+ while (tmpPos < len)
{
- if (delim.indexOf(str.charAt(tmpPos++)) > -1)
- {
- 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 < str.length()
- && delim.indexOf(str.charAt(tmpPos)) == -1)
- ++tmpPos;
- }
+ 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
+ // 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
diff --git a/libjava/java/util/TimerTask.java b/libjava/java/util/TimerTask.java
index cb841e5..1b32b67 100644
--- a/libjava/java/util/TimerTask.java
+++ b/libjava/java/util/TimerTask.java
@@ -44,11 +44,11 @@ package java.util;
* it should have been scheduled and cancel itself when no longer needed.
* <p>
* Example:
- * <code>
+ * <pre>
* Timer timer = new Timer();
* TimerTask task = new TimerTask() {
* public void run() {
- * if (this.scheduledExecutionTime() < System.currentTimeMillis() + 500)
+ * if (this.scheduledExecutionTime() &lt; System.currentTimeMillis() + 500)
* // Do something
* else
* // Complain: We are more then half a second late!
@@ -56,7 +56,7 @@ package java.util;
* this.cancel(); // This was our last execution
* };
* timer.scheduleAtFixedRate(task, 1000, 1000); // schedule every second
- * </code>
+ * </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,
diff --git a/libjava/java/util/TreeMap.java b/libjava/java/util/TreeMap.java
index 8799682..dfa9bc6 100644
--- a/libjava/java/util/TreeMap.java
+++ b/libjava/java/util/TreeMap.java
@@ -1,6 +1,6 @@
/* TreeMap.java -- a class providing a basic Red-Black Tree data structure,
mapping Object --> Object
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -162,7 +162,7 @@ public class TreeMap extends AbstractMap
*
* @author Eric Blake <ebb9@email.byu.edu>
*/
- private static final class Node extends BasicMapEntry
+ private static final class Node extends AbstractMap.BasicMapEntry
{
// All fields package visible for use by nested classes.
/** The color of this node. */
@@ -623,8 +623,10 @@ public class TreeMap extends AbstractMap
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 n.value;
+ return result;
}
/**
@@ -1768,7 +1770,7 @@ public class TreeMap extends AbstractMap
SubMap.this.clear();
}
};
- return this.keys;
+ return this.values;
}
} // class SubMap
} // class TreeMap
diff --git a/libjava/java/util/WeakHashMap.java b/libjava/java/util/WeakHashMap.java
index 8c55ae0..3431ac9 100644
--- a/libjava/java/util/WeakHashMap.java
+++ b/libjava/java/util/WeakHashMap.java
@@ -1,4 +1,4 @@
-/* java.util.WeakHashMap -- a hashtable that keeps only weak references
+/* WeakHashMap -- a hashtable that keeps only weak references
to its keys, allowing the virtual machine to reclaim them
Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
@@ -43,41 +43,41 @@ import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
/**
- * A weak hash map has only weak references to the key. This means
- * that it allows the key to be garbage collected if they are not used
- * otherwise. If this happens, the weak hash map will eventually
- * remove the whole entry from this map. <br>
+ * A weak hash map has only weak references to the key. This means that it
+ * allows the key to be garbage collected if it is not used otherwise. If
+ * this happens, the entry will eventually disappear from the map,
+ * asynchronously.
*
- * A weak hash map makes most sense, if the keys doesn't override the
- * <code>equals</code>-method: If there is no other reference to the
+ * <p>A weak hash map makes most sense when the keys doesn't override the
+ * <code>equals</code> method: If there is no other reference to the
* key nobody can ever look up the key in this table and so the entry
- * can be removed. This table also works, if the <code>equals</code>
- * method is overloaded, e.g. with Strings as keys, but you should be
- * prepared that some entries disappear spontaneously. <br>
+ * can be removed. This table also works when the <code>equals</code>
+ * method is overloaded, such as String keys, but you should be prepared
+ * to deal with some entries disappearing spontaneously.
*
- * You should also be prepared that this hash map behaves very
- * strange: The size of this map may spontaneously shrink (even if you
- * use a synchronized map and synchronize it); it behaves as if
- * another thread removes entries from this table without
- * synchronizations. The entry set returned by <code>entrySet</code>
+ * <p>Other strange behaviors to be aware of: The size of this map may
+ * spontaneously shrink (even if you use a synchronized map and synchronize
+ * it); it behaves as if another thread removes entries from this table
+ * without synchronization. The entry set returned by <code>entrySet</code>
* has similar phenomenons: The size may spontaneously shrink, or an
- * entry, that was in the set before, suddenly disappears. <br>
+ * entry, that was in the set before, suddenly disappears.
*
- * A weak hash map is not meant for caches; use a normal map, with
- * soft references as values instead, or try {@link LinkedHashMap}. <br>
+ * <p>A weak hash map is not meant for caches; use a normal map, with
+ * soft references as values instead, or try {@link LinkedHashMap}.
*
- * The weak hash map supports null values and null keys. The null key
- * is never deleted from the map (except explictly of course).
- * The performance of the methods are similar to that of a hash map. <br>
+ * <p>The weak hash map supports null values and null keys. The null key
+ * is never deleted from the map (except explictly of course). The
+ * performance of the methods are similar to that of a hash map.
*
- * The value objects are strongly referenced by this table. So if a
+ * <p>The value objects are strongly referenced by this table. So if a
* value object maintains a strong reference to the key (either direct
* or indirect) the key will never be removed from this map. According
* to Sun, this problem may be fixed in a future release. It is not
* possible to do it with the jdk 1.2 reference model, though.
*
* @author Jochen Hoenicke
- * @author Eric Blake <ebb9@email.byu.edu>
+ * @author Eric Blake (ebb9@email.byu.edu)
+ *
* @see HashMap
* @see WeakReference
* @see LinkedHashMap
@@ -86,6 +86,9 @@ import java.lang.ref.ReferenceQueue;
*/
public class WeakHashMap extends AbstractMap implements Map
{
+ // WARNING: WeakHashMap is a CORE class in the bootstrap cycle. See the
+ // comments in vm/reference/java/lang/Runtime for implications of this fact.
+
/**
* The default capacity for an instance of HashMap.
* Sun's documentation mildly suggests that this (11) is the correct
@@ -148,7 +151,7 @@ public class WeakHashMap extends AbstractMap implements Map
/**
* The rounded product of the capacity (i.e. number of buckets) and
* the load factor. When the number of elements exceeds the
- * threshold, the HashMap calls <pre>rehash()</pre>.
+ * threshold, the HashMap calls <code>rehash()</code>.
*/
private int threshold;
@@ -364,11 +367,11 @@ public class WeakHashMap extends AbstractMap implements Map
/**
* The slot of this entry. This should be
- * <pre>
- * Math.abs(key.hashCode() % buckets.length)
- * </pre>
+ * <code>Math.abs(key.hashCode() % buckets.length)</code>.
+ *
* But since the key may be silently removed we have to remember
* the slot number.
+ *
* If this bucket was removed the slot is -1. This marker will
* prevent the bucket from being removed twice.
*/
@@ -503,9 +506,10 @@ public class WeakHashMap extends AbstractMap implements Map
private final WeakEntrySet theEntrySet;
/**
- * The hash buckets. These are linked lists.
+ * The hash buckets. These are linked lists. Package visible for use in
+ * nested classes.
*/
- private WeakBucket[] buckets;
+ WeakBucket[] buckets;
/**
* Creates a new weak hash map with default load factor and default
@@ -676,10 +680,12 @@ public class WeakHashMap extends AbstractMap implements Map
/**
* Removes a bucket from this hash map, if it wasn't removed before
- * (e.g. one time through rehashing and one time through reference queue)
+ * (e.g. one time through rehashing and one time through reference queue).
+ * Package visible for use in nested classes.
+ *
* @param bucket the bucket to remove.
*/
- private void internalRemove(WeakBucket bucket)
+ void internalRemove(WeakBucket bucket)
{
int slot = bucket.slot;
if (slot == -1)
@@ -870,4 +876,4 @@ public class WeakHashMap extends AbstractMap implements Map
cleanQueue();
return super.values();
}
-}
+} // class WeakHashMap
diff --git a/libjava/java/util/jar/Attributes.java b/libjava/java/util/jar/Attributes.java
index 46d4ada..0bf27bd 100644
--- a/libjava/java/util/jar/Attributes.java
+++ b/libjava/java/util/jar/Attributes.java
@@ -430,7 +430,7 @@ public class Attributes implements Cloneable, Map
* @returns the old value of the attribute name or null if it didn't exist
* yet
*/
- private String putValue(Name name, String value)
+ String putValue(Name name, String value)
{
return (String) put(name, value);
}
diff --git a/libjava/java/util/jar/JarException.java b/libjava/java/util/jar/JarException.java
index c8c0fba..54291c6 100644
--- a/libjava/java/util/jar/JarException.java
+++ b/libjava/java/util/jar/JarException.java
@@ -1,5 +1,5 @@
-/* Attributes.java -- exception thrown to indicate an problem with a jar file
- Copyright (C) 2000 Free Software Foundation, Inc.
+/* JarException.java -- thrown to indicate an problem with a jar file
+ Copyright (C) 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,35 +41,34 @@ import java.util.zip.ZipException;
/**
* This exception is thrown to indicate an problem with a jar file.
- * It can be constructed with or without a descriptive message of the problem.
- * <p>
* Note that none of the methods in the java.util.jar package actually declare
* to throw this exception, most just declare that they throw an IOException
* which is super class of JarException.
- *
- * @since 1.2
+ *
* @author Mark Wielaard (mark@klomp.org)
+ * @since 1.2
*/
-
public class JarException extends ZipException
{
- // Constructors
+ /**
+ * Compatible with JDK 1.2+.
+ */
+ private static final long serialVersionUID = 7159778400963954473L;
/**
* Create a new JarException without a descriptive error message.
*/
public JarException()
{
- super();
}
/**
* Create a new JarException with a descriptive error message indicating
* what went wrong. This message can later be retrieved by calling the
* <code>getMessage()</code> method.
- * @see java.lang.Throwable@getMessage()
*
* @param message The descriptive error message
+ * @see #getMessage()
*/
public JarException(String message)
{
diff --git a/libjava/java/util/jar/Manifest.java b/libjava/java/util/jar/Manifest.java
index 20220b1..9a15376 100644
--- a/libjava/java/util/jar/Manifest.java
+++ b/libjava/java/util/jar/Manifest.java
@@ -174,10 +174,19 @@ public class Manifest implements Cloneable
private static void read_main_section(Attributes attr,
BufferedReader br) throws IOException
{
- read_version_info(attr, br);
+ // According to the spec we should actually call read_version_info() here.
read_attributes(attr, br);
+ // Explicitly set Manifest-Version attribute if not set in Main
+ // attributes of Manifest.
+ if (attr.getValue(Attributes.Name.MANIFEST_VERSION) == null)
+ attr.putValue(Attributes.Name.MANIFEST_VERSION, "0.0");
}
+ /**
+ * Pedantic method that requires the next attribute in the Manifest to be
+ * the "Manifest-Version". This follows the Manifest spec closely but
+ * reject some jar Manifest files out in the wild.
+ */
private static void read_version_info(Attributes attr,
BufferedReader br) throws IOException
{
@@ -185,7 +194,7 @@ public class Manifest implements Cloneable
try
{
String value = expect_header(version_header, br);
- attr.putValue(version_header, value);
+ attr.putValue(Attributes.Name.MANIFEST_VERSION, value);
}
catch (IOException ioe)
{