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
This commit is contained in:
Tom Tromey 2002-06-18 15:40:16 +00:00 committed by Tom Tromey
parent 0fd534ed06
commit 3831381763
31 changed files with 2304 additions and 1518 deletions

View file

@ -1,3 +1,37 @@
2002-06-18 Tom Tromey <tromey@redhat.com>
* 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.
2002-06-17 Tom Tromey <tromey@redhat.com> 2002-06-17 Tom Tromey <tromey@redhat.com>
* gcj/javaprims.h: Updated class declaration list. * gcj/javaprims.h: Updated class declaration list.

View file

@ -1220,6 +1220,7 @@ java/util/Observable.java \
java/util/Observer.java \ java/util/Observer.java \
java/util/Properties.java \ java/util/Properties.java \
java/util/PropertyPermission.java \ java/util/PropertyPermission.java \
java/util/PropertyPermissionCollection.java \
java/util/PropertyResourceBundle.java \ java/util/PropertyResourceBundle.java \
java/util/Random.java \ java/util/Random.java \
java/util/RandomAccess.java \ java/util/RandomAccess.java \

View file

@ -987,6 +987,7 @@ java/util/Observable.java \
java/util/Observer.java \ java/util/Observer.java \
java/util/Properties.java \ java/util/Properties.java \
java/util/PropertyPermission.java \ java/util/PropertyPermission.java \
java/util/PropertyPermissionCollection.java \
java/util/PropertyResourceBundle.java \ java/util/PropertyResourceBundle.java \
java/util/Random.java \ java/util/Random.java \
java/util/RandomAccess.java \ java/util/RandomAccess.java \
@ -2550,6 +2551,7 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/java/util/NoSuchElementException.P .deps/java/util/Observable.P \ .deps/java/util/NoSuchElementException.P .deps/java/util/Observable.P \
.deps/java/util/Observer.P .deps/java/util/Properties.P \ .deps/java/util/Observer.P .deps/java/util/Properties.P \
.deps/java/util/PropertyPermission.P \ .deps/java/util/PropertyPermission.P \
.deps/java/util/PropertyPermissionCollection.P \
.deps/java/util/PropertyResourceBundle.P .deps/java/util/Random.P \ .deps/java/util/PropertyResourceBundle.P .deps/java/util/Random.P \
.deps/java/util/RandomAccess.P .deps/java/util/ResourceBundle.P \ .deps/java/util/RandomAccess.P .deps/java/util/ResourceBundle.P \
.deps/java/util/Set.P .deps/java/util/SimpleTimeZone.P \ .deps/java/util/Set.P .deps/java/util/SimpleTimeZone.P \

View file

@ -243,6 +243,7 @@ extern "Java"
class AbstractCollection; class AbstractCollection;
class AbstractList; class AbstractList;
class AbstractMap; class AbstractMap;
class AbstractMap$BasicMapEntry;
class AbstractSequentialList; class AbstractSequentialList;
class AbstractSet; class AbstractSet;
class ArrayList; class ArrayList;
@ -317,11 +318,13 @@ extern "Java"
class Map$Entry; class Map$Entry;
class Map$Map; class Map$Map;
class MissingResourceException; class MissingResourceException;
class MyResources;
class NoSuchElementException; class NoSuchElementException;
class Observable; class Observable;
class Observer; class Observer;
class Properties; class Properties;
class PropertyPermission; class PropertyPermission;
class PropertyPermissionCollection;
class PropertyResourceBundle; class PropertyResourceBundle;
class Random; class Random;
class RandomAccess; class RandomAccess;

View file

@ -301,8 +301,8 @@ public class Thread implements Runnable
public static native void yield (); public static native void yield ();
// Private data. // Private data.
private ThreadGroup group; ThreadGroup group;
private String name; String name;
private Runnable runnable; private Runnable runnable;
private int priority; private int priority;
private boolean daemon_flag; private boolean daemon_flag;

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* AbstractList.java -- Abstract implementation of most of List /* 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. 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 * Obtains a hash code for this list. In order to obey the general
* the hashCode method of class Object, this value is calculated as follows: * contract of the hashCode method of class Object, this value is
* <pre> * calculated as follows:
* hashCode = 1; *
* Iterator i = list.iterator(); <pre>hashCode = 1;
* while (i.hasNext()) Iterator i = list.iterator();
* { while (i.hasNext())
* Object obj = i.next(); {
* hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode()); Object obj = i.next();
* } hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
* </pre> }</pre>
*
* This ensures that the general contract of Object.hashCode() is adhered to. * This ensures that the general contract of Object.hashCode() is adhered to.
* *
* @return the hash code of this list * @return the hash code of this list
*
* @see Object#hashCode() * @see Object#hashCode()
* @see #equals(Object) * @see #equals(Object)
*/ */
@ -611,19 +613,21 @@ public abstract class AbstractList extends AbstractCollection implements List
/** /**
* This class follows the implementation requirements set forth in * This class follows the implementation requirements set forth in
* {@link AbstractList#subList(int, int)}. Some compilers have problems * {@link AbstractList#subList(int, int)}. It matches Sun's implementation
* with AbstractList.this.modCount if this class is nested in AbstractList, * by using a non-public top-level class in the same package.
* even though the JLS defines that to be legal, so we make it a top-level
* class.
* *
* @author Original author unknown * @author Original author unknown
* @author Eric Blake <ebb9@email.byu.edu> * @author Eric Blake <ebb9@email.byu.edu>
*/ */
class SubList extends AbstractList class SubList extends AbstractList
{ {
private final AbstractList backingList; // Package visible, for use by iterator.
private final int offset; /** The original list. */
private int size; 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. * Construct the sublist.
@ -647,8 +651,8 @@ class SubList extends AbstractList
* @throws ConcurrentModificationException if the backing list has been * @throws ConcurrentModificationException if the backing list has been
* modified externally to this sublist * modified externally to this sublist
*/ */
// This will get inlined, since it is private. // This can be inlined. Package visible, for use by iterator.
private void checkMod() void checkMod()
{ {
if (modCount != backingList.modCount) if (modCount != backingList.modCount)
throw new ConcurrentModificationException(); throw new ConcurrentModificationException();

View file

@ -1,5 +1,5 @@
/* AbstractMap.java -- Abstract implementation of most of Map /* 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. This file is part of GNU Classpath.
@ -518,4 +518,130 @@ public abstract class AbstractMap implements Map
{ {
return o == null ? 0 : o.hashCode(); 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
} }

View file

@ -73,13 +73,12 @@ import java.io.*;
* and for the first line all fields are set, that line is used to * and for the first line all fields are set, that line is used to
* compute the day. <br> * compute the day. <br>
* *
* <pre> *
* month + day_of_month <pre>month + day_of_month
* month + week_of_month + day_of_week month + week_of_month + day_of_week
* month + day_of_week_of_month + day_of_week month + day_of_week_of_month + day_of_week
* day_of_year day_of_year
* day_of_week + week_of_year day_of_week + week_of_year</pre>
* </pre>
* *
* The hour_of_day-field takes precedence over the ampm and * The hour_of_day-field takes precedence over the ampm and
* hour_of_ampm fields. <br> * hour_of_ampm fields. <br>

View file

@ -1,5 +1,5 @@
/* Collections.java -- Utility class with methods to operate on collections /* 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. This file is part of GNU Classpath.
@ -60,7 +60,6 @@ import java.io.Serializable;
* modify the set. * modify the set.
* *
* @author Original author unknown * @author Original author unknown
* @author Bryce McKinlay
* @author Eric Blake <ebb9@email.byu.edu> * @author Eric Blake <ebb9@email.byu.edu>
* @see Collection * @see Collection
* @see Set * @see Set
@ -108,24 +107,6 @@ public class Collections
*/ */
public static final Set EMPTY_SET = new EmptySet(); 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 * The implementation of {@link #EMPTY_SET}. This class name is required
* for compatibility with Sun's JDK serializability. * for compatibility with Sun's JDK serializability.
@ -158,9 +139,94 @@ public class Collections
/** /**
* Returns an iterator that does not iterate. * Returns an iterator that does not iterate.
*/ */
// This is really cheating! I think it's perfectly valid, though.
public Iterator iterator() 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 } // class EmptySet
@ -208,13 +274,104 @@ public class Collections
throw new IndexOutOfBoundsException(); 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 * Never contains anything.
* allocation of an iterator in AbstractList.
*/ */
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 } // class EmptyList
@ -253,6 +410,64 @@ public class Collections
return EMPTY_SET; 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. * Size is always 0.
*/ */
@ -269,8 +484,17 @@ public class Collections
{ {
return EMPTY_SET; return EMPTY_SET;
} }
/**
* The string never changes.
*/
public String toString()
{
return "[]";
}
} // class EmptyMap } // class EmptyMap
/** /**
* Compare two objects with or without a Comparator. If c is null, uses the * 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 * 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 * Enumeration. This method exists for interoperability between legacy
* APIs and the new Collection API. * APIs and the new Collection API.
* *
@ -511,9 +735,9 @@ public class Collections
* @see ArrayList * @see ArrayList
* @since 1.4 * @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()) while (e.hasMoreElements())
l.add(e.nextElement()); l.add(e.nextElement());
return l; return l;
@ -1353,7 +1577,7 @@ public class Collections
public Set entrySet() public Set entrySet()
{ {
if (entries == null) if (entries == null)
entries = singleton(new BasicMapEntry(k, v) entries = singleton(new AbstractMap.BasicMapEntry(k, v)
{ {
public Object setValue(Object o) public Object setValue(Object o)
{ {
@ -1500,6 +1724,7 @@ public class Collections
l.set(i, l.set(j, l.get(i))); l.set(i, l.set(j, l.get(i)));
} }
/** /**
* Returns a synchronized (thread-safe) collection wrapper backed by the * Returns a synchronized (thread-safe) collection wrapper backed by the
* given collection. Notice that element access through the iterators * given collection. Notice that element access through the iterators
@ -2682,6 +2907,7 @@ public class Collections
} }
} // class SynchronizedSortedSet } // class SynchronizedSortedSet
/** /**
* Returns an unmodifiable view of the given collection. This allows * Returns an unmodifiable view of the given collection. This allows
* "read-only" access, although changes in the backing collection show up * "read-only" access, although changes in the backing collection show up

View file

@ -1,6 +1,6 @@
/* HashMap.java -- a class providing a basic hashtable data structure, /* HashMap.java -- a class providing a basic hashtable data structure,
mapping Object --> Object 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. This file is part of GNU Classpath.
@ -162,7 +162,7 @@ public class HashMap extends AbstractMap
* *
* @author Eric Blake <ebb9@email.byu.edu> * @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. * 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(); Map.Entry e = (Map.Entry) itr.next();
// Optimize in case the Entry is one of our own. // 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); put(entry.key, entry.value);
} }
else else
@ -647,7 +647,8 @@ public class HashMap extends AbstractMap
* @return the matching entry, if found, or null * @return the matching entry, if found, or null
* @see #entrySet() * @see #entrySet()
*/ */
private HashEntry getEntry(Object o) // Package visible, for use in nested classes.
HashEntry getEntry(Object o)
{ {
if (!(o instanceof Map.Entry)) if (!(o instanceof Map.Entry))
return null; return null;
@ -710,14 +711,13 @@ public class HashMap extends AbstractMap
} }
/** /**
* Increases the size of the HashMap and rehashes all keys to new array * Increases the size of the HashMap and rehashes all keys to new
* indices; this is called when the addition of a new value would cause * array indices; this is called when the addition of a new value
* size() > threshold. Note that the existing Entry objects are reused in * would cause size() &gt; threshold. Note that the existing Entry
* the new hash table. * objects are reused in the new hash table.
* <p>
* *
* This is not specified, but the new size is twice the current size plus * <p>This is not specified, but the new size is twice the current size
* one; this number is not always prime, unfortunately. * plus one; this number is not always prime, unfortunately.
*/ */
private void rehash() private void rehash()
{ {

View file

@ -1,6 +1,6 @@
/* Hashtable.java -- a class providing a basic hashtable data structure, /* Hashtable.java -- a class providing a basic hashtable data structure,
mapping Object --> Object 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. This file is part of GNU Classpath.
@ -102,6 +102,9 @@ import java.io.ObjectOutputStream;
public class Hashtable extends Dictionary public class Hashtable extends Dictionary
implements Map, Cloneable, Serializable 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 /** Default number of buckets. This is the value the JDK 1.3 uses. Some
* early documentation specified this value as 101. That is incorrect. * 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 * pair. A Hashtable Entry is identical to a HashMap Entry, except that
* `null' is not allowed for keys and values. * `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. */ /** The next entry in the linked list. */
HashEntry next; HashEntry next;
@ -340,9 +343,9 @@ public class Hashtable extends Dictionary
* *
* @param value the value to search for in this Hashtable * @param value the value to search for in this Hashtable
* @return true if at least one key maps to the value * @return true if at least one key maps to the value
* @throws NullPointerException if <code>value</code> is null
* @see #contains(Object) * @see #contains(Object)
* @see #containsKey(Object) * @see #containsKey(Object)
* @throws NullPointerException if <code>value</code> is null
* @since 1.2 * @since 1.2
*/ */
public boolean containsValue(Object value) public boolean containsValue(Object value)
@ -511,9 +514,9 @@ public class Hashtable extends Dictionary
{ {
Map.Entry e = (Map.Entry) itr.next(); Map.Entry e = (Map.Entry) itr.next();
// Optimize in case the Entry is one of our own. // 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); put(entry.key, entry.value);
} }
else else
@ -763,9 +766,9 @@ public class Hashtable extends Dictionary
/** /**
* Returns true if this Hashtable equals the supplied Object <code>o</code>. * Returns true if this Hashtable equals the supplied Object <code>o</code>.
* As specified by Map, this is: * As specified by Map, this is:
* <pre> * <code>
* (o instanceof Map) && entrySet().equals(((Map) o).entrySet()); * (o instanceof Map) && entrySet().equals(((Map) o).entrySet());
* </pre> * </code>
* *
* @param o the object to compare to * @param o the object to compare to
* @return true if o is an equal map * @return true if o is an equal map
@ -812,7 +815,10 @@ public class Hashtable extends Dictionary
*/ */
private int hash(Object key) 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 * @return the matching entry, if found, or null
* @see #entrySet() * @see #entrySet()
*/ */
private HashEntry getEntry(Object o) // Package visible, for use in nested classes.
HashEntry getEntry(Object o)
{ {
if (! (o instanceof Map.Entry)) if (! (o instanceof Map.Entry))
return null; return null;
@ -869,7 +876,7 @@ public class Hashtable extends Dictionary
/** /**
* Increases the size of the Hashtable and rehashes all keys to new array * 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 * 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. * the new hash table.
* <p> * <p>
* *
@ -1139,4 +1146,4 @@ public class Hashtable extends Dictionary
return type == VALUES ? e.value : e.key; return type == VALUES ? e.value : e.key;
} }
} // class Enumerator } // class Enumerator
} } // class Hashtable

View file

@ -71,7 +71,7 @@ package java.util;
* <p> * <p>
* *
* Under ideal circumstances (no collisions), LinkedHashMap offers O(1) * 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 * of course, O(n)). In the worst case (all keys map to the same
* hash code -- very unlikely), most operations are O(n). * hash code -- very unlikely), most operations are O(n).
* <p> * <p>
@ -87,7 +87,7 @@ package java.util;
* {@link ConcurrentModificationException} rather than exhibit * {@link ConcurrentModificationException} rather than exhibit
* non-deterministic behavior. * non-deterministic behavior.
* *
* @author Eric Blake <ebb9@email.byu.edu> * @author Eric Blake (ebb9@email.byu.edu)
* @see Object#hashCode() * @see Object#hashCode()
* @see Collection * @see Collection
* @see Map * @see Map
@ -256,8 +256,9 @@ public class LinkedHashMap extends HashMap
* @param initialCapacity the initial capacity (>=0) * @param initialCapacity the initial capacity (>=0)
* @param loadFactor the load factor (>0, not NaN) * @param loadFactor the load factor (>0, not NaN)
* @param accessOrder true for access-order, false for insertion-order * @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, public LinkedHashMap(int initialCapacity, float loadFactor,
boolean accessOrder) boolean accessOrder)
@ -277,11 +278,12 @@ public class LinkedHashMap extends HashMap
} }
/** /**
* Returns true if this HashMap contains a value <pre>o</pre>, such that * Returns <code>true</code> if this HashMap contains a value
* <pre>o.equals(value)</pre>. * <code>o</code>, such that <code>o.equals(value)</code>.
* *
* @param value the value to search for in this HashMap * @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) 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, * 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 * access-ordered Map and the key is found, this performs structural
* modification, moving the key to the newest end of the list. NOTE: * modification, moving the key to the newest end of the list. NOTE:
* Since the value could also be null, you must use containsKey to * Since the value could also be null, you must use containsKey to
@ -350,14 +352,14 @@ public class LinkedHashMap extends HashMap
* <p> * <p>
* *
* For example, to keep the Map limited to 100 entries, override as follows: * 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) <pre>private static final int MAX_ENTRIES = 100;
* {
* return size() > MAX_ENTRIES; protected boolean removeEldestEntry(Map.Entry eldest)
* } {
* </pre><p> return size() &gt; MAX_ENTRIES;
}
</pre><p>
* *
* Typically, this method does not modify the map, but just uses the * Typically, this method does not modify the map, but just uses the
* return value as an indication to <code>put</code> whether to proceed. * 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 * returns true. For an access-order map, this is the least
* recently accessed; for an insertion-order map, this is the * recently accessed; for an insertion-order map, this is the
* earliest element inserted. * earliest element inserted.
*
* @return true if <code>eldest</code> should be removed * @return true if <code>eldest</code> should be removed
*/ */
protected boolean removeEldestEntry(Map.Entry eldest) 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 * 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 ConcurrentModificationException if the HashMap was modified
*
* @throws IllegalStateException if called when there is no last element * @throws IllegalStateException if called when there is no last element
*/ */
public void remove() public void remove()

View file

@ -1,5 +1,5 @@
/* LinkedList.java -- Linked list implementation of the List interface /* 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. 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 * entry in the list is obtained in constant time, which is a very desirable
* property. * property.
* For speed and flexibility, range checking is not done in this method: * 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 * @param n the number of the entry to get
* @return the entry at position n * @return the entry at position n
*/ */
private Entry getEntry(int n) // Package visible for use in nested classes.
Entry getEntry(int n)
{ {
Entry e; Entry e;
if (n < size / 2) if (n < size / 2)
@ -156,7 +157,8 @@ public class LinkedList extends AbstractSequentialList
* *
* @param e the entry to remove * @param e the entry to remove
*/ */
private void removeEntry(Entry e) // Package visible for use in nested classes.
void removeEntry(Entry e)
{ {
modCount++; modCount++;
size--; size--;

View file

@ -201,7 +201,7 @@ public interface List extends Collection
* @see Object#equals(Object) * @see Object#equals(Object)
* @see #hashCode() * @see #hashCode()
*/ */
/* boolean equals(Object o);*/ boolean equals(Object o);
/** /**
* Get the element at a given index in this list. * Get the element at a given index in this list.
@ -213,18 +213,20 @@ public interface List extends Collection
Object get(int index); Object get(int index);
/** /**
* Obtain a hash code for this list. In order to obey the general contract of * Obtains a hash code for this list. In order to obey the general
* the hashCode method of class Object, this value is calculated as follows: * contract of the hashCode method of class Object, this value is
* <pre> * calculated as follows:
* hashCode = 1; *
* Iterator i = list.iterator(); <p><pre>hashCode = 1;
* while (i.hasNext()) Iterator i = list.iterator();
* { while (i.hasNext())
* Object obj = i.next(); {
* hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode()); Object obj = i.next();
* } hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
* </pre> }</pre>
* This ensures that the general contract of Object.hashCode() is adhered to. *
* <p>This ensures that the general contract of Object.hashCode()
* is adhered to.
* *
* @return the hash code of this list * @return the hash code of this list
* @see Object#hashCode() * @see Object#hashCode()

View file

@ -1,5 +1,5 @@
/* java.util.ListResourceBundle /* ListResourceBundle -- a resource bundle build around a list
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
@ -39,20 +39,45 @@ exception statement from your version. */
package java.util; package java.util;
/** /**
* A <code>ListResouceBundle</code> provides an easy way, to create * A <code>ListResouceBundle</code> provides an easy way, to create your own
* your own resource bundle. It is an abstract class that you can * resource bundle. It is an abstract class that you can subclass. You should
* subclass. You should then overwrite the getContents method, that * then overwrite the getContents method, that provides a key/value list.
* 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!
* *
* <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 Locale
* @see PropertyResourceBundle * @see PropertyResourceBundle
* @author Jochen Hoenicke */ * @since 1.1
* @status updated to 1.4
*/
public abstract class ListResourceBundle extends ResourceBundle public abstract class ListResourceBundle extends ResourceBundle
{ {
/** /**
@ -63,49 +88,53 @@ public abstract class ListResourceBundle extends ResourceBundle
} }
/** /**
* Gets the key/value list. You must override this method. * Gets a resource for a given key. This is called by <code>getObject</code>.
* @return a two dimensional list of Objects. The first dimension *
* ranges over the objects, and the second dimension ranges from * @param key the key of the resource
* zero (key) to one (value). * @return the resource for the key, or null if it doesn't exist
*/
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.
*/ */
public final Object handleGetObject(String key) public final Object handleGetObject(String key)
{ {
Object[][] contents = getContents(); Object[][] contents = getContents();
for (int i = 0; i < contents.length; i++) int i = contents.length;
{ while (--i >= 0)
if (key.equals(contents[i][0])) if (key.equals(contents[i][0]))
return contents[i][1]; return contents[i][1];
}
return null; return null;
} }
/** /**
* This method should return all keys for which a resource exists. * 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() 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(); final Object[][] contents = getContents();
Set s = new HashSet();
int i = contents.length;
while (--i >= 0)
s.add(contents[i][0]);
ResourceBundle bundle = parent;
// Eliminate tail recursion.
while (bundle != null)
{
Enumeration e = bundle.getKeys();
while (e.hasMoreElements())
s.add(e.nextElement());
bundle = bundle.parent;
}
return Collections.enumeration(s);
}
return new Enumeration() /**
{ * Gets the key/value list. You must override this method, and should not
int i = 0; * provide duplicate keys or null entries.
public boolean hasMoreElements() *
{ * @return a two dimensional list of String key / Object resouce pairs
return i < contents.length; */
} protected abstract Object[][] getContents();
public Object nextElement() } // class ListResourceBundle
{
return contents[i++][0];
}
};
}
}

View file

@ -296,14 +296,14 @@ public interface Map
*/ */
public Object setValue(Object value); public Object setValue(Object value);
/** /**
* Returns the hash code of the entry. This is defined as the exclusive-or * Returns the hash code of the entry. This is defined as the
* of the hashcodes of the key and value (using 0 for null). In other * exclusive-or of the hashcodes of the key and value (using 0 for
* words, this must be: * <code>null</code>). In other words, this must be:
* <pre> *
* (getKey() == null ? 0 : getKey().hashCode()) ^ <p><pre>(getKey() == null ? 0 : getKey().hashCode())
* (getValue() == null ? 0 : getValue().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode())</pre>
* </pre>
* *
* @return the hash code * @return the hash code
*/ */
@ -313,16 +313,16 @@ public interface Map
* Compares the specified object with this entry. Returns true only if * Compares the specified object with this entry. Returns true only if
* the object is a mapping of identical key and value. In other words, * the object is a mapping of identical key and value. In other words,
* this must be: * this must be:
* <pre> *
* (o instanceof Map.Entry) <p><pre>(o instanceof Map.Entry)
* && (getKey() == null ? ((HashMap) o).getKey() == null && (getKey() == null ? ((HashMap) o).getKey() == null
* : getKey().equals(((HashMap) o).getKey())) : getKey().equals(((HashMap) o).getKey()))
* && (getValue() == null ? ((HashMap) o).getValue() == null && (getValue() == null ? ((HashMap) o).getValue() == null
* : getValue().equals(((HashMap) o).getValue())) : getValue().equals(((HashMap) o).getValue()))</pre>
* </pre>
* *
* @param o the object to compare * @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); public boolean equals(Object o);
} }

View file

@ -1,5 +1,5 @@
/* java.util.Observable /* Observable.java -- an object to be observed
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
@ -38,55 +38,53 @@ exception statement from your version. */
package java.util; 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> * @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 public class Observable
{ {
/** tracks whether this object has changed */ /** Tracks whether this object has changed. */
private boolean changed; private boolean changed;
/* list of the Observers registered as interested in this Observable */ /* List of the Observers registered as interested in this Observable. */
private Vector observers; private LinkedHashSet 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[].
*/
/** /**
* Constructs an Observable with zero Observers. * Constructs an Observable with zero Observers.
*/ */
public Observable() public Observable()
{ {
changed = false; observers = new LinkedHashSet();
observers = new Vector();
} }
/** /**
* Adds an Observer. If the observer was already added this method does * Adds an Observer. If the observer was already added this method does
* nothing. * nothing.
* *
* @param observer Observer to add. * @param observer Observer to add
* @throws NullPointerException if observer is null
*/ */
public synchronized void addObserver(Observer observer) public synchronized void addObserver(Observer observer)
{ {
if (!observers.contains(observer)) observers.add(observer);
observers.addElement(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() 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() public synchronized int countObservers()
{ {
@ -104,11 +104,11 @@ public class Observable
/** /**
* Deletes an Observer of this Observable. * Deletes an Observer of this Observable.
* *
* @param victim Observer to delete. * @param victim Observer to delete
*/ */
public synchronized void deleteObserver(Observer victim) public synchronized void deleteObserver(Observer victim)
{ {
observers.removeElement(victim); observers.remove(victim);
} }
/** /**
@ -116,11 +116,14 @@ public class Observable
*/ */
public synchronized void deleteObservers() 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() public synchronized boolean hasChanged()
{ {
@ -129,7 +132,10 @@ public class Observable
/** /**
* If the Observable has actually changed then tell all Observers about it, * 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() public void notifyObservers()
{ {
@ -138,21 +144,29 @@ public class Observable
/** /**
* If the Observable has actually changed then tell all Observers about it, * If the Observable has actually changed then tell all Observers about it,
* then resets state to unchanged. * then reset state to unchanged. Note that though the order of
* Note that though the order of notification is unspecified in subclasses, * notification is unspecified in subclasses, in Observable it is in the
* in Observable it is in the order of registration. * 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) public void notifyObservers(Object obj)
{ {
if (!hasChanged()) if (! hasChanged())
return; return;
Vector ob1 = (Vector) observers.clone(); // Create clone inside monitor, as that is relatively fast and still
// important to keep threadsafe, but update observers outside of the
for (int i = 0; i < ob1.size(); i++) // lock since update() can call arbitrary code.
((Observer) ob1.elementAt(i)).update(this, obj); 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(); clearChanged();
} }

View file

@ -1,5 +1,5 @@
/* java.util.Properties /* Properties.java -- a set of persistent properties
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. This file is part of GNU Classpath.
@ -37,70 +37,109 @@ exception statement from your version. */
package java.util; 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 * 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 * Create a file MyResource_de.properties with the following contents
* and put it in the CLASSPATH. (The character * and put it in the CLASSPATH. (The character
* <code>\</code><code>u00e4</code> is the german &auml;) * <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>
* *
* Although this is a sub class of a hash table, you should never <pre>s1=3
s2=MeineDisk
s3=3. M\<code></code>u00e4rz 96
s4=Die Diskette ''{1}'' enth\<code></code>u00e4lt {0} in {2}.
s5=0
s6=keine Dateien
s7=1
s8=eine Datei
s9=2
s10={0,number} Dateien
s11=Das Formatieren schlug fehl mit folgender Exception: {0}
s12=FEHLER
s13=Ergebnis
s14=Dialog
s15=Auswahlkriterium
s16=1,3</pre>
*
* <p>Although this is a sub class of a hash table, you should never
* insert anything other than strings to this property, or several * insert anything other than strings to this property, or several
* methods, that need string keys and values, will fail. To ensure * methods, that need string keys and values, will fail. To ensure
* this, you should use the <code>get/setProperty</code> method instead * this, you should use the <code>get/setProperty</code> method instead
* of <code>get/put</code>. * 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 Jochen Hoenicke
* @author Eric Blake <ebb9@email.byu.edu>
* @see PropertyResourceBundle
* @status updated to 1.4
*/ */
public class Properties extends Hashtable 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 * 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; protected Properties defaults;
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = 4112578634029874840L; private static final long serialVersionUID = 4112578634029874840L;
/** /**
* Creates a new empty property list. * Creates a new empty property list with no default values.
*/ */
public Properties() public Properties()
{ {
this.defaults = null;
} }
/** /**
* Create a new empty property list with the specified default values. * 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) public Properties(Properties defaults)
{ {
this.defaults = defaults; this.defaults = defaults;
} }
/**
* Adds the given key/value pair to this properties. This calls
* the hashtable method put.
*
* @param key the key for this property
* @param value the value for this property
* @return The old value for the given key
* @see #getProperty(String)
* @since 1.2
*/
public Object setProperty(String key, String value)
{
return put(key, value);
}
/** /**
* Reads a property list from an input stream. The stream should * Reads a property list from an input stream. The stream should
* have the following format: <br> * have the following format: <br>
@ -120,24 +159,24 @@ public class Properties extends Hashtable
* *
* Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a * Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a
* space), and unicode characters with the * 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> * converted to the corresponding single character. <br>
* *
* <pre> *
* # This is a comment <pre># This is a comment
* key = value key = value
* k\:5 \ a string starting with space and ending with newline\n k\:5 \ a string starting with space and ending with newline\n
* # This is a multiline specification; note that the value contains # This is a multiline specification; note that the value contains
* # no white space. # no white space.
* weekdays: Sunday,Monday,Tuesday,Wednesday,\ weekdays: Sunday,Monday,Tuesday,Wednesday,\\
* Thursday,Friday,Saturday Thursday,Friday,Saturday
* # The safest way to include a space at the end of a value: # The safest way to include a space at the end of a value:
* label = Name:\<code></code>u0020 label = Name:\\u0020</pre>
* </pre>
* *
* @param in the input stream * @param in the input stream
* @exception IOException if an error occurred when reading * @throws IOException if an error occurred when reading the input
* from the input. */ * @throws NullPointerException if in is null
*/
public void load(InputStream inStream) throws IOException public void load(InputStream inStream) throws IOException
{ {
// The spec says that the file must be encoded using ISO-8859-1. // The spec says that the file must be encoded using ISO-8859-1.
@ -162,7 +201,7 @@ public class Properties extends Hashtable
// describe the key. But look for escape sequences. // describe the key. But look for escape sequences.
StringBuffer key = new StringBuffer(); StringBuffer key = new StringBuffer();
while (pos < line.length() while (pos < line.length()
&& !Character.isWhitespace(c = line.charAt(pos++)) && ! Character.isWhitespace(c = line.charAt(pos++))
&& c != '=' && c != ':') && c != '=' && c != ':')
{ {
if (c == '\\') if (c == '\\')
@ -214,7 +253,7 @@ public class Properties extends Hashtable
&& Character.isWhitespace(c = line.charAt(pos))) && Character.isWhitespace(c = line.charAt(pos)))
pos++; pos++;
if (!isDelim && (c == ':' || c == '=')) if (! isDelim && (c == ':' || c == '='))
{ {
pos++; pos++;
while (pos < line.length() while (pos < line.length()
@ -278,9 +317,12 @@ public class Properties extends Hashtable
/** /**
* Calls <code>store(OutputStream out, String header)</code> and * Calls <code>store(OutputStream out, String header)</code> and
* ignores the IOException that may be thrown. * ignores the IOException that may be thrown.
* @deprecated use store instead. *
* @exception ClassCastException if this property contains any key or * @param out the stream to write to
* value that isn't a string. * @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) public void save(OutputStream out, String header)
{ {
@ -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 * If header is not null, this method writes a comment containing
* the header as first line to the stream. The next line (or first * 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. * line if header is null) contains a comment with the current date.
* Afterwards the key/value pairs are written to the stream in the * 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, * Each line has the form <code>key = value</code>. Newlines,
* Returns and tabs are written as <code>\n,\t,\r</code> resp. * 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, * preceeded by a backslash. Spaces are preceded with a backslash,
* if and only if they are at the beginning of the key. Characters * 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 * 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 out the output stream
* @param header the header written in the first line, may be null. * @param header the header written in the first line, may be null
* @exception ClassCastException if this property contains any key or * @throws ClassCastException if this property contains any key or
* value that isn't a string. * 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 public void store(OutputStream out, String header) throws IOException
{ {
// The spec says that the file must be encoded using ISO-8859-1. // The spec says that the file must be encoded using ISO-8859-1.
PrintWriter writer PrintWriter writer
= new PrintWriter(new OutputStreamWriter (out, "ISO-8859-1")); = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
if (header != null) if (header != null)
writer.println("#" + header); writer.println("#" + header);
writer.println("#" + new Date().toString()); writer.println("#" + new Date());
list(writer); list(writer);
writer.flush(); 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. * 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 key is not found, the default property list is searched.
* If the property is not found in default or the default of * If the property is not found in the default, null is returned.
* default, null is returned. *
* @param key The key for this property. * @param key The key for this property
* @param defaulValue A default value * @return the value for the given key, or null if not found
* @return The value for the given key, or null if not found. * @throws ClassCastException if this property contains any key or
* @exception ClassCastException if this property contains any key or * value that isn't a string
* value that isn't a string. * @see #defaults
* @see #setProperty(String, String)
* @see #getProperty(String, String)
*/ */
public String getProperty(String key) 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 * 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 * 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 * property is not found in the default, the specified defaultValue is
* specified defaultValue is returned. * returned.
* @param key The key for this property. *
* @param defaulValue A default value * @param key The key for this property
* @return The value for the given key. * @param defaultValue A default value
* @exception ClassCastException if this property contains any key or * @return The value for the given key
* value that isn't a string. * @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) public String getProperty(String key, String defaultValue)
{ {
@ -381,175 +422,136 @@ public class Properties extends Hashtable
return defaultValue; 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 * Returns an enumeration of all keys in this property list, including
* the keys in the default property list. * the keys in the default property list.
*
* @return an Enumeration of all defined keys
*/ */
public Enumeration propertyNames() public Enumeration propertyNames()
{ {
// We make a new Hashtable that holds all the keys. Then we // We make a new Set that holds all the keys, then return an enumeration
// return an enumeration for this hash. We do this because we // for that. This prevents modifications from ruining the enumeration,
// don't want modifications to be reflected in the enumeration // as well as ignoring duplicates.
// (per JCL), and because there doesn't seem to be a Properties prop = this;
// particularly better way to ensure that duplicates are Set s = new HashSet();
// ignored. // Eliminate tail recursion.
Hashtable t = new Hashtable(); do
addHashEntries(t);
return t.keys();
}
/**
* 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
*/
private String formatForOutput(String key, String value)
{ {
// This is a simple approximation of the expected line size. s.addAll(prop.keySet());
StringBuffer result = prop = prop.defaults;
new StringBuffer(key.length() + value.length() + 16);
boolean head = true;
for (int i = 0; i < key.length(); i++)
{
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 while (prop != null);
result.append(c); return Collections.enumeration(s);
}
if (c != 32)
head = false;
}
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 stream. They are
* written in the way, described in the method store. * written in the way described in the method store. This does not visit
* @param out the stream, where the key/value pairs are written to. * the keys in the default properties.
* @exception ClassCastException if this property contains any key or *
* value that isn't a string. * @param out the stream, where the key/value pairs are written to
* @see #store * @throws ClassCastException if this property contains any key or
* value that isn't a string
* @see #store(OutputStream, String)
*/ */
public void list(PrintStream out) public void list(PrintStream out)
{ {
Enumeration keys = keys(); Iterator iter = entrySet().iterator();
Enumeration elts = elements(); int i = size();
while (keys.hasMoreElements()) StringBuffer s = new StringBuffer(); // Reuse the same buffer.
while (--i >= 0)
{ {
String key = (String) keys.nextElement(); Map.Entry entry = (Map.Entry) iter.next();
String elt = (String) elts.nextElement(); formatForOutput((String) entry.getKey(), s, true);
String output = formatForOutput(key, elt); s.append('=');
out.println(output); formatForOutput((String) entry.getValue(), s, false);
out.println(s);
} }
} }
/** /**
* Writes the key/value pairs to the given print writer. They are * Writes the key/value pairs to the given print writer. They are
* written in the way, described in the method store. * 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 * @param out the writer, where the key/value pairs are written to
* value that isn't a string. * @throws ClassCastException if this property contains any key or
* @see #store * value that isn't a string
* @see #list(java.io.PrintStream) * @see #store(OutputStream, String)
* @since JDK1.1 * @see #list(PrintStream)
* @since 1.1
*/ */
public void list(PrintWriter out) public void list(PrintWriter out)
{ {
Enumeration keys = keys(); Iterator iter = entrySet().iterator();
Enumeration elts = elements(); int i = size();
while (keys.hasMoreElements()) StringBuffer s = new StringBuffer(); // Reuse the same buffer.
while (--i >= 0)
{ {
String key = (String) keys.nextElement(); Map.Entry entry = (Map.Entry) iter.next();
String elt = (String) elts.nextElement(); formatForOutput((String) entry.getKey(), s, true);
String output = formatForOutput(key, elt); s.append('=');
out.println(output); formatForOutput((String) entry.getValue(), s, false);
out.println(s);
} }
} }
}
/**
* Formats a key or value for output in a properties file.
* See store for a description of the format.
*
* @param str the string to format
* @param buffer the buffer to add it to
* @param key true if all ' ' must be escaped for the key, false if only
* leading spaces must be escaped for the value
* @see #store(OutputStream, String)
*/
private void formatForOutput(String str, StringBuffer buffer, boolean key)
{
if (key)
{
buffer.setLength(0);
buffer.ensureCapacity(str.length());
}
else
buffer.ensureCapacity(buffer.length() + str.length());
boolean head = true;
int size = str.length();
for (int i = 0; i < size; i++)
{
char c = str.charAt(i);
switch (c)
{
case '\n':
buffer.append("\\n");
break;
case '\r':
buffer.append("\\r");
break;
case '\t':
buffer.append("\\t");
break;
case ' ':
buffer.append(head ? "\\ " : " ");
break;
case '\\':
case '!':
case '#':
case '=':
case ':':
buffer.append('\\').append(c);
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

View file

@ -1,5 +1,5 @@
/* java.util.PropertyPermission /* PropertyPermission.java -- permission to get and set System properties
Copyright (C) 1999, 2000 Free Software Foundation, Inc. Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
@ -37,6 +37,7 @@ exception statement from your version. */
package java.util; package java.util;
import java.security.Permission; import java.security.Permission;
import java.security.BasicPermission; import java.security.BasicPermission;
import java.security.PermissionCollection; import java.security.PermissionCollection;
@ -49,9 +50,9 @@ import java.io.IOException;
* This class represents the permission to access and modify a property.<br> * 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 * 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: * two possible actions:
* <dl> * <dl>
* <dt>read</dt> * <dt>read</dt>
@ -64,120 +65,92 @@ import java.io.IOException;
* *
* @see Permission * @see Permission
* @see BasicPermission * @see BasicPermission
* @see SecurityManager
* @author Jochen Hoenicke * @author Jochen Hoenicke
* @since 1.2
* @status updated to 1.4
*/ */
public final class PropertyPermission extends BasicPermission public final class PropertyPermission extends BasicPermission
{ {
/** /**
* @serialField action String * PropertyPermission uses a more efficient representation than the
* The action string. * serialized form; this documents the difference.
*
* @serialField action String the action string
*/ */
private static final ObjectStreamField[] serialPersistentFields = private static final ObjectStreamField[] serialPersistentFields =
{ {
new ObjectStreamField("action", String.class) new ObjectStreamField("action", String.class)
}; };
/**
* Compatible with JDK 1.2+.
*/
private static final long serialVersionUID = 885438825399942851L; private static final long serialVersionUID = 885438825399942851L;
/** Permission to read. */
private static final int READ = 1; private static final int READ = 1;
/** Permission to write. */
private static final int WRITE = 2; 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[] = private static final String actionStrings[] =
{ {
"", "read", "write", "read,write" "", "read", "write", "read,write"
}; };
/** /**
* Constructs a PropertyPermission witha he specified property. Possible * Constructs a PropertyPermission with the specified property. Possible
* actions are read and write. * actions are read and write, comma-separated and case-insensitive.
* @param name the name of the property. *
* @param actions the action string. * @param name the name of the property
* @exception IllegalArgumentException if name string contains an * @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 * illegal wildcard or actions string contains an illegal action
* (this includes a null actions string)
*/ */
public PropertyPermission(String name, String actions) public PropertyPermission(String name, String actions)
{ {
super(name); super(name);
if (actions == null)
throw new IllegalArgumentException();
setActions(actions.toLowerCase()); setActions(actions.toLowerCase());
} }
/** /**
* Parse the action string and convert actions from external to internal * Parse the action string and convert actions from external to internal
* form. This will set the internal actions field. * 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)
{
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);
}
}
/**
* Check if this permission implies p. This returns true iff all of
* the following conditions are true:
* <ul>
* <li> p is a PropertyPermission </li>
* <li> this.getName() implies p.getName(),
* e.g. <code>java.*</code> implies <code>java.home</code> </li>
* <li> this.getActions is a subset of p.getActions </li>
* </ul>
*/
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];
}
/**
* Check to see whether this object is the same as another
* PropertyPermission object.
* *
* @param obj The other object * @param str the action string
* @throws IllegalArgumentException if actions string contains an
* illegal action
*/ */
public boolean equals (Object obj) private void setActions(String str)
{ {
if (! (obj instanceof PropertyPermission)) if ("read".equals(str))
return false; actions = READ;
PropertyPermission p = (PropertyPermission) obj; else if ("write".equals(str))
return actions == p.actions && super.equals (p); 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 * Reads an object from the stream. This converts the external to the
* internal representation. * 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) private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException throws IOException, ClassNotFoundException
@ -189,6 +162,9 @@ public final class PropertyPermission extends BasicPermission
/** /**
* Writes an object to the stream. This converts the internal to the * Writes an object to the stream. This converts the internal to the
* external representation. * external representation.
*
* @param s the stram to write to
* @throws IOException if the stream fails
*/ */
private void writeObject(ObjectOutputStream s) throws IOException private void writeObject(ObjectOutputStream s) throws IOException
{ {
@ -197,66 +173,75 @@ public final class PropertyPermission extends BasicPermission
s.writeFields(); s.writeFields();
} }
/**
* Check if this permission implies p. This returns true iff all of
* the following conditions are true:
* <ul>
* <li> p is a PropertyPermission </li>
* <li> this.getName() implies p.getName(),
* e.g. <code>java.*</code> implies <code>java.home</code> </li>
* <li> this.getActions is a subset of p.getActions </li>
* </ul>
*
* @param p the permission to check
* @return true if this permission implies p
*/
public boolean implies(Permission p)
{
// BasicPermission checks for name and type.
if (super.implies(p))
{
// We have to check the actions.
PropertyPermission pp = (PropertyPermission) p;
return (pp.actions & ~actions) == 0;
}
return false;
}
/**
* Check to see whether this object is the same as another
* PropertyPermission object; this is true if it has the same name and
* actions.
*
* @param obj the other object
* @return true if the two are equivalent
*/
public boolean equals(Object obj)
{
return super.equals(obj) && actions == ((PropertyPermission) obj).actions;
}
/**
* Returns the hash code for this permission. It is equivalent to
* <code>getName().hashCode()</code>.
*
* @return the hash code
*/
public int hashCode()
{
return super.hashCode();
}
/**
* Returns the action string. Note that this may differ from the string
* given at the constructor: The actions are converted to lowercase and
* may be reordered.
*
* @return one of "read", "write", or "read,write"
*/
public String getActions()
{
return actionStrings[actions];
}
/** /**
* Returns a permission collection suitable to take * Returns a permission collection suitable to take
* PropertyPermission objects. * PropertyPermission objects.
* @return a new empty PermissionCollection. *
* @return a new empty PermissionCollection
*/ */
public PermissionCollection newPermissionCollection() public PermissionCollection newPermissionCollection()
{ {
return new PermissionCollection() return new PropertyPermissionCollection();
{
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();
}
};
} }
} }

View file

@ -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();
}
}

View file

@ -1,5 +1,5 @@
/* java.util.PropertyResourceBundle /* PropertyResourceBundle -- a resource bundle built from a Property file
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
@ -38,6 +38,8 @@ exception statement from your version. */
package java.util; package java.util;
import java.io.IOException;
import java.io.InputStream;
import gnu.java.util.DoubleEnumeration; import gnu.java.util.DoubleEnumeration;
/** /**
@ -52,65 +54,57 @@ import gnu.java.util.DoubleEnumeration;
* file. * file.
* *
* If there is also a class for this resource and the same locale, the * If there is also a class for this resource and the same locale, the
* class does win. * 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
* The properties file should have the name of the resource bundle, * extension <code>.properties</code>. The file should have the same format
* 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> * 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 * 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 * 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;) * 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 ResourceBundle
* @see ListResourceBundle * @see ListResourceBundle
* @see Properties#load() * @see Properties#load()
* @author Jochen Hoenicke */ * @since 1.1
* @status updated to 1.4
*/
public class PropertyResourceBundle extends ResourceBundle public class PropertyResourceBundle extends ResourceBundle
{ {
Properties properties; /** The properties file this bundle is based on. */
private Properties properties;
/** /**
* Creates a new property resource bundle. * 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) public PropertyResourceBundle(InputStream stream) throws IOException
throws java.io.IOException
{ {
properties = new Properties(); properties = new Properties();
properties.load(stream); properties.load(stream);
@ -119,8 +113,9 @@ public class PropertyResourceBundle extends ResourceBundle
/** /**
* 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. * 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) 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. * 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() public Enumeration getKeys()
{ {
// We must also return the keys of our parent. if (parent == null)
if (parent != null)
{
return new DoubleEnumeration(properties.propertyNames(),
parent.getKeys());
}
return properties.propertyNames(); return properties.propertyNames();
// We make a new Set that holds all the keys, then return an enumeration
// for that. This prevents modifications from ruining the enumeration,
// as well as ignoring duplicates.
Set s = new HashSet();
Enumeration e = properties.propertyNames();
while (e.hasMoreElements())
s.add(e.nextElement());
ResourceBundle bundle = parent;
// Eliminate tail recursion.
do
{
e = bundle.getKeys();
while (e.hasMoreElements())
s.add(e.nextElement());
bundle = bundle.parent;
} }
} while (bundle != null);
return Collections.enumeration(s);
}
} // class PropertyResourceBundle

View file

@ -1,5 +1,5 @@
/* java.util.Random /* Random.java -- a pseudo-random number generator
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. This file is part of GNU Classpath.
@ -38,13 +38,16 @@ exception statement from your version. */
package java.util; package java.util;
import java.io.Serializable;
/** /**
* This class generates pseudorandom numbers. It uses the same * This class generates pseudorandom numbers. It uses the same
* algorithm as the original JDK-class, so that your programs behave * algorithm as the original JDK-class, so that your programs behave
* exactly the same way, if started with the same seed. * exactly the same way, if started with the same seed.
* *
* The algorithm is described in <em>The Art of Computer Programming, * 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 * 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 * the same calls to these classes are made, they behave exactly the
@ -66,51 +69,65 @@ package java.util;
* *
* @see java.security.SecureRandom * @see java.security.SecureRandom
* @see Math#random() * @see Math#random()
* @author Jochen Hoenicke */ * @author Jochen Hoenicke
public class Random implements java.io.Serializable * @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 * True if the next nextGaussian is available. This is used by
* nextGaussian, which generates two gaussian numbers by one call, * nextGaussian, which generates two gaussian numbers by one call,
* and returns the second on the second call. * and returns the second on the second call.
* @see #nextGaussian. */ *
* @serial whether nextNextGaussian is available
* @see #nextGaussian()
* @see #nextNextGaussian
*/
private boolean haveNextNextGaussian; 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 * which generates two gaussian numbers by one call, and returns the
* second on the second call. * second on the second call.
* @see #nextGaussian. *
* @serial the second gaussian of a pair
* @see #nextGaussian()
* @see #haveNextNextGaussian
*/ */
private double nextNextGaussian; private double nextNextGaussian;
/** /**
* The seed. This is the number set by setSeed and which is used * The seed. This is the number set by setSeed and which is used
* in next. * in next.
* @see #next *
* @serial the internal state of this generator
* @see #next()
*/ */
private long seed; private long seed;
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = 3905348978240129619L; private static final long serialVersionUID = 3905348978240129619L;
/** /**
* Creates a new pseudorandom number generator. The seed is initialized * Creates a new pseudorandom number generator. The seed is initialized
* to the current time as follows. * to the current time, as if by
* <pre> * <code>setSeed(System.currentTimeMillis());</code>.
* setSeed(System.currentTimeMillis()); *
* </pre>
* @see System#currentTimeMillis() * @see System#currentTimeMillis()
*/ */
public Random() public Random()
{ {
setSeed(System.currentTimeMillis()); this(System.currentTimeMillis());
} }
/** /**
* Creates a new pseudorandom number generator, starting with the * Creates a new pseudorandom number generator, starting with the
* specified seed. This does: * specified seed, using <code>setSeed(seed);</code>.
* <pre> *
* setSeed(seed); * @param seed the initial seed
* </pre>
* @param seed the initial seed.
*/ */
public Random(long 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 * above, two instances of the same random class, starting with the
* same seed, should produce the same results, if the same methods * same seed, should produce the same results, if the same methods
* are called. The implementation for java.util.Random is: * are called. The implementation for java.util.Random is:
* <pre> *
* public synchronized void setSeed(long seed) { <pre>public synchronized void setSeed(long seed)
* this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1); {
* haveNextNextGaussian = false; this.seed = (seed ^ 0x5DEECE66DL) & ((1L &lt;&lt; 48) - 1);
* } haveNextNextGaussian = false;
* </pre> }</pre>
*
* @param seed the new seed
*/ */
public synchronized void setSeed(long 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 * an int value whose <code>bits</code> low order bits are
* independent chosen random bits (0 and 1 are equally likely). * independent chosen random bits (0 and 1 are equally likely).
* The implementation for java.util.Random is: * The implementation for java.util.Random is:
* <pre> *
* protected synchronized int next(int bits) { <pre>protected synchronized int next(int bits)
* seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1); {
* return (int) (seed >>> (48 - bits)); seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L &lt;&lt; 48) - 1);
* } return (int) (seed &gt;&gt;&gt; (48 - bits));
* </pre> }</pre>
* @param bits the number of random bits to generate. Must be in range *
* 1..32. * @param bits the number of random bits to generate, in the range 1..32
* @return the next pseudorandom value. * @return the next pseudorandom value
* @since JDK1.1 * @since 1.1
*/ */
protected synchronized int next(int bits) 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); seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int) (seed >>> (48 - bits)); return (int) (seed >>> (48 - bits));
@ -163,25 +180,28 @@ public class Random implements java.io.Serializable
* Fills an array of bytes with random numbers. All possible values * Fills an array of bytes with random numbers. All possible values
* are (approximately) equally likely. * are (approximately) equally likely.
* The JDK documentation gives no implementation, but it seems to be: * The JDK documentation gives no implementation, but it seems to be:
* <pre> *
* public void nextBytes(byte[] bytes) { <pre>public void nextBytes(byte[] bytes)
* for (int i=0; i< bytes.length; i+=4) { {
* int random = next(32); for (int i = 0; i &lt; bytes.length; i += 4)
* for (int j=0; i+j< bytes.length && j<4; j++) {
* bytes[i+j] = (byte) (random & 0xff) int random = next(32);
* random >>= 8; 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. }
* @since JDK1.1 }</pre>
*
* @param bytes the byte array that should be filled
* @throws NullPointerException if bytes is null
* @since 1.1
*/ */
public void nextBytes(byte[] bytes) public void nextBytes(byte[] bytes)
/*{ require { bytes != null :: "bytes is null"; } } */
{ {
int random; 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; int max = bytes.length & ~0x3;
for (int i = 0; i < max; i += 4) for (int i = 0; i < max; i += 4)
{ {
@ -207,13 +227,14 @@ public class Random implements java.io.Serializable
* an int value whose 32 bits are independent chosen random bits * an int value whose 32 bits are independent chosen random bits
* (0 and 1 are equally likely). The implementation for * (0 and 1 are equally likely). The implementation for
* java.util.Random is: * java.util.Random is:
* <pre>
* public int nextInt() {
* return next(32);
* }
* </pre>
* *
* @return the next pseudorandom value. */ <pre>public int nextInt()
{
return next(32);
}</pre>
*
* @return the next pseudorandom value
*/
public int nextInt() public int nextInt()
{ {
return next(32); return next(32);
@ -225,21 +246,28 @@ public class Random implements java.io.Serializable
* each value has the same likelihodd (1/<code>n</code>). * each value has the same likelihodd (1/<code>n</code>).
* (0 and 1 are equally likely). The implementation for * (0 and 1 are equally likely). The implementation for
* java.util.Random is: * java.util.Random is:
* <pre> *
* public int nextInt(int n) { <pre>
* if (n<=0) public int nextInt(int n)
* throw new IllegalArgumentException("n must be positive"); {
* if ((n & -n) == n) // i.e., n is a power of 2 if (n &lt;= 0)
* return (int)((n * (long)next(31)) >> 31); throw new IllegalArgumentException("n must be positive");
* int bits, val;
* do { if ((n & -n) == n) // i.e., n is a power of 2
* bits = next(32); return (int)((n * (long) next(31)) &gt;&gt; 31);
* val = bits % n;
* } while(bits - val + (n-1) < 0); int bits, val;
* return val; do
* } {
* </pre> bits = next(32);
* This algorithm would return every value with exactly the same 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 * probability, if the next()-method would be a perfect random number
* generator. * generator.
* *
@ -254,12 +282,12 @@ public class Random implements java.io.Serializable
* 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. * ``less random'' than the high order bits.
* *
* @param n the upper bound. * @param n the upper bound
* @exception IllegalArgumentException if the given upper bound is negative * @throws IllegalArgumentException if the given upper bound is negative
* @return the next pseudorandom value. * @return the next pseudorandom value
* @since 1.2
*/ */
public int nextInt(int n) public int nextInt(int n)
/*{ require { n > 0 :: "n must be positive"; } } */
{ {
if (n <= 0) if (n <= 0)
throw new IllegalArgumentException("n must be positive"); throw new IllegalArgumentException("n must be positive");
@ -279,12 +307,13 @@ public class Random implements java.io.Serializable
* Generates the next pseudorandom long number. All bits of this * Generates the next pseudorandom long number. All bits of this
* long are independently chosen and 0 and 1 have equal likelihood. * long are independently chosen and 0 and 1 have equal likelihood.
* The implementation for java.util.Random is: * The implementation for java.util.Random is:
* <pre> *
* public long nextLong() { <pre>public long nextLong()
* return ((long)next(32) << 32) + next(32); {
* } return ((long) next(32) &lt;&lt; 32) + next(32);
* </pre> }</pre>
* @return the next pseudorandom value. *
* @return the next pseudorandom value
*/ */
public long nextLong() public long nextLong()
{ {
@ -294,12 +323,14 @@ public class Random implements java.io.Serializable
/** /**
* Generates the next pseudorandom boolean. True and false have * Generates the next pseudorandom boolean. True and false have
* the same probability. The implementation is: * the same probability. The implementation is:
* <pre> *
* public boolean nextBoolean() { <pre>public boolean nextBoolean()
* return next(1) != 0; {
* } return next(1) != 0;
* </pre> }</pre>
* @return the next pseudorandom boolean. *
* @return the next pseudorandom boolean
* @since 1.2
*/ */
public boolean nextBoolean() public boolean nextBoolean()
{ {
@ -308,29 +339,33 @@ public class Random implements java.io.Serializable
/** /**
* Generates the next pseudorandom float uniformly distributed * 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. * implementation is as follows.
* <pre> *
* public float nextFloat() { <pre>public float nextFloat()
* return next(24) / ((float)(1 << 24)); {
* } return next(24) / ((float)(1 &lt;&lt; 24));
* </pre> }</pre>
* @return the next pseudorandom float. */ *
* @return the next pseudorandom float
*/
public float nextFloat() public float nextFloat()
{ {
return next(24) / ((float) (1 << 24)); return next(24) / (float) (1 << 24);
} }
/** /**
* Generates the next pseudorandom double uniformly distributed * 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. * implementation is as follows.
* <pre> *
* public double nextDouble() { <pre>public double nextDouble()
* return (((long)next(26) << 27) + next(27)) / (double)(1 << 53); {
* } return (((long) next(26) &lt;&lt; 27) + next(27)) / (double)(1L &lt;&lt; 53);
* </pre> }</pre>
* @return the next pseudorandom double. */ *
* @return the next pseudorandom double
*/
public double nextDouble() public double nextDouble()
{ {
return (((long) next(26) << 27) + next(27)) / (double) (1L << 53); return (((long) next(26) << 27) + next(27)) / (double) (1L << 53);
@ -340,32 +375,9 @@ public class Random implements java.io.Serializable
* 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. * double value, with mean 0.0 and standard deviation 1.0.
* The algorithm is as follows. * 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
* Programming, Volume 2</em> by Donald Knuth.
* *
* @return the next pseudorandom Gaussian distributed double. <pre>public synchronized double nextGaussian()
*/ {
public synchronized double nextGaussian()
{
if (haveNextNextGaussian) if (haveNextNextGaussian)
{ {
haveNextNextGaussian = false; haveNextNextGaussian = false;
@ -381,10 +393,37 @@ public class Random implements java.io.Serializable
s = v1 * v1 + v2 * v2; s = v1 * v1 + v2 * v2;
} }
while (s >= 1); while (s >= 1);
double norm = Math.sqrt(-2 * Math.log(s) / s); double norm = Math.sqrt(-2 * Math.log(s) / s);
nextNextGaussian = v2 * norm; nextNextGaussian = v2 * norm;
haveNextNextGaussian = true; haveNextNextGaussian = true;
return v1 * norm; return v1 * norm;
} }
}</pre>
*
* <p>This is described in section 3.4.1 of <em>The Art of Computer
* Programming, Volume 2</em> by Donald Knuth.
*
* @return the next pseudorandom Gaussian distributed double
*/
public synchronized double nextGaussian()
{
if (haveNextNextGaussian)
{
haveNextNextGaussian = false;
return nextNextGaussian;
}
double v1, v2, s;
do
{
v1 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
v2 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
s = v1 * v1 + v2 * v2;
}
while (s >= 1);
double norm = Math.sqrt(-2 * Math.log(s) / s);
nextNextGaussian = v2 * norm;
haveNextNextGaussian = true;
return v1 * norm;
} }
} }

View file

@ -52,7 +52,8 @@ import java.text.DateFormatSymbols;
* *
* @see Calendar * @see Calendar
* @see GregorianCalender * @see GregorianCalender
* @author Jochen Hoenicke */ * @author Jochen Hoenicke
*/
public class SimpleTimeZone extends TimeZone 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 * 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. * inaccurate results at the end of February or the beginning of March.
* To avoid this, you should use Calendar instead: * To avoid this, you should use Calendar instead:
* <pre> * <code>offset = cal.get(Calendar.ZONE_OFFSET)
* offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); * + cal.get(Calendar.DST_OFFSET);</code>
* </pre> *
* You could also use in * You could also use in
* *
* This version doesn't suffer this inaccuracy. * This version doesn't suffer this inaccuracy.

View file

@ -1,5 +1,5 @@
/* java.util.StringTokenizer /* StringTokenizer -- breaks a String into tokens
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath. This file is part of GNU Classpath.
@ -41,58 +41,63 @@ 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 * 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 * nextToken(String). But the semantic is quite difficult; it even
* depends on calling <code>hasMoreTokens()</code>. You should call * depends on calling <code>hasMoreTokens()</code>. You should call
* <code>hasMoreTokens()</code> before, otherwise the old delimiters * <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 * constructor. The delimiters are returned as token consisting of a
* single character. * single character.
* *
* @author Jochen Hoenicke * @author Jochen Hoenicke
* @author Warren Levy <warrenl@cygnus.com> * @author Warren Levy <warrenl@cygnus.com>
* @see java.io.StreamTokenizer
* @status updated to 1.4
*/ */
public class StringTokenizer implements Enumeration 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. * The position in the str, where we currently are.
*/ */
private int pos; private int pos;
/** /**
* The string that should be split into tokens. * 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. * The string containing the delimiter characters.
*/ */
private String delim; private String delim;
/** /**
* Tells, if we should return the delimiters. * Tells, if we should return the delimiters.
*/ */
private boolean retDelims; private final 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";
}
} */
/** /**
* Creates a new StringTokenizer for the string <code>str</code>, * 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 * newline, return and formfeed), and which doesn't return the
* delimiters. * delimiters.
* @param str The string to split. *
* @param str The string to split
* @throws NullPointerException if str is null
*/ */
public StringTokenizer(String str) public StringTokenizer(String str)
/*{ require { str != null :: "str must not be null"; } } */
{ {
this(str, " \t\n\r\f", false); this(str, " \t\n\r\f", false);
} }
@ -102,12 +107,11 @@ public class StringTokenizer implements Enumeration
* the given delimiter characters. It doesn't return the delimiter * the given delimiter characters. It doesn't return the delimiter
* characters. * characters.
* *
* @param str The string to split. * @param str the string to split
* @param delim A string containing all delimiter characters. * @param delim a string containing all delimiter characters
* @throws NullPointerException if either argument is null
*/ */
public StringTokenizer(String str, String delim) 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); this(str, delim, false);
} }
@ -119,34 +123,34 @@ public class StringTokenizer implements Enumeration
* characters are returned as tokens of their own. The delimiter * characters are returned as tokens of their own. The delimiter
* tokens always consist of a single character. * tokens always consist of a single character.
* *
* @param str The string to split. * @param str the string to split
* @param delim A string containing all delimiter characters. * @param delim a string containing all delimiter characters
* @param returnDelims Tells, if you want to get the delimiters. * @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) 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.str = str;
this.delim = delim; // The toString() hack causes the NullPointerException.
this.delim = delim.toString();
this.retDelims = returnDelims; this.retDelims = returnDelims;
this.pos = 0; this.pos = 0;
} }
/** /**
* Tells if there are more tokens. * 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() public boolean hasMoreTokens()
{ {
if (!retDelims) if (! retDelims)
{
while (pos < str.length() && delim.indexOf(str.charAt(pos)) > -1)
{ {
while (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
pos++; pos++;
} }
} return pos < len;
return pos < str.length();
} }
/** /**
@ -154,13 +158,13 @@ public class StringTokenizer implements Enumeration
* <code>delim</code>. The change of the delimiter set is * <code>delim</code>. The change of the delimiter set is
* permanent, ie. the next call of nextToken(), uses the same * permanent, ie. the next call of nextToken(), uses the same
* delimiter set. * delimiter set.
* @param delim a string containing the new delimiter characters. *
* @return the next token with respect to the new delimiter characters. * @param delim a string containing the new delimiter characters
* @exception NoSuchElementException if there are no more tokens. * @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 public String nextToken(String delim) throws NoSuchElementException
/*{ require { hasMoreTokens() :: "no more Tokens available";
ensure { $return != null && $return.length() > 0; } } */
{ {
this.delim = delim; this.delim = delim;
return nextToken(); return nextToken();
@ -168,31 +172,23 @@ public class StringTokenizer implements Enumeration
/** /**
* Returns the nextToken of the string. * 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. * @return the next token with respect to the current delimiter characters
* @exception NoSuchElementException if there are no more tokens. * @throws NoSuchElementException if there are no more tokens
*/ */
public String nextToken() throws NoSuchElementException 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) if (retDelims)
return str.substring(pos, ++pos); return str.substring(pos, ++pos);
while (++pos < len && delim.indexOf(str.charAt(pos)) >= 0);
while (++pos < str.length() && delim.indexOf(str.charAt(pos)) > -1)
{
/* empty */
} }
} if (pos < len)
if (pos < str.length())
{ {
int start = pos; int start = pos;
while (++pos < str.length() && delim.indexOf(str.charAt(pos)) == -1) while (++pos < len && delim.indexOf(str.charAt(pos)) < 0);
{
/* empty */
}
return str.substring(start, pos); return str.substring(start, pos);
} }
throw new NoSuchElementException(); throw new NoSuchElementException();
@ -201,9 +197,9 @@ public class StringTokenizer implements Enumeration
/** /**
* This does the same as hasMoreTokens. This is the * This does the same as hasMoreTokens. This is the
* <code>Enumeration</code interface method. * <code>Enumeration</code interface method.
* @return True, if the next call of nextElement() succeeds, false *
* otherwise. * @return true, if the next call of nextElement() will succeed
* @see #hasMoreTokens * @see #hasMoreTokens()
*/ */
public boolean hasMoreElements() public boolean hasMoreElements()
{ {
@ -213,9 +209,10 @@ public class StringTokenizer implements Enumeration
/** /**
* This does the same as nextTokens. This is the * This does the same as nextTokens. This is the
* <code>Enumeration</code interface method. * <code>Enumeration</code interface method.
* @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
* @see #nextToken * @throws NoSuchElementException if there are no more tokens
* @see #nextToken()
*/ */
public Object nextElement() throws NoSuchElementException public Object nextElement() throws NoSuchElementException
{ {
@ -225,9 +222,9 @@ public class StringTokenizer implements Enumeration
/** /**
* This counts the number of remaining tokens in the string, with * This counts the number of remaining tokens in the string, with
* respect to the current delimiter set. * respect to the current delimiter set.
* @return the number of times <code>nextTokens()</code> will *
* succeed. * @return the number of times <code>nextTokens()</code> will succeed
* @see #nextToken * @see #nextToken()
*/ */
public int countTokens() public int countTokens()
{ {
@ -239,9 +236,9 @@ public class StringTokenizer implements Enumeration
// Note for efficiency, we count up the delimiters rather than check // Note for efficiency, we count up the delimiters rather than check
// retDelims every time we encounter one. That way, we can // retDelims every time we encounter one. That way, we can
// just do the conditional once at the end of the method // 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 (delim.indexOf(str.charAt(tmpPos++)) >= 0)
{ {
if (tokenFound) if (tokenFound)
{ {
@ -249,16 +246,14 @@ public class StringTokenizer implements Enumeration
count++; count++;
tokenFound = false; tokenFound = false;
} }
delimiterCount++; // Increment for this delimiter delimiterCount++; // Increment for this delimiter
} }
else else
{ {
tokenFound = true; tokenFound = true;
// Get to the end of the token // Get to the end of the token
while (tmpPos < str.length() while (tmpPos < len
&& delim.indexOf(str.charAt(tmpPos)) == -1) && delim.indexOf(str.charAt(tmpPos)) < 0)
++tmpPos; ++tmpPos;
} }
} }
@ -270,4 +265,4 @@ public class StringTokenizer implements Enumeration
// if counting delmiters add them into the token count // if counting delmiters add them into the token count
return retDelims ? count + delimiterCount : count; return retDelims ? count + delimiterCount : count;
} }
} } // class StringTokenizer

View file

@ -44,11 +44,11 @@ package java.util;
* it should have been scheduled and cancel itself when no longer needed. * it should have been scheduled and cancel itself when no longer needed.
* <p> * <p>
* Example: * Example:
* <code> * <pre>
* Timer timer = new Timer(); * Timer timer = new Timer();
* TimerTask task = new TimerTask() { * TimerTask task = new TimerTask() {
* public void run() { * public void run() {
* if (this.scheduledExecutionTime() < System.currentTimeMillis() + 500) * if (this.scheduledExecutionTime() &lt; System.currentTimeMillis() + 500)
* // Do something * // Do something
* else * else
* // Complain: We are more then half a second late! * // Complain: We are more then half a second late!
@ -56,7 +56,7 @@ package java.util;
* this.cancel(); // This was our last execution * this.cancel(); // This was our last execution
* }; * };
* timer.scheduleAtFixedRate(task, 1000, 1000); // schedule every second * timer.scheduleAtFixedRate(task, 1000, 1000); // schedule every second
* </code> * </pre>
* <p> * <p>
* Note that a TimerTask object is a one shot object and can only given once * 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, * to a Timer. (The Timer will use the TimerTask object for bookkeeping,

View file

@ -1,6 +1,6 @@
/* TreeMap.java -- a class providing a basic Red-Black Tree data structure, /* TreeMap.java -- a class providing a basic Red-Black Tree data structure,
mapping Object --> Object 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. This file is part of GNU Classpath.
@ -162,7 +162,7 @@ public class TreeMap extends AbstractMap
* *
* @author Eric Blake <ebb9@email.byu.edu> * @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. // All fields package visible for use by nested classes.
/** The color of this node. */ /** The color of this node. */
@ -623,8 +623,10 @@ public class TreeMap extends AbstractMap
Node n = getNode(key); Node n = getNode(key);
if (n == nil) if (n == nil)
return null; return null;
// Note: removeNode can alter the contents of n, so save value now.
Object result = n.value;
removeNode(n); removeNode(n);
return n.value; return result;
} }
/** /**
@ -1768,7 +1770,7 @@ public class TreeMap extends AbstractMap
SubMap.this.clear(); SubMap.this.clear();
} }
}; };
return this.keys; return this.values;
} }
} // class SubMap } // class SubMap
} // class TreeMap } // class TreeMap

View file

@ -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 to its keys, allowing the virtual machine to reclaim them
Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
@ -43,41 +43,41 @@ import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue; import java.lang.ref.ReferenceQueue;
/** /**
* A weak hash map has only weak references to the key. This means * A weak hash map has only weak references to the key. This means that it
* that it allows the key to be garbage collected if they are not used * allows the key to be garbage collected if it is not used otherwise. If
* otherwise. If this happens, the weak hash map will eventually * this happens, the entry will eventually disappear from the map,
* remove the whole entry from this map. <br> * asynchronously.
* *
* A weak hash map makes most sense, if the keys doesn't override 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 * <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 * 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> * can be removed. This table also works when the <code>equals</code>
* method is overloaded, e.g. with Strings as keys, but you should be * method is overloaded, such as String keys, but you should be prepared
* prepared that some entries disappear spontaneously. <br> * to deal with some entries disappearing spontaneously.
* *
* You should also be prepared that this hash map behaves very * <p>Other strange behaviors to be aware of: The size of this map may
* strange: The size of this map may spontaneously shrink (even if you * spontaneously shrink (even if you use a synchronized map and synchronize
* use a synchronized map and synchronize it); it behaves as if * it); it behaves as if another thread removes entries from this table
* another thread removes entries from this table without * without synchronization. The entry set returned by <code>entrySet</code>
* synchronizations. The entry set returned by <code>entrySet</code>
* has similar phenomenons: The size may spontaneously shrink, or an * 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 * <p>A weak hash map is not meant for caches; use a normal map, with
* soft references as values instead, or try {@link LinkedHashMap}. <br> * soft references as values instead, or try {@link LinkedHashMap}.
* *
* The weak hash map supports null values and null keys. The null key * <p>The weak hash map supports null values and null keys. The null key
* is never deleted from the map (except explictly of course). * is never deleted from the map (except explictly of course). The
* The performance of the methods are similar to that of a hash map. <br> * 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 * value object maintains a strong reference to the key (either direct
* or indirect) the key will never be removed from this map. According * 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 * 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. * possible to do it with the jdk 1.2 reference model, though.
* *
* @author Jochen Hoenicke * @author Jochen Hoenicke
* @author Eric Blake <ebb9@email.byu.edu> * @author Eric Blake (ebb9@email.byu.edu)
*
* @see HashMap * @see HashMap
* @see WeakReference * @see WeakReference
* @see LinkedHashMap * @see LinkedHashMap
@ -86,6 +86,9 @@ import java.lang.ref.ReferenceQueue;
*/ */
public class WeakHashMap extends AbstractMap implements Map 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. * The default capacity for an instance of HashMap.
* Sun's documentation mildly suggests that this (11) is the correct * 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 rounded product of the capacity (i.e. number of buckets) and
* the load factor. When the number of elements exceeds the * 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; private int threshold;
@ -364,11 +367,11 @@ public class WeakHashMap extends AbstractMap implements Map
/** /**
* The slot of this entry. This should be * The slot of this entry. This should be
* <pre> * <code>Math.abs(key.hashCode() % buckets.length)</code>.
* Math.abs(key.hashCode() % buckets.length) *
* </pre>
* But since the key may be silently removed we have to remember * But since the key may be silently removed we have to remember
* the slot number. * the slot number.
*
* If this bucket was removed the slot is -1. This marker will * If this bucket was removed the slot is -1. This marker will
* prevent the bucket from being removed twice. * prevent the bucket from being removed twice.
*/ */
@ -503,9 +506,10 @@ public class WeakHashMap extends AbstractMap implements Map
private final WeakEntrySet theEntrySet; 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 * 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 * 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. * @param bucket the bucket to remove.
*/ */
private void internalRemove(WeakBucket bucket) void internalRemove(WeakBucket bucket)
{ {
int slot = bucket.slot; int slot = bucket.slot;
if (slot == -1) if (slot == -1)
@ -870,4 +876,4 @@ public class WeakHashMap extends AbstractMap implements Map
cleanQueue(); cleanQueue();
return super.values(); return super.values();
} }
} } // class WeakHashMap

View file

@ -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 * @returns the old value of the attribute name or null if it didn't exist
* yet * yet
*/ */
private String putValue(Name name, String value) String putValue(Name name, String value)
{ {
return (String) put(name, value); return (String) put(name, value);
} }

View file

@ -1,5 +1,5 @@
/* Attributes.java -- exception thrown to indicate an problem with a jar file /* JarException.java -- thrown to indicate an problem with a jar file
Copyright (C) 2000 Free Software Foundation, Inc. Copyright (C) 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath. 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. * 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 * 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 * to throw this exception, most just declare that they throw an IOException
* which is super class of JarException. * which is super class of JarException.
* *
* @since 1.2
* @author Mark Wielaard (mark@klomp.org) * @author Mark Wielaard (mark@klomp.org)
* @since 1.2
*/ */
public class JarException extends ZipException 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. * Create a new JarException without a descriptive error message.
*/ */
public JarException() public JarException()
{ {
super();
} }
/** /**
* Create a new JarException with a descriptive error message indicating * Create a new JarException with a descriptive error message indicating
* what went wrong. This message can later be retrieved by calling the * what went wrong. This message can later be retrieved by calling the
* <code>getMessage()</code> method. * <code>getMessage()</code> method.
* @see java.lang.Throwable@getMessage()
* *
* @param message The descriptive error message * @param message The descriptive error message
* @see #getMessage()
*/ */
public JarException(String message) public JarException(String message)
{ {

View file

@ -174,10 +174,19 @@ public class Manifest implements Cloneable
private static void read_main_section(Attributes attr, private static void read_main_section(Attributes attr,
BufferedReader br) throws IOException 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); 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, private static void read_version_info(Attributes attr,
BufferedReader br) throws IOException BufferedReader br) throws IOException
{ {
@ -185,7 +194,7 @@ public class Manifest implements Cloneable
try try
{ {
String value = expect_header(version_header, br); String value = expect_header(version_header, br);
attr.putValue(version_header, value); attr.putValue(Attributes.Name.MANIFEST_VERSION, value);
} }
catch (IOException ioe) catch (IOException ioe)
{ {