Major merge with Classpath.

Removed many duplicate files.
	* HACKING: Updated.x
	* classpath: Imported new directory.
	* standard.omit: New file.
	* Makefile.in, aclocal.m4, configure: Rebuilt.
	* sources.am: New file.
	* configure.ac: Run Classpath configure script.  Moved code around
	to support.  Disable xlib AWT peers (temporarily).
	* Makefile.am (SUBDIRS): Added 'classpath'
	(JAVAC): Removed.
	(AM_CPPFLAGS): Added more -I options.
	(BOOTCLASSPATH): Simplified.
	Completely redid how sources are built.
	Include sources.am.
	* include/Makefile.am (tool_include__HEADERS): Removed jni.h.
	* include/jni.h: Removed (in Classpath).
	* scripts/classes.pl: Updated to look at built classes.
	* scripts/makemake.tcl: New file.
	* testsuite/libjava.jni/jni.exp (gcj_jni_compile_c_to_so): Added
	-I options.
	(gcj_jni_invocation_compile_c_to_binary): Likewise.

From-SVN: r102082
This commit is contained in:
Tom Tromey
2005-07-16 01:27:14 +00:00
committed by Tom Tromey
parent ea54b29342
commit b0fa81eea9
2817 changed files with 11656 additions and 643398 deletions
-470
View File
@@ -1,470 +0,0 @@
/* AbstractCollection.java -- Abstract implementation of most of Collection
Copyright (C) 1998, 2000, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.lang.reflect.Array;
/**
* A basic implementation of most of the methods in the Collection interface to
* make it easier to create a collection. To create an unmodifiable Collection,
* just subclass AbstractCollection and provide implementations of the
* iterator() and size() methods. The Iterator returned by iterator() need only
* provide implementations of hasNext() and next() (that is, it may throw an
* UnsupportedOperationException if remove() is called). To create a modifiable
* Collection, you must in addition provide an implementation of the
* add(Object) method and the Iterator returned by iterator() must provide an
* implementation of remove(). Other methods should be overridden if the
* backing data structure allows for a more efficient implementation. The
* precise implementation used by AbstractCollection is documented, so that
* subclasses can tell which methods could be implemented more efficiently.
* <p>
*
* The programmer should provide a no-argument constructor, and one that
* accepts another Collection, as recommended by the Collection interface.
* Unfortunately, there is no way to enforce this in Java.
*
* @author Original author unknown
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see AbstractSet
* @see AbstractList
* @since 1.2
* @status updated to 1.4
*/
public abstract class AbstractCollection implements Collection
{
/**
* The main constructor, for use by subclasses.
*/
protected AbstractCollection()
{
}
/**
* Return an Iterator over this collection. The iterator must provide the
* hasNext and next methods and should in addition provide remove if the
* collection is modifiable.
*
* @return an iterator
*/
public abstract Iterator iterator();
/**
* Return the number of elements in this collection. If there are more than
* Integer.MAX_VALUE elements, return Integer.MAX_VALUE.
*
* @return the size
*/
public abstract int size();
/**
* Add an object to the collection (optional operation). This implementation
* always throws an UnsupportedOperationException - it should be
* overridden if the collection is to be modifiable. If the collection
* does not accept duplicates, simply return false. Collections may specify
* limitations on what may be added.
*
* @param o the object to add
* @return true if the add operation caused the Collection to change
* @throws UnsupportedOperationException if the add operation is not
* supported on this collection
* @throws NullPointerException if the collection does not support null
* @throws ClassCastException if the object is of the wrong type
* @throws IllegalArgumentException if some aspect of the object prevents
* it from being added
*/
public boolean add(Object o)
{
throw new UnsupportedOperationException();
}
/**
* Add all the elements of a given collection to this collection (optional
* operation). This implementation obtains an Iterator over the given
* collection and iterates over it, adding each element with the
* add(Object) method (thus this method will fail with an
* UnsupportedOperationException if the add method does). The behavior is
* unspecified if the specified collection is modified during the iteration,
* including the special case of trying addAll(this) on a non-empty
* collection.
*
* @param c the collection to add the elements of to this collection
* @return true if the add operation caused the Collection to change
* @throws UnsupportedOperationException if the add operation is not
* supported on this collection
* @throws NullPointerException if the specified collection is null
* @throws ClassCastException if the type of any element in c is
* not a valid type for addition.
* @throws IllegalArgumentException if some aspect of any element
* in c prevents it being added.
* @throws NullPointerException if any element in c is null and this
* collection doesn't allow null values.
* @see #add(Object)
*/
public boolean addAll(Collection c)
{
Iterator itr = c.iterator();
boolean modified = false;
int pos = c.size();
while (--pos >= 0)
modified |= add(itr.next());
return modified;
}
/**
* Remove all elements from the collection (optional operation). This
* implementation obtains an iterator over the collection and calls next
* and remove on it repeatedly (thus this method will fail with an
* UnsupportedOperationException if the Iterator's remove method does)
* until there are no more elements to remove.
* Many implementations will have a faster way of doing this.
*
* @throws UnsupportedOperationException if the Iterator returned by
* iterator does not provide an implementation of remove
* @see Iterator#remove()
*/
public void clear()
{
Iterator itr = iterator();
int pos = size();
while (--pos >= 0)
{
itr.next();
itr.remove();
}
}
/**
* Test whether this collection contains a given object. That is, if the
* collection has an element e such that (o == null ? e == null :
* o.equals(e)). This implementation obtains an iterator over the collection
* and iterates over it, testing each element for equality with the given
* object. If it is equal, true is returned. Otherwise false is returned when
* the end of the collection is reached.
*
* @param o the object to remove from this collection
* @return true if this collection contains an object equal to o
*/
public boolean contains(Object o)
{
Iterator itr = iterator();
int pos = size();
while (--pos >= 0)
if (equals(o, itr.next()))
return true;
return false;
}
/**
* Tests whether this collection contains all the elements in a given
* collection. This implementation iterates over the given collection,
* testing whether each element is contained in this collection. If any one
* is not, false is returned. Otherwise true is returned.
*
* @param c the collection to test against
* @return true if this collection contains all the elements in the given
* collection
* @throws NullPointerException if the given collection is null
* @see #contains(Object)
*/
public boolean containsAll(Collection c)
{
Iterator itr = c.iterator();
int pos = c.size();
while (--pos >= 0)
if (!contains(itr.next()))
return false;
return true;
}
/**
* Test whether this collection is empty. This implementation returns
* size() == 0.
*
* @return true if this collection is empty.
* @see #size()
*/
public boolean isEmpty()
{
return size() == 0;
}
/**
* Remove a single instance of an object from this collection (optional
* operation). That is, remove one element e such that
* <code>(o == null ? e == null : o.equals(e))</code>, if such an element
* exists. This implementation obtains an iterator over the collection
* and iterates over it, testing each element for equality with the given
* object. If it is equal, it is removed by the iterator's remove method
* (thus this method will fail with an UnsupportedOperationException if
* the Iterator's remove method does). After the first element has been
* removed, true is returned; if the end of the collection is reached, false
* is returned.
*
* @param o the object to remove from this collection
* @return true if the remove operation caused the Collection to change, or
* equivalently if the collection did contain o.
* @throws UnsupportedOperationException if this collection's Iterator
* does not support the remove method
* @see Iterator#remove()
*/
public boolean remove(Object o)
{
Iterator itr = iterator();
int pos = size();
while (--pos >= 0)
if (equals(o, itr.next()))
{
itr.remove();
return true;
}
return false;
}
/**
* Remove from this collection all its elements that are contained in a given
* collection (optional operation). This implementation iterates over this
* collection, and for each element tests if it is contained in the given
* collection. If so, it is removed by the Iterator's remove method (thus
* this method will fail with an UnsupportedOperationException if the
* Iterator's remove method does).
*
* @param c the collection to remove the elements of
* @return true if the remove operation caused the Collection to change
* @throws UnsupportedOperationException if this collection's Iterator
* does not support the remove method
* @throws NullPointerException if the collection, c, is null.
* @see Iterator#remove()
*/
public boolean removeAll(Collection c)
{
return removeAllInternal(c);
}
/**
* Remove from this collection all its elements that are contained in a given
* collection (optional operation). This implementation iterates over this
* collection, and for each element tests if it is contained in the given
* collection. If so, it is removed by the Iterator's remove method (thus
* this method will fail with an UnsupportedOperationException if the
* Iterator's remove method does). This method is necessary for ArrayList,
* which cannot publicly override removeAll but can optimize this call.
*
* @param c the collection to remove the elements of
* @return true if the remove operation caused the Collection to change
* @throws UnsupportedOperationException if this collection's Iterator
* does not support the remove method
* @throws NullPointerException if the collection, c, is null.
* @see Iterator#remove()
*/
// Package visible for use throughout java.util.
boolean removeAllInternal(Collection c)
{
Iterator itr = iterator();
boolean modified = false;
int pos = size();
while (--pos >= 0)
if (c.contains(itr.next()))
{
itr.remove();
modified = true;
}
return modified;
}
/**
* Remove from this collection all its elements that are not contained in a
* given collection (optional operation). This implementation iterates over
* this collection, and for each element tests if it is contained in the
* given collection. If not, it is removed by the Iterator's remove method
* (thus this method will fail with an UnsupportedOperationException if
* the Iterator's remove method does).
*
* @param c the collection to retain the elements of
* @return true if the remove operation caused the Collection to change
* @throws UnsupportedOperationException if this collection's Iterator
* does not support the remove method
* @throws NullPointerException if the collection, c, is null.
* @see Iterator#remove()
*/
public boolean retainAll(Collection c)
{
return retainAllInternal(c);
}
/**
* Remove from this collection all its elements that are not contained in a
* given collection (optional operation). This implementation iterates over
* this collection, and for each element tests if it is contained in the
* given collection. If not, it is removed by the Iterator's remove method
* (thus this method will fail with an UnsupportedOperationException if
* the Iterator's remove method does). This method is necessary for
* ArrayList, which cannot publicly override retainAll but can optimize
* this call.
*
* @param c the collection to retain the elements of
* @return true if the remove operation caused the Collection to change
* @throws UnsupportedOperationException if this collection's Iterator
* does not support the remove method
* @throws NullPointerException if the collection, c, is null.
* @see Iterator#remove()
*/
// Package visible for use throughout java.util.
boolean retainAllInternal(Collection c)
{
Iterator itr = iterator();
boolean modified = false;
int pos = size();
while (--pos >= 0)
if (!c.contains(itr.next()))
{
itr.remove();
modified = true;
}
return modified;
}
/**
* Return an array containing the elements of this collection. This
* implementation creates an Object array of size size() and then iterates
* over the collection, setting each element of the array from the value
* returned by the iterator. The returned array is safe, and is not backed
* by the collection.
*
* @return an array containing the elements of this collection
*/
public Object[] toArray()
{
Iterator itr = iterator();
int size = size();
Object[] a = new Object[size];
for (int pos = 0; pos < size; pos++)
a[pos] = itr.next();
return a;
}
/**
* Copy the collection into a given array if it will fit, or into a
* dynamically created array of the same run-time type as the given array if
* not. If there is space remaining in the array, the first element after the
* end of the collection is set to null (this is only useful if the
* collection is known to contain no null elements, however). This
* implementation first tests whether the given array is large enough to hold
* all the elements of the collection. If not, the reflection API is used to
* allocate a new array of the same run-time type. Next an iterator is
* obtained over the collection and the elements are placed in the array as
* they are returned by the iterator. Finally the first spare element, if
* any, of the array is set to null, and the created array is returned.
* The returned array is safe; it is not backed by the collection. Note that
* null may not mark the last element, if the collection allows null
* elements.
*
* @param a the array to copy into, or of the correct run-time type
* @return the array that was produced
* @throws NullPointerException if the given array is null
* @throws ArrayStoreException if the type of the array precludes holding
* one of the elements of the Collection
*/
public Object[] toArray(Object[] a)
{
int size = size();
if (a.length < size)
a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
size);
else if (a.length > size)
a[size] = null;
Iterator itr = iterator();
for (int pos = 0; pos < size; pos++)
a[pos] = itr.next();
return a;
}
/**
* Creates a String representation of the Collection. The string returned is
* of the form "[a, b, ...]" where a and b etc are the results of calling
* toString on the elements of the collection. This implementation obtains an
* Iterator over the Collection and adds each element to a StringBuffer as it
* is returned by the iterator.
*
* @return a String representation of the Collection
*/
public String toString()
{
Iterator itr = iterator();
StringBuffer r = new StringBuffer("[");
for (int pos = size(); pos > 0; pos--)
{
r.append(itr.next());
if (pos > 1)
r.append(", ");
}
r.append("]");
return r.toString();
}
/**
* Compare two objects according to Collection semantics.
*
* @param o1 the first object
* @param o2 the second object
* @return o1 == null ? o2 == null : o1.equals(o2)
*/
// Package visible for use throughout java.util.
// It may be inlined since it is final.
static final boolean equals(Object o1, Object o2)
{
return o1 == null ? o2 == null : o1.equals(o2);
}
/**
* Hash an object according to Collection semantics.
*
* @param o the object to hash
* @return o1 == null ? 0 : o1.hashCode()
*/
// Package visible for use throughout java.util.
// It may be inlined since it is final.
static final int hashCode(Object o)
{
return o == null ? 0 : o.hashCode();
}
}
File diff suppressed because it is too large Load Diff
-749
View File
@@ -1,749 +0,0 @@
/* AbstractMap.java -- Abstract implementation of most of Map
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* An abstract implementation of Map to make it easier to create your own
* implementations. In order to create an unmodifiable Map, subclass
* AbstractMap and implement the <code>entrySet</code> (usually via an
* AbstractSet). To make it modifiable, also implement <code>put</code>,
* and have <code>entrySet().iterator()</code> support <code>remove</code>.
* <p>
*
* It is recommended that classes which extend this support at least the
* no-argument constructor, and a constructor which accepts another Map.
* Further methods in this class may be overridden if you have a more
* efficient implementation.
*
* @author Original author unknown
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
* @see Map
* @see Collection
* @see HashMap
* @see LinkedHashMap
* @see TreeMap
* @see WeakHashMap
* @see IdentityHashMap
* @since 1.2
* @status updated to 1.4
*/
public abstract class AbstractMap implements Map
{
/** An "enum" of iterator types. */
// Package visible for use by subclasses.
static final int KEYS = 0,
VALUES = 1,
ENTRIES = 2;
/**
* The cache for {@link #keySet()}.
*/
// Package visible for use by subclasses.
Set keys;
/**
* The cache for {@link #values()}.
*/
// Package visible for use by subclasses.
Collection values;
/**
* The main constructor, for use by subclasses.
*/
protected AbstractMap()
{
}
/**
* Returns a set view of the mappings in this Map. Each element in the
* set must be an implementation of Map.Entry. The set is backed by
* the map, so that changes in one show up in the other. Modifications
* made while an iterator is in progress cause undefined behavior. If
* the set supports removal, these methods must be valid:
* <code>Iterator.remove</code>, <code>Set.remove</code>,
* <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
* Element addition is not supported via this set.
*
* @return the entry set
* @see Map.Entry
*/
public abstract Set entrySet();
/**
* Remove all entries from this Map (optional operation). This default
* implementation calls entrySet().clear(). NOTE: If the entry set does
* not permit clearing, then this will fail, too. Subclasses often
* override this for efficiency. Your implementation of entrySet() should
* not call <code>AbstractMap.clear</code> unless you want an infinite loop.
*
* @throws UnsupportedOperationException if <code>entrySet().clear()</code>
* does not support clearing.
* @see Set#clear()
*/
public void clear()
{
entrySet().clear();
}
/**
* Create a shallow copy of this Map, no keys or values are copied. The
* default implementation simply calls <code>super.clone()</code>.
*
* @return the shallow clone
* @throws CloneNotSupportedException if a subclass is not Cloneable
* @see Cloneable
* @see Object#clone()
*/
protected Object clone() throws CloneNotSupportedException
{
AbstractMap copy = (AbstractMap) super.clone();
// Clear out the caches; they are stale.
copy.keys = null;
copy.values = null;
return copy;
}
/**
* Returns true if this contains a mapping for the given key. This
* implementation does a linear search, O(n), over the
* <code>entrySet()</code>, returning <code>true</code> if a match
* is found, <code>false</code> if the iteration ends. Many subclasses
* can implement this more efficiently.
*
* @param key the key to search for
* @return true if the map contains the key
* @throws NullPointerException if key is <code>null</code> but the map
* does not permit null keys
* @see #containsValue(Object)
*/
public boolean containsKey(Object key)
{
Iterator entries = entrySet().iterator();
int pos = size();
while (--pos >= 0)
if (equals(key, ((Map.Entry) entries.next()).getKey()))
return true;
return false;
}
/**
* Returns true if this contains at least one mapping with the given value.
* This implementation does a linear search, O(n), over the
* <code>entrySet()</code>, returning <code>true</code> if a match
* is found, <code>false</code> if the iteration ends. A match is
* defined as a value, v, where <code>(value == null ? v == null :
* value.equals(v))</code>. Subclasses are unlikely to implement
* this more efficiently.
*
* @param value the value to search for
* @return true if the map contains the value
* @see #containsKey(Object)
*/
public boolean containsValue(Object value)
{
Iterator entries = entrySet().iterator();
int pos = size();
while (--pos >= 0)
if (equals(value, ((Map.Entry) entries.next()).getValue()))
return true;
return false;
}
/**
* Compares the specified object with this map for equality. Returns
* <code>true</code> if the other object is a Map with the same mappings,
* that is,<br>
* <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
*
* @param o the object to be compared
* @return true if the object equals this map
* @see Set#equals(Object)
*/
public boolean equals(Object o)
{
return (o == this ||
(o instanceof Map &&
entrySet().equals(((Map) o).entrySet())));
}
/**
* Returns the value mapped by the given key. Returns <code>null</code> if
* there is no mapping. However, in Maps that accept null values, you
* must rely on <code>containsKey</code> to determine if a mapping exists.
* This iteration takes linear time, searching entrySet().iterator() of
* the key. Many implementations override this method.
*
* @param key the key to look up
* @return the value associated with the key, or null if key not in map
* @throws NullPointerException if this map does not accept null keys
* @see #containsKey(Object)
*/
public Object get(Object key)
{
Iterator entries = entrySet().iterator();
int pos = size();
while (--pos >= 0)
{
Map.Entry entry = (Map.Entry) entries.next();
if (equals(key, entry.getKey()))
return entry.getValue();
}
return null;
}
/**
* Returns the hash code for this map. As defined in Map, this is the sum
* of all hashcodes for each Map.Entry object in entrySet, or basically
* entrySet().hashCode().
*
* @return the hash code
* @see Map.Entry#hashCode()
* @see Set#hashCode()
*/
public int hashCode()
{
return entrySet().hashCode();
}
/**
* Returns true if the map contains no mappings. This is implemented by
* <code>size() == 0</code>.
*
* @return true if the map is empty
* @see #size()
*/
public boolean isEmpty()
{
return size() == 0;
}
/**
* Returns a set view of this map's keys. The set is backed by the map,
* so changes in one show up in the other. Modifications while an iteration
* is in progress produce undefined behavior. The set supports removal
* if entrySet() does, but does not support element addition.
* <p>
*
* This implementation creates an AbstractSet, where the iterator wraps
* the entrySet iterator, size defers to the Map's size, and contains
* defers to the Map's containsKey. The set is created on first use, and
* returned on subsequent uses, although since no synchronization occurs,
* there is a slight possibility of creating two sets.
*
* @return a Set view of the keys
* @see Set#iterator()
* @see #size()
* @see #containsKey(Object)
* @see #values()
*/
public Set keySet()
{
if (keys == null)
keys = new AbstractSet()
{
/**
* Retrieves the number of keys in the backing map.
*
* @return The number of keys.
*/
public int size()
{
return AbstractMap.this.size();
}
/**
* Returns true if the backing map contains the
* supplied key.
*
* @param key The key to search for.
* @return True if the key was found, false otherwise.
*/
public boolean contains(Object key)
{
return containsKey(key);
}
/**
* Returns an iterator which iterates over the keys
* in the backing map, using a wrapper around the
* iterator returned by <code>entrySet()</code>.
*
* @return An iterator over the keys.
*/
public Iterator iterator()
{
return new Iterator()
{
/**
* The iterator returned by <code>entrySet()</code>.
*/
private final Iterator map_iterator = entrySet().iterator();
/**
* Returns true if a call to <code>next()</code> will
* return another key.
*
* @return True if the iterator has not yet reached
* the last key.
*/
public boolean hasNext()
{
return map_iterator.hasNext();
}
/**
* Returns the key from the next entry retrieved
* by the underlying <code>entrySet()</code> iterator.
*
* @return The next key.
*/
public Object next()
{
return ((Map.Entry) map_iterator.next()).getKey();
}
/**
* Removes the map entry which has a key equal
* to that returned by the last call to
* <code>next()</code>.
*
* @throws UnsupportedOperationException if the
* map doesn't support removal.
*/
public void remove()
{
map_iterator.remove();
}
};
}
};
return keys;
}
/**
* Associates the given key to the given value (optional operation). If the
* map already contains the key, its value is replaced. This implementation
* simply throws an UnsupportedOperationException. Be aware that in a map
* that permits <code>null</code> values, a null return does not always
* imply that the mapping was created.
*
* @param key the key to map
* @param value the value to be mapped
* @return the previous value of the key, or null if there was no mapping
* @throws UnsupportedOperationException if the operation is not supported
* @throws ClassCastException if the key or value is of the wrong type
* @throws IllegalArgumentException if something about this key or value
* prevents it from existing in this map
* @throws NullPointerException if the map forbids null keys or values
* @see #containsKey(Object)
*/
public Object put(Object key, Object value)
{
throw new UnsupportedOperationException();
}
/**
* Copies all entries of the given map to this one (optional operation). If
* the map already contains a key, its value is replaced. This implementation
* simply iterates over the map's entrySet(), calling <code>put</code>,
* so it is not supported if puts are not.
*
* @param m the mapping to load into this map
* @throws UnsupportedOperationException if the operation is not supported
* by this map.
* @throws ClassCastException if a key or value is of the wrong type for
* adding to this map.
* @throws IllegalArgumentException if something about a key or value
* prevents it from existing in this map.
* @throws NullPointerException if the map forbids null keys or values.
* @throws NullPointerException if <code>m</code> is null.
* @see #put(Object, Object)
*/
public void putAll(Map m)
{
Iterator entries = m.entrySet().iterator();
int pos = m.size();
while (--pos >= 0)
{
Map.Entry entry = (Map.Entry) entries.next();
put(entry.getKey(), entry.getValue());
}
}
/**
* Removes the mapping for this key if present (optional operation). This
* implementation iterates over the entrySet searching for a matching
* key, at which point it calls the iterator's <code>remove</code> method.
* It returns the result of <code>getValue()</code> on the entry, if found,
* or null if no entry is found. Note that maps which permit null values
* may also return null if the key was removed. If the entrySet does not
* support removal, this will also fail. This is O(n), so many
* implementations override it for efficiency.
*
* @param key the key to remove
* @return the value the key mapped to, or null if not present.
* Null may also be returned if null values are allowed
* in the map and the value of this mapping is null.
* @throws UnsupportedOperationException if deletion is unsupported
* @see Iterator#remove()
*/
public Object remove(Object key)
{
Iterator entries = entrySet().iterator();
int pos = size();
while (--pos >= 0)
{
Map.Entry entry = (Map.Entry) entries.next();
if (equals(key, entry.getKey()))
{
// Must get the value before we remove it from iterator.
Object r = entry.getValue();
entries.remove();
return r;
}
}
return null;
}
/**
* Returns the number of key-value mappings in the map. If there are more
* than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
* implemented as <code>entrySet().size()</code>.
*
* @return the number of mappings
* @see Set#size()
*/
public int size()
{
return entrySet().size();
}
/**
* Returns a String representation of this map. This is a listing of the
* map entries (which are specified in Map.Entry as being
* <code>getKey() + "=" + getValue()</code>), separated by a comma and
* space (", "), and surrounded by braces ('{' and '}'). This implementation
* uses a StringBuffer and iterates over the entrySet to build the String.
* Note that this can fail with an exception if underlying keys or
* values complete abruptly in toString().
*
* @return a String representation
* @see Map.Entry#toString()
*/
public String toString()
{
Iterator entries = entrySet().iterator();
StringBuffer r = new StringBuffer("{");
for (int pos = size(); pos > 0; pos--)
{
Map.Entry entry = (Map.Entry) entries.next();
r.append(entry.getKey());
r.append('=');
r.append(entry.getValue());
if (pos > 1)
r.append(", ");
}
r.append("}");
return r.toString();
}
/**
* Returns a collection or bag view of this map's values. The collection
* is backed by the map, so changes in one show up in the other.
* Modifications while an iteration is in progress produce undefined
* behavior. The collection supports removal if entrySet() does, but
* does not support element addition.
* <p>
*
* This implementation creates an AbstractCollection, where the iterator
* wraps the entrySet iterator, size defers to the Map's size, and contains
* defers to the Map's containsValue. The collection is created on first
* use, and returned on subsequent uses, although since no synchronization
* occurs, there is a slight possibility of creating two collections.
*
* @return a Collection view of the values
* @see Collection#iterator()
* @see #size()
* @see #containsValue(Object)
* @see #keySet()
*/
public Collection values()
{
if (values == null)
values = new AbstractCollection()
{
/**
* Returns the number of values stored in
* the backing map.
*
* @return The number of values.
*/
public int size()
{
return AbstractMap.this.size();
}
/**
* Returns true if the backing map contains
* the supplied value.
*
* @param value The value to search for.
* @return True if the value was found, false otherwise.
*/
public boolean contains(Object value)
{
return containsValue(value);
}
/**
* Returns an iterator which iterates over the
* values in the backing map, by using a wrapper
* around the iterator returned by <code>entrySet()</code>.
*
* @return An iterator over the values.
*/
public Iterator iterator()
{
return new Iterator()
{
/**
* The iterator returned by <code>entrySet()</code>.
*/
private final Iterator map_iterator = entrySet().iterator();
/**
* Returns true if a call to <code>next()</call> will
* return another value.
*
* @return True if the iterator has not yet reached
* the last value.
*/
public boolean hasNext()
{
return map_iterator.hasNext();
}
/**
* Returns the value from the next entry retrieved
* by the underlying <code>entrySet()</code> iterator.
*
* @return The next value.
*/
public Object next()
{
return ((Map.Entry) map_iterator.next()).getValue();
}
/**
* Removes the map entry which has a key equal
* to that returned by the last call to
* <code>next()</code>.
*
* @throws UnsupportedOperationException if the
* map doesn't support removal.
*/
public void remove()
{
map_iterator.remove();
}
};
}
};
return values;
}
/**
* Compare two objects according to Collection semantics.
*
* @param o1 the first object
* @param o2 the second object
* @return o1 == null ? o2 == null : o1.equals(o2)
*/
// Package visible for use throughout java.util.
// It may be inlined since it is final.
static final boolean equals(Object o1, Object o2)
{
return o1 == null ? o2 == null : o1.equals(o2);
}
/**
* Hash an object according to Collection semantics.
*
* @param o the object to hash
* @return o1 == null ? 0 : o1.hashCode()
*/
// Package visible for use throughout java.util.
// It may be inlined since it is final.
static final int hashCode(Object o)
{
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)
*/
// XXX - FIXME Use fully qualified implements as gcj 3.1 workaround.
// Bug still exists in 3.4.1
static class BasicMapEntry implements Map.Entry
{
/**
* 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:<br>
* <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:<br>
* <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.
* @throws UnsupportedOperationException if the map doesn't support
* <code>put()</code>.
* @throws ClassCastException if the value is of a type unsupported
* by the map.
* @throws IllegalArgumentException if something else about this
* value prevents it being stored in the map.
*/
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
}
@@ -1,235 +0,0 @@
/* AbstractSequentialList.java -- List implementation for sequential access
Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* Abstract superclass to make it easier to implement the List interface when
* backed by a sequential-access store, such as a linked list. For random
* access data, use AbstractList. This class implements the random access
* methods (<code>get</code>, <code>set</code>, <code>add</code>, and
* <code>remove</code>) atop the list iterator, opposite of AbstractList's
* approach of implementing the iterator atop random access.
* <p>
*
* To implement a list, you need an implementation for <code>size()</code>
* and <code>listIterator</code>. With just <code>hasNext</code>,
* <code>next</code>, <code>hasPrevious</code>, <code>previous</code>,
* <code>nextIndex</code>, and <code>previousIndex</code>, you have an
* unmodifiable list. For a modifiable one, add <code>set</code>, and for
* a variable-size list, add <code>add</code> and <code>remove</code>.
* <p>
*
* The programmer should provide a no-argument constructor, and one that
* accepts another Collection, as recommended by the Collection interface.
* Unfortunately, there is no way to enforce this in Java.
*
* @author Original author unknown
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see List
* @see AbstractList
* @see AbstractCollection
* @see ListIterator
* @see LinkedList
* @since 1.2
* @status updated to 1.4
*/
public abstract class AbstractSequentialList extends AbstractList
{
/**
* The main constructor, for use by subclasses.
*/
protected AbstractSequentialList()
{
}
/**
* Returns a ListIterator over the list, starting from position index.
* Subclasses must provide an implementation of this method.
*
* @param index the starting position of the list
* @return the list iterator
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
public abstract ListIterator listIterator(int index);
/**
* Insert an element into the list at a given position (optional operation).
* This shifts all existing elements from that position to the end one
* index to the right. This version of add has no return, since it is
* assumed to always succeed if there is no exception. This iteration
* uses listIterator(index).add(o).
*
* @param index the location to insert the item
* @param o the object to insert
* @throws UnsupportedOperationException if this list does not support the
* add operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
* @throws ClassCastException if o cannot be added to this list due to its
* type
* @throws IllegalArgumentException if o cannot be added to this list for
* some other reason.
* @throws NullPointerException if o is null and the list does not permit
* the addition of null values.
*/
public void add(int index, Object o)
{
listIterator(index).add(o);
}
/**
* Insert the contents of a collection into the list at a given position
* (optional operation). Shift all elements at that position to the right
* by the number of elements inserted. This operation is undefined if
* this list is modified during the operation (for example, if you try
* to insert a list into itself).
* <p>
*
* This implementation grabs listIterator(index), then proceeds to use add
* for each element returned by c's iterator. Sun's online specs are wrong,
* claiming that this also calls next(): listIterator.add() correctly
* skips the added element.
*
* @param index the location to insert the collection
* @param c the collection to insert
* @return true if the list was modified by this action, that is, if c is
* non-empty
* @throws UnsupportedOperationException if this list does not support the
* addAll operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
* @throws ClassCastException if some element of c cannot be added to this
* list due to its type
* @throws IllegalArgumentException if some element of c cannot be added
* to this list for some other reason
* @throws NullPointerException if the specified collection is null
* @throws NullPointerException if an object, o, in c is null and the list
* does not permit the addition of null values.
* @see #add(int, Object)
*/
public boolean addAll(int index, Collection c)
{
Iterator ci = c.iterator();
int size = c.size();
ListIterator i = listIterator(index);
for (int pos = size; pos > 0; pos--)
i.add(ci.next());
return size > 0;
}
/**
* Get the element at a given index in this list. This implementation
* returns listIterator(index).next().
*
* @param index the index of the element to be returned
* @return the element at index index in this list
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
public Object get(int index)
{
// This is a legal listIterator position, but an illegal get.
if (index == size())
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ size());
return listIterator(index).next();
}
/**
* Obtain an Iterator over this list, whose sequence is the list order. This
* implementation returns listIterator().
*
* @return an Iterator over the elements of this list, in order
*/
public Iterator iterator()
{
return listIterator();
}
/**
* Remove the element at a given position in this list (optional operation).
* Shifts all remaining elements to the left to fill the gap. This
* implementation uses listIterator(index) and ListIterator.remove().
*
* @param index the position within the list of the object to remove
* @return the object that was removed
* @throws UnsupportedOperationException if this list does not support the
* remove operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
public Object remove(int index)
{
// This is a legal listIterator position, but an illegal remove.
if (index == size())
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ size());
ListIterator i = listIterator(index);
Object removed = i.next();
i.remove();
return removed;
}
/**
* Replace an element of this list with another object (optional operation).
* This implementation uses listIterator(index) and ListIterator.set(o).
*
* @param index the position within this list of the element to be replaced
* @param o the object to replace it with
* @return the object that was replaced
* @throws UnsupportedOperationException if this list does not support the
* set operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
* @throws ClassCastException if o cannot be added to this list due to its
* type
* @throws IllegalArgumentException if o cannot be added to this list for
* some other reason
* @throws NullPointerException if o is null and the list does not allow
* a value to be set to null.
*/
public Object set(int index, Object o)
{
// This is a legal listIterator position, but an illegal set.
if (index == size())
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ size());
ListIterator i = listIterator(index);
Object old = i.next();
i.set(o);
return old;
}
}
-139
View File
@@ -1,139 +0,0 @@
/* AbstractSet.java -- Abstract implementation of most of Set
Copyright (C) 1998, 2000, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* An abstract implementation of Set to make it easier to create your own
* implementations. In order to create a Set, subclass AbstractSet and
* implement the same methods that are required for AbstractCollection
* (although these methods must of course meet the requirements that Set puts
* on them - specifically, no element may be in the set more than once). This
* class simply provides implementations of equals() and hashCode() to fulfil
* the requirements placed on them by the Set interface.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see AbstractCollection
* @see Set
* @see HashSet
* @see TreeSet
* @see LinkedHashSet
* @since 1.2
* @status updated to 1.4
*/
public abstract class AbstractSet extends AbstractCollection implements Set
{
/**
* The main constructor, for use by subclasses.
*/
protected AbstractSet()
{
}
/**
* Tests whether the given object is equal to this Set. This implementation
* first checks whether this set <em>is</em> the given object, and returns
* true if so. Otherwise, if o is a Set and is the same size as this one, it
* returns the result of calling containsAll on the given Set. Otherwise, it
* returns false.
*
* @param o the Object to be tested for equality with this Set
* @return true if the given object is equal to this Set
*/
public boolean equals(Object o)
{
return (o == this ||
(o instanceof Set && ((Set) o).size() == size()
&& containsAll((Collection) o)));
}
/**
* Returns a hash code for this Set. The hash code of a Set is the sum of the
* hash codes of all its elements, except that the hash code of null is
* defined to be zero. This implementation obtains an Iterator over the Set,
* and sums the results.
*
* @return a hash code for this Set
*/
public int hashCode()
{
Iterator itr = iterator();
int hash = 0;
int pos = size();
while (--pos >= 0)
hash += hashCode(itr.next());
return hash;
}
/**
* Removes from this set all elements in the given collection (optional
* operation). This implementation uses <code>size()</code> to determine
* the smaller collection. Then, if this set is smaller, it iterates
* over the set, calling Iterator.remove if the collection contains
* the element. If this set is larger, it iterates over the collection,
* calling Set.remove for all elements in the collection. Note that
* this operation will fail if a remove methods is not supported.
*
* @param c the collection of elements to remove
* @return true if the set was modified as a result
* @throws UnsupportedOperationException if remove is not supported
* @throws NullPointerException if the collection is null
* @see AbstractCollection#remove(Object)
* @see Collection#contains(Object)
* @see Iterator#remove()
*/
public boolean removeAll(Collection c)
{
int oldsize = size();
int count = c.size();
Iterator i;
if (oldsize < count)
{
for (i = iterator(), count = oldsize; count > 0; count--)
if (c.contains(i.next()))
i.remove();
}
else
for (i = c.iterator(); count > 0; count--)
remove(i.next());
return oldsize != size();
}
}
-591
View File
@@ -1,591 +0,0 @@
/* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed
implementation of the List interface
Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
/**
* An array-backed implementation of the List interface. This implements
* all optional list operations, and permits null elements, so that it is
* better than Vector, which it replaces. Random access is roughly constant
* time, and iteration is roughly linear time, so it is nice and fast, with
* less overhead than a LinkedList.
* <p>
*
* Each list has a capacity, and as the array reaches that capacity it
* is automatically transferred to a larger array. You also have access to
* ensureCapacity and trimToSize to control the backing array's size, avoiding
* reallocation or wasted memory.
* <p>
*
* ArrayList is not synchronized, so if you need multi-threaded access,
* consider using:<br>
* <code>List l = Collections.synchronizedList(new ArrayList(...));</code>
* <p>
*
* The iterators are <i>fail-fast</i>, meaning that any structural
* modification, except for <code>remove()</code> called on the iterator
* itself, cause the iterator to throw a
* {@link ConcurrentModificationException} rather than exhibit
* non-deterministic behavior.
*
* @author Jon A. Zeppieri
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see List
* @see LinkedList
* @see Vector
* @see Collections#synchronizedList(List)
* @see AbstractList
* @status updated to 1.4
*/
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2
*/
private static final long serialVersionUID = 8683452581122892189L;
/**
* The default capacity for new ArrayLists.
*/
private static final int DEFAULT_CAPACITY = 16;
/**
* The number of elements in this list.
* @serial the list size
*/
private int size;
/**
* Where the data is stored.
*/
private transient Object[] data;
/**
* Construct a new ArrayList with the supplied initial capacity.
*
* @param capacity initial capacity of this ArrayList
* @throws IllegalArgumentException if capacity is negative
*/
public ArrayList(int capacity)
{
// Must explicitly check, to get correct exception.
if (capacity < 0)
throw new IllegalArgumentException();
data = new Object[capacity];
}
/**
* Construct a new ArrayList with the default capacity (16).
*/
public ArrayList()
{
this(DEFAULT_CAPACITY);
}
/**
* Construct a new ArrayList, and initialize it with the elements
* in the supplied Collection. The initial capacity is 110% of the
* Collection's size.
*
* @param c the collection whose elements will initialize this list
* @throws NullPointerException if c is null
*/
public ArrayList(Collection c)
{
this((int) (c.size() * 1.1f));
addAll(c);
}
/**
* Trims the capacity of this List to be equal to its size;
* a memory saver.
*/
public void trimToSize()
{
// Not a structural change from the perspective of iterators on this list,
// so don't update modCount.
if (size != data.length)
{
Object[] newData = new Object[size];
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
}
/**
* Guarantees that this list will have at least enough capacity to
* hold minCapacity elements. This implementation will grow the list to
* max(current * 2, minCapacity) if (minCapacity &gt; current). The JCL says
* explictly that "this method increases its capacity to minCap", while
* the JDK 1.3 online docs specify that the list will grow to at least the
* size specified.
*
* @param minCapacity the minimum guaranteed capacity
*/
public void ensureCapacity(int minCapacity)
{
int current = data.length;
if (minCapacity > current)
{
Object[] newData = new Object[Math.max(current * 2, minCapacity)];
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
}
/**
* Returns the number of elements in this list.
*
* @return the list size
*/
public int size()
{
return size;
}
/**
* Checks if the list is empty.
*
* @return true if there are no elements
*/
public boolean isEmpty()
{
return size == 0;
}
/**
* Returns true iff element is in this ArrayList.
*
* @param e the element whose inclusion in the List is being tested
* @return true if the list contains e
*/
public boolean contains(Object e)
{
return indexOf(e) != -1;
}
/**
* Returns the lowest index at which element appears in this List, or
* -1 if it does not appear.
*
* @param e the element whose inclusion in the List is being tested
* @return the index where e was found
*/
public int indexOf(Object e)
{
for (int i = 0; i < size; i++)
if (equals(e, data[i]))
return i;
return -1;
}
/**
* Returns the highest index at which element appears in this List, or
* -1 if it does not appear.
*
* @param e the element whose inclusion in the List is being tested
* @return the index where e was found
*/
public int lastIndexOf(Object e)
{
for (int i = size - 1; i >= 0; i--)
if (equals(e, data[i]))
return i;
return -1;
}
/**
* Creates a shallow copy of this ArrayList (elements are not cloned).
*
* @return the cloned object
*/
public Object clone()
{
ArrayList clone = null;
try
{
clone = (ArrayList) super.clone();
clone.data = (Object[]) data.clone();
}
catch (CloneNotSupportedException e)
{
// Impossible to get here.
}
return clone;
}
/**
* Returns an Object array containing all of the elements in this ArrayList.
* The array is independent of this list.
*
* @return an array representation of this list
*/
public Object[] toArray()
{
Object[] array = new Object[size];
System.arraycopy(data, 0, array, 0, size);
return array;
}
/**
* Returns an Array whose component type is the runtime component type of
* the passed-in Array. The returned Array is populated with all of the
* elements in this ArrayList. If the passed-in Array is not large enough
* to store all of the elements in this List, a new Array will be created
* and returned; if the passed-in Array is <i>larger</i> than the size
* of this List, then size() index will be set to null.
*
* @param a the passed-in Array
* @return an array representation of this list
* @throws ArrayStoreException if the runtime type of a does not allow
* an element in this list
* @throws NullPointerException if a is null
*/
public Object[] toArray(Object[] a)
{
if (a.length < size)
a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
size);
else if (a.length > size)
a[size] = null;
System.arraycopy(data, 0, a, 0, size);
return a;
}
/**
* Retrieves the element at the user-supplied index.
*
* @param index the index of the element we are fetching
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
public Object get(int index)
{
checkBoundExclusive(index);
return data[index];
}
/**
* Sets the element at the specified index. The new element, e,
* can be an object of any type or null.
*
* @param index the index at which the element is being set
* @param e the element to be set
* @return the element previously at the specified index
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= 0
*/
public Object set(int index, Object e)
{
checkBoundExclusive(index);
Object result = data[index];
data[index] = e;
return result;
}
/**
* Appends the supplied element to the end of this list.
* The element, e, can be an object of any type or null.
*
* @param e the element to be appended to this list
* @return true, the add will always succeed
*/
public boolean add(Object e)
{
modCount++;
if (size == data.length)
ensureCapacity(size + 1);
data[size++] = e;
return true;
}
/**
* Adds the supplied element at the specified index, shifting all
* elements currently at that index or higher one to the right.
* The element, e, can be an object of any type or null.
*
* @param index the index at which the element is being added
* @param e the item being added
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
public void add(int index, Object e)
{
checkBoundInclusive(index);
modCount++;
if (size == data.length)
ensureCapacity(size + 1);
if (index != size)
System.arraycopy(data, index, data, index + 1, size - index);
data[index] = e;
size++;
}
/**
* Removes the element at the user-supplied index.
*
* @param index the index of the element to be removed
* @return the removed Object
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
public Object remove(int index)
{
checkBoundExclusive(index);
Object r = data[index];
modCount++;
if (index != --size)
System.arraycopy(data, index + 1, data, index, size - index);
// Aid for garbage collection by releasing this pointer.
data[size] = null;
return r;
}
/**
* Removes all elements from this List
*/
public void clear()
{
if (size > 0)
{
modCount++;
// Allow for garbage collection.
Arrays.fill(data, 0, size, null);
size = 0;
}
}
/**
* Add each element in the supplied Collection to this List. It is undefined
* what happens if you modify the list while this is taking place; for
* example, if the collection contains this list. c can contain objects
* of any type, as well as null values.
*
* @param c a Collection containing elements to be added to this List
* @return true if the list was modified, in other words c is not empty
* @throws NullPointerException if c is null
*/
public boolean addAll(Collection c)
{
return addAll(size, c);
}
/**
* Add all elements in the supplied collection, inserting them beginning
* at the specified index. c can contain objects of any type, as well
* as null values.
*
* @param index the index at which the elements will be inserted
* @param c the Collection containing the elements to be inserted
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; 0
* @throws NullPointerException if c is null
*/
public boolean addAll(int index, Collection c)
{
checkBoundInclusive(index);
Iterator itr = c.iterator();
int csize = c.size();
modCount++;
if (csize + size > data.length)
ensureCapacity(size + csize);
int end = index + csize;
if (size > 0 && index != size)
System.arraycopy(data, index, data, end, size - index);
size += csize;
for ( ; index < end; index++)
data[index] = itr.next();
return csize > 0;
}
/**
* Removes all elements in the half-open interval [fromIndex, toIndex).
* Does nothing when toIndex is equal to fromIndex.
*
* @param fromIndex the first index which will be removed
* @param toIndex one greater than the last index which will be removed
* @throws IndexOutOfBoundsException if fromIndex &gt; toIndex
*/
protected void removeRange(int fromIndex, int toIndex)
{
int change = toIndex - fromIndex;
if (change > 0)
{
modCount++;
System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
size -= change;
}
else if (change < 0)
throw new IndexOutOfBoundsException();
}
/**
* Checks that the index is in the range of possible elements (inclusive).
*
* @param index the index to check
* @throws IndexOutOfBoundsException if index &gt; size
*/
private void checkBoundInclusive(int index)
{
// Implementation note: we do not check for negative ranges here, since
// use of a negative index will cause an ArrayIndexOutOfBoundsException,
// a subclass of the required exception, with no effort on our part.
if (index > size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
}
/**
* Checks that the index is in the range of existing elements (exclusive).
*
* @param index the index to check
* @throws IndexOutOfBoundsException if index &gt;= size
*/
private void checkBoundExclusive(int index)
{
// Implementation note: we do not check for negative ranges here, since
// use of a negative index will cause an ArrayIndexOutOfBoundsException,
// a subclass of the required exception, with no effort on our part.
if (index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
}
/**
* Remove from this list all elements contained in the given collection.
* This is not public, due to Sun's API, but this performs in linear
* time while the default behavior of AbstractList would be quadratic.
*
* @param c the collection to filter out
* @return true if this list changed
* @throws NullPointerException if c is null
*/
boolean removeAllInternal(Collection c)
{
int i;
int j;
for (i = 0; i < size; i++)
if (c.contains(data[i]))
break;
if (i == size)
return false;
modCount++;
for (j = i++; i < size; i++)
if (! c.contains(data[i]))
data[j++] = data[i];
size -= i - j;
return true;
}
/**
* Retain in this vector only the elements contained in the given collection.
* This is not public, due to Sun's API, but this performs in linear
* time while the default behavior of AbstractList would be quadratic.
*
* @param c the collection to filter by
* @return true if this vector changed
* @throws NullPointerException if c is null
* @since 1.2
*/
boolean retainAllInternal(Collection c)
{
int i;
int j;
for (i = 0; i < size; i++)
if (! c.contains(data[i]))
break;
if (i == size)
return false;
modCount++;
for (j = i++; i < size; i++)
if (c.contains(data[i]))
data[j++] = data[i];
size -= i - j;
return true;
}
/**
* Serializes this object to the given stream.
*
* @param out the stream to write to
* @throws IOException if the underlying stream fails
* @serialData the size field (int), the length of the backing array
* (int), followed by its elements (Objects) in proper order.
*/
private void writeObject(ObjectOutputStream s) throws IOException
{
// The 'size' field.
s.defaultWriteObject();
// We serialize unused list entries to preserve capacity.
int len = data.length;
s.writeInt(len);
// it would be more efficient to just write "size" items,
// this need readObject read "size" items too.
for (int i = 0; i < size; i++)
s.writeObject(data[i]);
}
/**
* Deserializes this object from the given stream.
*
* @param in the stream to read from
* @throws ClassNotFoundException if the underlying stream fails
* @throws IOException if the underlying stream fails
* @serialData the size field (int), the length of the backing array
* (int), followed by its elements (Objects) in proper order.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
// the `size' field.
s.defaultReadObject();
int capacity = s.readInt();
data = new Object[capacity];
for (int i = 0; i < size; i++)
data[i] = s.readObject();
}
}
File diff suppressed because it is too large Load Diff
-744
View File
@@ -1,744 +0,0 @@
/* BitSet.java -- A vector of bits.
Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.Serializable;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* hashCode algorithm taken from JDK 1.2 docs.
*/
/**
* This class can be thought of in two ways. You can see it as a
* vector of bits or as a set of non-negative integers. The name
* <code>BitSet</code> is a bit misleading.
*
* It is implemented by a bit vector, but its equally possible to see
* it as set of non-negative integer; each integer in the set is
* represented by a set bit at the corresponding index. The size of
* this structure is determined by the highest integer in the set.
*
* You can union, intersect and build (symmetric) remainders, by
* invoking the logical operations and, or, andNot, resp. xor.
*
* This implementation is NOT synchronized against concurrent access from
* multiple threads. Specifically, if one thread is reading from a bitset
* while another thread is simultaneously modifying it, the results are
* undefined.
*
* @author Jochen Hoenicke
* @author Tom Tromey (tromey@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
* @status updated to 1.4
*/
public class BitSet implements Cloneable, Serializable
{
/**
* Compatible with JDK 1.0.
*/
private static final long serialVersionUID = 7997698588986878753L;
/**
* A common mask.
*/
private static final int LONG_MASK = 0x3f;
/**
* The actual bits.
* @serial the i'th bit is in bits[i/64] at position i%64 (where position
* 0 is the least significant).
*/
private long[] bits;
/**
* Create a new empty bit set. All bits are initially false.
*/
public BitSet()
{
this(64);
}
/**
* Create a new empty bit set, with a given size. This
* constructor reserves enough space to represent the integers
* from <code>0</code> to <code>nbits-1</code>.
*
* @param nbits the initial size of the bit set
* @throws NegativeArraySizeException if nbits &lt; 0
*/
public BitSet(int nbits)
{
if (nbits < 0)
throw new NegativeArraySizeException();
int length = nbits >>> 6;
if ((nbits & LONG_MASK) != 0)
++length;
bits = new long[length];
}
/**
* Performs the logical AND operation on this bit set and the
* given <code>set</code>. This means it builds the intersection
* of the two sets. The result is stored into this bit set.
*
* @param set the second bit set
* @throws NullPointerException if set is null
*/
public void and(BitSet bs)
{
int max = Math.min(bits.length, bs.bits.length);
int i;
for (i = 0; i < max; ++i)
bits[i] &= bs.bits[i];
while (i < bits.length)
bits[i++] = 0;
}
/**
* Performs the logical AND operation on this bit set and the
* complement of the given <code>set</code>. This means it
* selects every element in the first set, that isn't in the
* second set. The result is stored into this bit set and is
* effectively the set difference of the two.
*
* @param set the second bit set
* @throws NullPointerException if set is null
* @since 1.2
*/
public void andNot(BitSet bs)
{
int i = Math.min(bits.length, bs.bits.length);
while (--i >= 0)
bits[i] &= ~bs.bits[i];
}
/**
* Returns the number of bits set to true.
*
* @return the number of true bits
* @since 1.4
*/
public int cardinality()
{
int card = 0;
for (int i = bits.length - 1; i >= 0; i--)
{
long a = bits[i];
// Take care of common cases.
if (a == 0)
continue;
if (a == -1)
{
card += 64;
continue;
}
// Successively collapse alternating bit groups into a sum.
a = ((a >> 1) & 0x5555555555555555L) + (a & 0x5555555555555555L);
a = ((a >> 2) & 0x3333333333333333L) + (a & 0x3333333333333333L);
int b = (int) ((a >>> 32) + a);
b = ((b >> 4) & 0x0f0f0f0f) + (b & 0x0f0f0f0f);
b = ((b >> 8) & 0x00ff00ff) + (b & 0x00ff00ff);
card += ((b >> 16) & 0x0000ffff) + (b & 0x0000ffff);
}
return card;
}
/**
* Sets all bits in the set to false.
*
* @since 1.4
*/
public void clear()
{
Arrays.fill(bits, 0);
}
/**
* Removes the integer <code>bitIndex</code> from this set. That is
* the corresponding bit is cleared. If the index is not in the set,
* this method does nothing.
*
* @param bitIndex a non-negative integer
* @throws IndexOutOfBoundsException if bitIndex &lt; 0
*/
public void clear(int pos)
{
int offset = pos >> 6;
ensure(offset);
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
// so we'll just let that be our exception.
bits[offset] &= ~(1L << pos);
}
/**
* Sets the bits between from (inclusive) and to (exclusive) to false.
*
* @param from the start range (inclusive)
* @param to the end range (exclusive)
* @throws IndexOutOfBoundsException if from &lt; 0 || to &lt; 0 ||
* from &gt; to
* @since 1.4
*/
public void clear(int from, int to)
{
if (from < 0 || from > to)
throw new IndexOutOfBoundsException();
if (from == to)
return;
int lo_offset = from >>> 6;
int hi_offset = to >>> 6;
ensure(hi_offset);
if (lo_offset == hi_offset)
{
bits[hi_offset] &= ((1L << from) - 1) | (-1L << to);
return;
}
bits[lo_offset] &= (1L << from) - 1;
bits[hi_offset] &= -1L << to;
for (int i = lo_offset + 1; i < hi_offset; i++)
bits[i] = 0;
}
/**
* Create a clone of this bit set, that is an instance of the same
* class and contains the same elements. But it doesn't change when
* this bit set changes.
*
* @return the clone of this object.
*/
public Object clone()
{
try
{
BitSet bs = (BitSet) super.clone();
bs.bits = (long[]) bits.clone();
return bs;
}
catch (CloneNotSupportedException e)
{
// Impossible to get here.
return null;
}
}
/**
* Returns true if the <code>obj</code> is a bit set that contains
* exactly the same elements as this bit set, otherwise false.
*
* @param obj the object to compare to
* @return true if obj equals this bit set
*/
public boolean equals(Object obj)
{
if (!(obj instanceof BitSet))
return false;
BitSet bs = (BitSet) obj;
int max = Math.min(bits.length, bs.bits.length);
int i;
for (i = 0; i < max; ++i)
if (bits[i] != bs.bits[i])
return false;
// If one is larger, check to make sure all extra bits are 0.
for (int j = i; j < bits.length; ++j)
if (bits[j] != 0)
return false;
for (int j = i; j < bs.bits.length; ++j)
if (bs.bits[j] != 0)
return false;
return true;
}
/**
* Sets the bit at the index to the opposite value.
*
* @param index the index of the bit
* @throws IndexOutOfBoundsException if index is negative
* @since 1.4
*/
public void flip(int index)
{
int offset = index >> 6;
ensure(offset);
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
// so we'll just let that be our exception.
bits[offset] ^= 1L << index;
}
/**
* Sets a range of bits to the opposite value.
*
* @param from the low index (inclusive)
* @param to the high index (exclusive)
* @throws IndexOutOfBoundsException if from &gt; to || from &lt; 0 ||
* to &lt; 0
* @since 1.4
*/
public void flip(int from, int to)
{
if (from < 0 || from > to)
throw new IndexOutOfBoundsException();
if (from == to)
return;
int lo_offset = from >>> 6;
int hi_offset = to >>> 6;
ensure(hi_offset);
if (lo_offset == hi_offset)
{
bits[hi_offset] ^= (-1L << from) & ((1L << to) - 1);
return;
}
bits[lo_offset] ^= -1L << from;
bits[hi_offset] ^= (1L << to) - 1;
for (int i = lo_offset + 1; i < hi_offset; i++)
bits[i] ^= -1;
}
/**
* Returns true if the integer <code>bitIndex</code> is in this bit
* set, otherwise false.
*
* @param pos a non-negative integer
* @return the value of the bit at the specified index
* @throws IndexOutOfBoundsException if the index is negative
*/
public boolean get(int pos)
{
int offset = pos >> 6;
if (offset >= bits.length)
return false;
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
// so we'll just let that be our exception.
return (bits[offset] & (1L << pos)) != 0;
}
/**
* Returns a new <code>BitSet</code> composed of a range of bits from
* this one.
*
* @param from the low index (inclusive)
* @param to the high index (exclusive)
* @throws IndexOutOfBoundsException if from &gt; to || from &lt; 0 ||
* to &lt; 0
* @since 1.4
*/
public BitSet get(int from, int to)
{
if (from < 0 || from > to)
throw new IndexOutOfBoundsException();
BitSet bs = new BitSet(to - from);
int lo_offset = from >>> 6;
if (lo_offset >= bits.length)
return bs;
int lo_bit = from & LONG_MASK;
int hi_offset = to >>> 6;
if (lo_bit == 0)
{
int len = Math.min(hi_offset - lo_offset + 1, bits.length - lo_offset);
System.arraycopy(bits, lo_offset, bs.bits, 0, len);
if (hi_offset < bits.length)
bs.bits[hi_offset - lo_offset] &= (1L << to) - 1;
return bs;
}
int len = Math.min(hi_offset, bits.length - 1);
int reverse = 64 - lo_bit;
int i;
for (i = 0; lo_offset < len; lo_offset++, i++)
bs.bits[i] = ((bits[lo_offset] >>> lo_bit)
| (bits[lo_offset + 1] << reverse));
if ((to & LONG_MASK) > lo_bit)
bs.bits[i++] = bits[lo_offset] >>> lo_bit;
if (hi_offset < bits.length)
bs.bits[i - 1] &= (1L << (to - from)) - 1;
return bs;
}
/**
* Returns a hash code value for this bit set. The hash code of
* two bit sets containing the same integers is identical. The algorithm
* used to compute it is as follows:
*
* Suppose the bits in the BitSet were to be stored in an array of
* long integers called <code>bits</code>, in such a manner that
* bit <code>k</code> is set in the BitSet (for non-negative values
* of <code>k</code>) if and only if
*
* <code>((k/64) &lt; bits.length)
* && ((bits[k/64] & (1L &lt;&lt; (bit % 64))) != 0)
* </code>
*
* Then the following definition of the hashCode method
* would be a correct implementation of the actual algorithm:
*
*
<pre>public int hashCode()
{
long h = 1234;
for (int i = bits.length-1; i &gt;= 0; i--)
{
h ^= bits[i] * (i + 1);
}
return (int)((h >> 32) ^ h);
}</pre>
*
* Note that the hash code values changes, if the set is changed.
*
* @return the hash code value for this bit set.
*/
public int hashCode()
{
long h = 1234;
for (int i = bits.length; i > 0; )
h ^= i * bits[--i];
return (int) ((h >> 32) ^ h);
}
/**
* Returns true if the specified BitSet and this one share at least one
* common true bit.
*
* @param set the set to check for intersection
* @return true if the sets intersect
* @throws NullPointerException if set is null
* @since 1.4
*/
public boolean intersects(BitSet set)
{
int i = Math.min(bits.length, set.bits.length);
while (--i >= 0)
if ((bits[i] & set.bits[i]) != 0)
return true;
return false;
}
/**
* Returns true if this set contains no true bits.
*
* @return true if all bits are false
* @since 1.4
*/
public boolean isEmpty()
{
for (int i = bits.length - 1; i >= 0; i--)
if (bits[i] != 0)
return false;
return true;
}
/**
* Returns the logical number of bits actually used by this bit
* set. It returns the index of the highest set bit plus one.
* Note that this method doesn't return the number of set bits.
*
* @return the index of the highest set bit plus one.
*/
public int length()
{
// Set i to highest index that contains a non-zero value.
int i;
for (i = bits.length - 1; i >= 0 && bits[i] == 0; --i)
;
// if i < 0 all bits are cleared.
if (i < 0)
return 0;
// Now determine the exact length.
long b = bits[i];
int len = (i + 1) * 64;
// b >= 0 checks if the highest bit is zero.
while (b >= 0)
{
--len;
b <<= 1;
}
return len;
}
/**
* Returns the index of the next false bit, from the specified bit
* (inclusive).
*
* @param from the start location
* @return the first false bit
* @throws IndexOutOfBoundsException if from is negative
* @since 1.4
*/
public int nextClearBit(int from)
{
int offset = from >> 6;
long mask = 1L << from;
while (offset < bits.length)
{
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
// so we'll just let that be our exception.
long h = bits[offset];
do
{
if ((h & mask) == 0)
return from;
mask <<= 1;
from++;
}
while (mask != 0);
mask = 1;
offset++;
}
return from;
}
/**
* Returns the index of the next true bit, from the specified bit
* (inclusive). If there is none, -1 is returned. You can iterate over
* all true bits with this loop:<br>
*
<pre>for (int i = bs.nextSetBit(0); i &gt;= 0; i = bs.nextSetBit(i + 1))
{
// operate on i here
}</pre>
*
* @param from the start location
* @return the first true bit, or -1
* @throws IndexOutOfBoundsException if from is negative
* @since 1.4
*/
public int nextSetBit(int from)
{
int offset = from >> 6;
long mask = 1L << from;
while (offset < bits.length)
{
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
// so we'll just let that be our exception.
long h = bits[offset];
do
{
if ((h & mask) != 0)
return from;
mask <<= 1;
from++;
}
while (mask != 0);
mask = 1;
offset++;
}
return -1;
}
/**
* Performs the logical OR operation on this bit set and the
* given <code>set</code>. This means it builds the union
* of the two sets. The result is stored into this bit set, which
* grows as necessary.
*
* @param bs the second bit set
* @throws NullPointerException if bs is null
*/
public void or(BitSet bs)
{
ensure(bs.bits.length - 1);
for (int i = bs.bits.length - 1; i >= 0; i--)
bits[i] |= bs.bits[i];
}
/**
* Add the integer <code>bitIndex</code> to this set. That is
* the corresponding bit is set to true. If the index was already in
* the set, this method does nothing. The size of this structure
* is automatically increased as necessary.
*
* @param pos a non-negative integer.
* @throws IndexOutOfBoundsException if pos is negative
*/
public void set(int pos)
{
int offset = pos >> 6;
ensure(offset);
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
// so we'll just let that be our exception.
bits[offset] |= 1L << pos;
}
/**
* Sets the bit at the given index to the specified value. The size of
* this structure is automatically increased as necessary.
*
* @param index the position to set
* @param value the value to set it to
* @throws IndexOutOfBoundsException if index is negative
* @since 1.4
*/
public void set(int index, boolean value)
{
if (value)
set(index);
else
clear(index);
}
/**
* Sets the bits between from (inclusive) and to (exclusive) to true.
*
* @param from the start range (inclusive)
* @param to the end range (exclusive)
* @throws IndexOutOfBoundsException if from &lt; 0 || from &gt; to ||
* to &lt; 0
* @since 1.4
*/
public void set(int from, int to)
{
if (from < 0 || from > to)
throw new IndexOutOfBoundsException();
if (from == to)
return;
int lo_offset = from >>> 6;
int hi_offset = to >>> 6;
ensure(hi_offset);
if (lo_offset == hi_offset)
{
bits[hi_offset] |= (-1L << from) & ((1L << to) - 1);
return;
}
bits[lo_offset] |= -1L << from;
bits[hi_offset] |= (1L << to) - 1;
for (int i = lo_offset + 1; i < hi_offset; i++)
bits[i] = -1;
}
/**
* Sets the bits between from (inclusive) and to (exclusive) to the
* specified value.
*
* @param from the start range (inclusive)
* @param to the end range (exclusive)
* @param value the value to set it to
* @throws IndexOutOfBoundsException if from &lt; 0 || from &gt; to ||
* to &lt; 0
* @since 1.4
*/
public void set(int from, int to, boolean value)
{
if (value)
set(from, to);
else
clear(from, to);
}
/**
* Returns the number of bits actually used by this bit set. Note
* that this method doesn't return the number of set bits, and that
* future requests for larger bits will make this automatically grow.
*
* @return the number of bits currently used.
*/
public int size()
{
return bits.length * 64;
}
/**
* Returns the string representation of this bit set. This
* consists of a comma separated list of the integers in this set
* surrounded by curly braces. There is a space after each comma.
* A sample string is thus "{1, 3, 53}".
* @return the string representation.
*/
public String toString()
{
StringBuffer r = new StringBuffer("{");
boolean first = true;
for (int i = 0; i < bits.length; ++i)
{
long bit = 1;
long word = bits[i];
if (word == 0)
continue;
for (int j = 0; j < 64; ++j)
{
if ((word & bit) != 0)
{
if (! first)
r.append(", ");
r.append(64 * i + j);
first = false;
}
bit <<= 1;
}
}
return r.append("}").toString();
}
/**
* Performs the logical XOR operation on this bit set and the
* given <code>set</code>. This means it builds the symmetric
* remainder of the two sets (the elements that are in one set,
* but not in the other). The result is stored into this bit set,
* which grows as necessary.
*
* @param bs the second bit set
* @throws NullPointerException if bs is null
*/
public void xor(BitSet bs)
{
ensure(bs.bits.length - 1);
for (int i = bs.bits.length - 1; i >= 0; i--)
bits[i] ^= bs.bits[i];
}
/**
* Make sure the vector is big enough.
*
* @param lastElt the size needed for the bits array
*/
private void ensure(int lastElt)
{
if (lastElt >= bits.length)
{
long[] nd = new long[lastElt + 1];
System.arraycopy(bits, 0, nd, 0, bits.length);
bits = nd;
}
}
}
-288
View File
@@ -1,288 +0,0 @@
/* Collection.java -- Interface that represents a collection of objects
Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* Interface that represents a collection of objects. This interface is the
* root of the collection hierarchy, and does not provide any guarantees about
* the order of its elements or whether or not duplicate elements are
* permitted.
* <p>
* All methods of this interface that are defined to modify the collection are
* defined as <dfn>optional</dfn>. An optional operation may throw an
* UnsupportedOperationException if the data backing this collection does not
* support such a modification. This may mean that the data structure is
* immutable, or that it is read-only but may change ("unmodifiable"), or
* that it is modifiable but of fixed size (such as an array), or any number
* of other combinations.
* <p>
* A class that wishes to implement this interface should consider subclassing
* AbstractCollection, which provides basic implementations of most of the
* methods of this interface. Classes that are prepared to make guarantees
* about ordering or about absence of duplicate elements should consider
* implementing List or Set respectively, both of which are subinterfaces of
* Collection.
* <p>
* A general-purpose implementation of the Collection interface should in most
* cases provide at least two constructors: One which takes no arguments and
* creates an empty collection, and one which takes a Collection as an argument
* and returns a collection containing the same elements (that is, creates a
* copy of the argument using its own implementation).
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see List
* @see Set
* @see Map
* @see SortedSet
* @see SortedMap
* @see HashSet
* @see TreeSet
* @see ArrayList
* @see LinkedList
* @see Vector
* @see Collections
* @see Arrays
* @see AbstractCollection
* @since 1.2
* @status updated to 1.4
*/
public interface Collection
{
/**
* Add an element to this collection.
*
* @param o the object to add.
* @return true if the collection was modified as a result of this action.
* @throws UnsupportedOperationException if this collection does not
* support the add operation.
* @throws ClassCastException if o cannot be added to this collection due
* to its type.
* @throws NullPointerException if o is null and this collection doesn't
* support the addition of null values.
* @throws IllegalArgumentException if o cannot be added to this
* collection for some other reason.
*/
boolean add(Object o);
/**
* Add the contents of a given collection to this collection.
*
* @param c the collection to add.
* @return true if the collection was modified as a result of this action.
* @throws UnsupportedOperationException if this collection does not
* support the addAll operation.
* @throws ClassCastException if some element of c cannot be added to this
* collection due to its type.
* @throws NullPointerException if some element of c is null and this
* collection does not support the addition of null values.
* @throws NullPointerException if c itself is null.
* @throws IllegalArgumentException if some element of c cannot be added
* to this collection for some other reason.
*/
boolean addAll(Collection c);
/**
* Clear the collection, such that a subsequent call to isEmpty() would
* return true.
*
* @throws UnsupportedOperationException if this collection does not
* support the clear operation.
*/
void clear();
/**
* Test whether this collection contains a given object as one of its
* elements.
*
* @param o the element to look for.
* @return true if this collection contains at least one element e such that
* <code>o == null ? e == null : o.equals(e)</code>.
* @throws ClassCastException if the type of o is not a valid type for this
* collection.
* @throws NullPointerException if o is null and this collection doesn't
* support null values.
*/
boolean contains(Object o);
/**
* Test whether this collection contains every element in a given collection.
*
* @param c the collection to test for.
* @return true if for every element o in c, contains(o) would return true.
* @throws ClassCastException if the type of any element in c is not a valid
* type for this collection.
* @throws NullPointerException if some element of c is null and this
* collection does not support null values.
* @throws NullPointerException if c itself is null.
*/
boolean containsAll(Collection c);
/**
* Test whether this collection is equal to some object. The Collection
* interface does not explicitly require any behaviour from this method, and
* it may be left to the default implementation provided by Object. The Set
* and List interfaces do, however, require specific behaviour from this
* method.
* <p>
* If an implementation of Collection, which is not also an implementation of
* Set or List, should choose to implement this method, it should take care
* to obey the contract of the equals method of Object. In particular, care
* should be taken to return false when o is a Set or a List, in order to
* preserve the symmetry of the relation.
*
* @param o the object to compare to this collection.
* @return true if the o is equal to this collection.
*/
boolean equals(Object o);
/**
* Obtain a hash code for this collection. The Collection interface does not
* explicitly require any behaviour from this method, and it may be left to
* the default implementation provided by Object. The Set and List interfaces
* do, however, require specific behaviour from this method.
* <p>
* If an implementation of Collection, which is not also an implementation of
* Set or List, should choose to implement this method, it should take care
* to obey the contract of the hashCode method of Object. Note that this
* method renders it impossible to correctly implement both Set and List, as
* the required implementations are mutually exclusive.
*
* @return a hash code for this collection.
*/
int hashCode();
/**
* Test whether this collection is empty, that is, if size() == 0.
*
* @return true if this collection contains no elements.
*/
boolean isEmpty();
/**
* Obtain an Iterator over this collection.
*
* @return an Iterator over the elements of this collection, in any order.
*/
Iterator iterator();
/**
* Remove a single occurrence of an object from this collection. That is,
* remove an element e, if one exists, such that <code>o == null ? e == null
* : o.equals(e)</code>.
*
* @param o the object to remove.
* @return true if the collection changed as a result of this call, that is,
* if the collection contained at least one occurrence of o.
* @throws UnsupportedOperationException if this collection does not
* support the remove operation.
* @throws ClassCastException if the type of o is not a valid type
* for this collection.
* @throws NullPointerException if o is null and the collection doesn't
* support null values.
*/
boolean remove(Object o);
/**
* Remove all elements of a given collection from this collection. That is,
* remove every element e such that c.contains(e).
*
* @param c The collection of objects to be removed.
* @return true if this collection was modified as a result of this call.
* @throws UnsupportedOperationException if this collection does not
* support the removeAll operation.
* @throws ClassCastException if the type of any element in c is not a valid
* type for this collection.
* @throws NullPointerException if some element of c is null and this
* collection does not support removing null values.
* @throws NullPointerException if c itself is null.
*/
boolean removeAll(Collection c);
/**
* Remove all elements of this collection that are not contained in a given
* collection. That is, remove every element e such that !c.contains(e).
*
* @param c The collection of objects to be retained.
* @return true if this collection was modified as a result of this call.
* @throws UnsupportedOperationException if this collection does not
* support the retainAll operation.
* @throws ClassCastException if the type of any element in c is not a valid
* type for this collection.
* @throws NullPointerException if some element of c is null and this
* collection does not support retaining null values.
* @throws NullPointerException if c itself is null.
*/
boolean retainAll(Collection c);
/**
* Get the number of elements in this collection.
*
* @return the number of elements in the collection.
*/
int size();
/**
* Copy the current contents of this collection into an array.
*
* @return an array of type Object[] and length equal to the size of this
* collection, containing the elements currently in this collection, in
* any order.
*/
Object[] toArray();
/**
* Copy the current contents of this collection into an array. If the array
* passed as an argument has length less than the size of this collection, an
* array of the same run-time type as a, and length equal to the size of this
* collection, is allocated using Reflection. Otherwise, a itself is used.
* The elements of this collection are copied into it, and if there is space
* in the array, the following element is set to null. The resultant array is
* returned.
* Note: The fact that the following element is set to null is only useful
* if it is known that this collection does not contain any null elements.
*
* @param a the array to copy this collection into.
* @return an array containing the elements currently in this collection, in
* any order.
* @throws ArrayStoreException if the type of any element of the
* collection is not a subtype of the element type of a.
*/
Object[] toArray(Object[] a);
}
File diff suppressed because it is too large Load Diff
-119
View File
@@ -1,119 +0,0 @@
/* Comparator.java -- Interface for objects that specify an ordering
Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* Interface for objects that specify an ordering between objects. The ordering
* should be <em>total</em>, such that any two objects of the correct type
* can be compared, and the comparison is reflexive, anti-symmetric, and
* transitive. It is also recommended that the comparator be <em>consistent
* with equals</em>, although this is not a strict requirement. A relation
* is consistent with equals if these two statements always have the same
* results (if no exceptions occur):<br>
* <code>compare((Object) e1, (Object) e2) == 0</code> and
* <code>e1.equals((Object) e2)</code><br>
* Comparators that violate consistency with equals may cause strange behavior
* in sorted lists and sets. For example, a case-sensitive dictionary order
* comparison of Strings is consistent with equals, but if it is
* case-insensitive it is not, because "abc" and "ABC" compare as equal even
* though "abc".equals("ABC") returns false.
* <P>
* In general, Comparators should be Serializable, because when they are passed
* to Serializable data structures such as SortedMap or SortedSet, the entire
* data structure will only serialize correctly if the comparator is
* Serializable.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Comparable
* @see TreeMap
* @see TreeSet
* @see SortedMap
* @see SortedSet
* @see Arrays#sort(Object[], Comparator)
* @see java.io.Serializable
* @since 1.2
* @status updated to 1.4
*/
public interface Comparator
{
/**
* Return an integer that is negative, zero or positive depending on whether
* the first argument is less than, equal to or greater than the second
* according to this ordering. This method should obey the following
* contract:
* <ul>
* <li>if compare(a, b) &lt; 0 then compare(b, a) &gt; 0</li>
* <li>if compare(a, b) throws an exception, so does compare(b, a)</li>
* <li>if compare(a, b) &lt; 0 and compare(b, c) &lt; 0 then compare(a, c)
* &lt; 0</li>
* <li>if compare(a, b) == 0 then compare(a, c) and compare(b, c) must
* have the same sign</li>
* </ul>
* To be consistent with equals, the following additional constraint is
* in place:
* <ul>
* <li>if a.equals(b) or both a and b are null, then
* compare(a, b) == 0.</li>
* </ul><p>
*
* Although it is permissible for a comparator to provide an order
* inconsistent with equals, that should be documented.
*
* @param o1 the first object
* @param o2 the second object
* @return the comparison
* @throws ClassCastException if the elements are not of types that can be
* compared by this ordering.
*/
int compare(Object o1, Object o2);
/**
* Return true if the object is equal to this object. To be
* considered equal, the argument object must satisfy the constraints
* of <code>Object.equals()</code>, be a Comparator, and impose the
* same ordering as this Comparator. The default implementation
* inherited from Object is usually adequate.
*
* @param obj The object
* @return true if it is a Comparator that imposes the same order
* @see Object#equals(Object)
*/
boolean equals(Object obj);
}
@@ -1,92 +0,0 @@
/* ConcurrentModificationException.java -- Data structure concurrently modified
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
*/
/**
* Exception that is thrown by the collections classes when it is detected that
* a modification has been made to a data structure when this is not allowed,
* such as when a collection is structurally modified while an Iterator is
* operating over it. In cases where this can be detected, a
* ConcurrentModificationException will be thrown. An Iterator that detects
* this condition is referred to as fail-fast. Notice that this can occur
* even in single-threaded designs, if you call methods out of order.
*
* @author Warren Levy (warrenl@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see Iterator
* @see ListIterator
* @see Vector
* @see LinkedList
* @see HashSet
* @see Hashtable
* @see TreeMap
* @see AbstractList
* @since 1.2
* @status updated to 1.4
*/
public class ConcurrentModificationException extends RuntimeException
{
/**
* Compatible with JDK 1.2.
*/
private static final long serialVersionUID = -3666751008965953603L;
/**
* Constructs a ConcurrentModificationException with no detail message.
*/
public ConcurrentModificationException()
{
}
/**
* Constructs a ConcurrentModificationException with a detail message.
*
* @param detail the detail message for the exception
*/
public ConcurrentModificationException(String detail)
{
super(detail);
}
}
-136
View File
@@ -1,136 +0,0 @@
/* Dictionary.java -- an abstract (and essentially worthless)
class which is Hashtable's superclass
Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* A Dictionary maps keys to values; <i>how</i> it does that is
* implementation-specific.
*
* This is an abstract class which has really gone by the wayside.
* People at Javasoft are probably embarrassed by it. At this point,
* it might as well be an interface rather than a class, but it remains
* this poor, laughable skeleton for the sake of backwards compatibility.
* At any rate, this was what came before the {@link Map} interface
* in the Collections framework.
*
* @author Jon Zeppieri
* @author Eric Blake (ebb9@email.byu.edu)
* @see Map
* @see Hashtable
* @since 1.0
* @status updated to 1.4
*/
public abstract class Dictionary
{
// WARNING: Dictionary is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
/**
* Sole constructor (often called implicitly).
*/
public Dictionary()
{
}
/**
* Returns an Enumeration of the values in this Dictionary.
*
* @return an Enumeration of the values
* @see #keys()
*/
public abstract Enumeration elements();
/**
* Returns the value associated with the supplied key, or null
* if no such value exists. Since Dictionaries are not allowed null keys
* or elements, a null result always means the key is not present.
*
* @param key the key to use to fetch the value
* @return the mapped value
* @throws NullPointerException if key is null
* @see #put(Object, Object)
*/
public abstract Object get(Object key);
/**
* Returns true when there are no elements in this Dictionary.
*
* @return <code>size() == 0</code>
*/
public abstract boolean isEmpty();
/**
* Returns an Enumeration of the keys in this Dictionary
*
* @return an Enumeration of the keys
* @see #elements()
*/
public abstract Enumeration keys();
/**
* Inserts a new value into this Dictionary, located by the
* supplied key. Dictionary does not support null keys or values, so
* a null return can safely be interpreted as adding a new key.
*
* @param key the key which locates the value
* @param value the value to put into the Dictionary
* @return the previous value of the key, or null if there was none
* @throws NullPointerException if key or value is null
* @see #get(Object)
*/
public abstract Object put(Object key, Object value);
/**
* Removes from the Dictionary the value located by the given key. A null
* return safely means that the key was not mapped in the Dictionary.
*
* @param key the key used to locate the value to be removed
* @return the value associated with the removed key
* @throws NullPointerException if key is null
*/
public abstract Object remove(Object key);
/**
* Returns the number of values currently in this Dictionary.
*
* @return the number of keys in the Dictionary
*/
public abstract int size();
} // class Dictionary
@@ -1,69 +0,0 @@
/* EmptyStackException.java -- Attempt to pop from an empty stack
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
*/
/**
* This exception is thrown by the Stack class when an attempt is made to pop
* or otherwise access elements from an empty stack.
*
* @author Warren Levy (warrenl@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
* @see Stack
* @since 1.0
* @status updated to 1.4
*/
public class EmptyStackException extends RuntimeException
{
/**
* Compatible with JDK 1.0.
*/
private static final long serialVersionUID = 5084686378493302095L;
/**
* Constructs an EmptyStackException with no detail message.
*/
public EmptyStackException()
{
}
}
-81
View File
@@ -1,81 +0,0 @@
/* Enumeration.java -- Interface for enumerating lists of objects
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1.
* Status: Believed complete and correct
*/
/**
* Interface for lists of objects that can be returned in sequence. Successive
* objects are obtained by the nextElement method.
* <p>
* As of Java 1.2, the Iterator interface provides the same functionality, but
* with shorter method names and a new optional method to remove items from the
* list. If writing for 1.2, consider using Iterator instead. Enumerations over
* the new collections classes, for use with legacy APIs that require them, can
* be obtained by the enumeration method in class Collections.
*
* @author Warren Levy (warrenl@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
* @see Iterator
* @see Hashtable
* @see Vector
* @since 1.0
* @status updated to 1.4
*/
public interface Enumeration
{
/**
* Tests whether there are elements remaining in the enumeration.
*
* @return true if there is at least one more element in the enumeration,
* that is, if the next call to nextElement will not throw a
* NoSuchElementException.
*/
boolean hasMoreElements();
/**
* Obtain the next element in the enumeration.
*
* @return the next element in the enumeration
* @throws NoSuchElementException if there are no more elements
*/
Object nextElement();
}
-54
View File
@@ -1,54 +0,0 @@
/* EventListener.java -- tagging interface for all event listeners
Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* Empty interface that is implemented by classes that need to receive
* events. Subinterfaces define methods that can be called to fire an
* event notification. Normally the name of these subinterfaces end in
* <code>Listener</code> and all method described by the subinterface
* take as argument an subclass of <code>EventObject</code>.
*
* @author Tom Tromey (tromey@cygnus.com)
* @see EventObject
* @status updated to 1.4
*/
public interface EventListener
{
}
-75
View File
@@ -1,75 +0,0 @@
/* EventListenerProxy.java -- abstract wrapper for event listeners
Copyright (C) 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* An abstract wrapper for event listeners. This allows subclasses to
* attach additional parameters to an existing event listener to create
* a new one. Subclasses are expected to add methods to set and retrieve
* any attached properties.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.4
* @status updated to 1.4
*/
public abstract class EventListenerProxy implements EventListener
{
/** The listener that this proxy wraps. */
private final EventListener listener;
/**
* Construct a proxy event listener, given an existing one to augment.
*
* @param listener the listener to wrap
*/
public EventListenerProxy(EventListener listener)
{
this.listener = listener;
}
/**
* Return the wrapped event listener.
*
* @return the listener associated with this proxy
*/
public EventListener getListener()
{
return listener;
}
} // class EventListenerProxy
-101
View File
@@ -1,101 +0,0 @@
/* EventObject.java -- represents an event on an object
Copyright (C) 1999, 2000, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.Serializable;
/**
* Represents Events fired by Objects.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @see EventListener
* @since 1.1
* @status updated to 1.4
*/
public class EventObject implements Serializable
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = 5516075349620653480L;
/**
* The source object; in other words, the object which this event takes
* place on.
*/
protected transient Object source;
/**
* Constructs an EventObject with the specified source.
*
* @param source the source of the event
* @throws IllegalArgumentException if source is null (This is not
* specified, but matches the behavior of the JDK)
*/
public EventObject(Object source)
{
// This check for null is stupid, if you ask me, since source is
// protected and non-final, so a subclass can set it to null later on.
if (source == null)
throw new IllegalArgumentException();
this.source = source;
}
/**
* Returns the source of the event.
*
* @return the event source
*/
public Object getSource()
{
return source;
}
/**
* Converts the event to a String. The format is not specified, but by
* observation, the JDK uses:
* <code>getClass().getName() + "[source=" + source + "]";</code>.
*
* @return String representation of the Event
*/
public String toString()
{
return getClass().getName() + "[source=" + source + "]";
}
} // class EventObject
-906
View File
@@ -1,906 +0,0 @@
/* HashMap.java -- a class providing a basic hashtable data structure,
mapping Object --> Object
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
// NOTE: This implementation is very similar to that of Hashtable. If you fix
// a bug in here, chances are you should make a similar change to the Hashtable
// code.
// NOTE: This implementation has some nasty coding style in order to
// support LinkedHashMap, which extends this.
/**
* This class provides a hashtable-backed implementation of the
* Map interface.
* <p>
*
* It uses a hash-bucket approach; that is, hash collisions are handled
* by linking the new node off of the pre-existing node (or list of
* nodes). In this manner, techniques such as linear probing (which
* can cause primary clustering) and rehashing (which does not fit very
* well with Java's method of precomputing hash codes) are avoided.
* <p>
*
* Under ideal circumstances (no collisions), HashMap offers O(1)
* performance on most operations (<code>containsValue()</code> is,
* of course, O(n)). In the worst case (all keys map to the same
* hash code -- very unlikely), most operations are O(n).
* <p>
*
* HashMap is part of the JDK1.2 Collections API. It differs from
* Hashtable in that it accepts the null key and null values, and it
* does not support "Enumeration views." Also, it is not synchronized;
* if you plan to use it in multiple threads, consider using:<br>
* <code>Map m = Collections.synchronizedMap(new HashMap(...));</code>
* <p>
*
* The iterators are <i>fail-fast</i>, meaning that any structural
* modification, except for <code>remove()</code> called on the iterator
* itself, cause the iterator to throw a
* <code>ConcurrentModificationException</code> rather than exhibit
* non-deterministic behavior.
*
* @author Jon Zeppieri
* @author Jochen Hoenicke
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
* @see Object#hashCode()
* @see Collection
* @see Map
* @see TreeMap
* @see LinkedHashMap
* @see IdentityHashMap
* @see Hashtable
* @since 1.2
* @status updated to 1.4
*/
public class HashMap extends AbstractMap
implements Map, Cloneable, Serializable
{
/**
* Default number of buckets. This is the value the JDK 1.3 uses. Some
* early documentation specified this value as 101. That is incorrect.
* Package visible for use by HashSet.
*/
static final int DEFAULT_CAPACITY = 11;
/**
* The default load factor; this is explicitly specified by the spec.
* Package visible for use by HashSet.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* Compatible with JDK 1.2.
*/
private static final long serialVersionUID = 362498820763181265L;
/**
* The rounded product of the capacity and the load factor; when the number
* of elements exceeds the threshold, the HashMap calls
* <code>rehash()</code>.
* @serial the threshold for rehashing
*/
private int threshold;
/**
* Load factor of this HashMap: used in computing the threshold.
* Package visible for use by HashSet.
* @serial the load factor
*/
final float loadFactor;
/**
* Array containing the actual key-value mappings.
* Package visible for use by nested and subclasses.
*/
transient HashEntry[] buckets;
/**
* Counts the number of modifications this HashMap has undergone, used
* by Iterators to know when to throw ConcurrentModificationExceptions.
* Package visible for use by nested and subclasses.
*/
transient int modCount;
/**
* The size of this HashMap: denotes the number of key-value pairs.
* Package visible for use by nested and subclasses.
*/
transient int size;
/**
* The cache for {@link #entrySet()}.
*/
private transient Set entries;
/**
* Class to represent an entry in the hash table. Holds a single key-value
* pair. Package visible for use by subclass.
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
static class HashEntry extends AbstractMap.BasicMapEntry
{
/**
* The next entry in the linked list. Package visible for use by subclass.
*/
HashEntry next;
/**
* Simple constructor.
* @param key the key
* @param value the value
*/
HashEntry(Object key, Object value)
{
super(key, value);
}
/**
* Called when this entry is accessed via {@link #put(Object, Object)}.
* This version does nothing, but in LinkedHashMap, it must do some
* bookkeeping for access-traversal mode.
*/
void access()
{
}
/**
* Called when this entry is removed from the map. This version simply
* returns the value, but in LinkedHashMap, it must also do bookkeeping.
*
* @return the value of this key as it is removed
*/
Object cleanup()
{
return value;
}
}
/**
* Construct a new HashMap with the default capacity (11) and the default
* load factor (0.75).
*/
public HashMap()
{
this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
}
/**
* Construct a new HashMap from the given Map, with initial capacity
* the greater of the size of <code>m</code> or the default of 11.
* <p>
*
* Every element in Map m will be put into this new HashMap.
*
* @param m a Map whose key / value pairs will be put into the new HashMap.
* <b>NOTE: key / value pairs are not cloned in this constructor.</b>
* @throws NullPointerException if m is null
*/
public HashMap(Map m)
{
this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
putAll(m);
}
/**
* Construct a new HashMap with a specific inital capacity and
* default load factor of 0.75.
*
* @param initialCapacity the initial capacity of this HashMap (&gt;=0)
* @throws IllegalArgumentException if (initialCapacity &lt; 0)
*/
public HashMap(int initialCapacity)
{
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
/**
* Construct a new HashMap with a specific inital capacity and load factor.
*
* @param initialCapacity the initial capacity (&gt;=0)
* @param loadFactor the load factor (&gt; 0, not NaN)
* @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
* ! (loadFactor &gt; 0.0)
*/
public HashMap(int initialCapacity, float loadFactor)
{
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "
+ initialCapacity);
if (! (loadFactor > 0)) // check for NaN too
throw new IllegalArgumentException("Illegal Load: " + loadFactor);
if (initialCapacity == 0)
initialCapacity = 1;
buckets = new HashEntry[initialCapacity];
this.loadFactor = loadFactor;
threshold = (int) (initialCapacity * loadFactor);
}
/**
* Returns the number of kay-value mappings currently in this Map.
*
* @return the size
*/
public int size()
{
return size;
}
/**
* Returns true if there are no key-value mappings currently in this Map.
*
* @return <code>size() == 0</code>
*/
public boolean isEmpty()
{
return size == 0;
}
/**
* Return the value in this HashMap associated with the supplied key,
* or <code>null</code> if the key maps to nothing. NOTE: Since the value
* could also be null, you must use containsKey to see if this key
* actually maps to something.
*
* @param key the key for which to fetch an associated value
* @return what the key maps to, if present
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
public Object get(Object key)
{
int idx = hash(key);
HashEntry e = buckets[idx];
while (e != null)
{
if (equals(key, e.key))
return e.value;
e = e.next;
}
return null;
}
/**
* Returns true if the supplied object <code>equals()</code> a key
* in this HashMap.
*
* @param key the key to search for in this HashMap
* @return true if the key is in the table
* @see #containsValue(Object)
*/
public boolean containsKey(Object key)
{
int idx = hash(key);
HashEntry e = buckets[idx];
while (e != null)
{
if (equals(key, e.key))
return true;
e = e.next;
}
return false;
}
/**
* Puts the supplied value into the Map, mapped by the supplied key.
* The value may be retrieved by any object which <code>equals()</code>
* this key. NOTE: Since the prior value could also be null, you must
* first use containsKey if you want to see if you are replacing the
* key's mapping.
*
* @param key the key used to locate the value
* @param value the value to be stored in the HashMap
* @return the prior mapping of the key, or null if there was none
* @see #get(Object)
* @see Object#equals(Object)
*/
public Object put(Object key, Object value)
{
int idx = hash(key);
HashEntry e = buckets[idx];
while (e != null)
{
if (equals(key, e.key))
{
e.access(); // Must call this for bookkeeping in LinkedHashMap.
Object r = e.value;
e.value = value;
return r;
}
else
e = e.next;
}
// At this point, we know we need to add a new entry.
modCount++;
if (++size > threshold)
{
rehash();
// Need a new hash value to suit the bigger table.
idx = hash(key);
}
// LinkedHashMap cannot override put(), hence this call.
addEntry(key, value, idx, true);
return null;
}
/**
* Copies all elements of the given map into this hashtable. If this table
* already has a mapping for a key, the new mapping replaces the current
* one.
*
* @param m the map to be hashed into this
*/
public void putAll(Map m)
{
Iterator itr = m.entrySet().iterator();
while (itr.hasNext())
{
Map.Entry e = (Map.Entry) itr.next();
// Optimize in case the Entry is one of our own.
if (e instanceof AbstractMap.BasicMapEntry)
{
AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
put(entry.key, entry.value);
}
else
put(e.getKey(), e.getValue());
}
}
/**
* Removes from the HashMap and returns the value which is mapped by the
* supplied key. If the key maps to nothing, then the HashMap remains
* unchanged, and <code>null</code> is returned. NOTE: Since the value
* could also be null, you must use containsKey to see if you are
* actually removing a mapping.
*
* @param key the key used to locate the value to remove
* @return whatever the key mapped to, if present
*/
public Object remove(Object key)
{
int idx = hash(key);
HashEntry e = buckets[idx];
HashEntry last = null;
while (e != null)
{
if (equals(key, e.key))
{
modCount++;
if (last == null)
buckets[idx] = e.next;
else
last.next = e.next;
size--;
// Method call necessary for LinkedHashMap to work correctly.
return e.cleanup();
}
last = e;
e = e.next;
}
return null;
}
/**
* Clears the Map so it has no keys. This is O(1).
*/
public void clear()
{
if (size != 0)
{
modCount++;
Arrays.fill(buckets, null);
size = 0;
}
}
/**
* Returns true if this HashMap contains a value <code>o</code>, such that
* <code>o.equals(value)</code>.
*
* @param value the value to search for in this HashMap
* @return true if at least one key maps to the value
* @see containsKey(Object)
*/
public boolean containsValue(Object value)
{
for (int i = buckets.length - 1; i >= 0; i--)
{
HashEntry e = buckets[i];
while (e != null)
{
if (equals(value, e.value))
return true;
e = e.next;
}
}
return false;
}
/**
* Returns a shallow clone of this HashMap. The Map itself is cloned,
* but its contents are not. This is O(n).
*
* @return the clone
*/
public Object clone()
{
HashMap copy = null;
try
{
copy = (HashMap) super.clone();
}
catch (CloneNotSupportedException x)
{
// This is impossible.
}
copy.buckets = new HashEntry[buckets.length];
copy.putAllInternal(this);
// Clear the entry cache. AbstractMap.clone() does the others.
copy.entries = null;
return copy;
}
/**
* Returns a "set view" of this HashMap's keys. The set is backed by the
* HashMap, so changes in one show up in the other. The set supports
* element removal, but not element addition.
*
* @return a set view of the keys
* @see #values()
* @see #entrySet()
*/
public Set keySet()
{
if (keys == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overridden easily and efficiently.
keys = new AbstractSet()
{
public int size()
{
return size;
}
public Iterator iterator()
{
// Cannot create the iterator directly, because of LinkedHashMap.
return HashMap.this.iterator(KEYS);
}
public void clear()
{
HashMap.this.clear();
}
public boolean contains(Object o)
{
return containsKey(o);
}
public boolean remove(Object o)
{
// Test against the size of the HashMap to determine if anything
// really got removed. This is necessary because the return value
// of HashMap.remove() is ambiguous in the null case.
int oldsize = size;
HashMap.this.remove(o);
return oldsize != size;
}
};
return keys;
}
/**
* Returns a "collection view" (or "bag view") of this HashMap's values.
* The collection is backed by the HashMap, so changes in one show up
* in the other. The collection supports element removal, but not element
* addition.
*
* @return a bag view of the values
* @see #keySet()
* @see #entrySet()
*/
public Collection values()
{
if (values == null)
// We don't bother overriding many of the optional methods, as doing so
// wouldn't provide any significant performance advantage.
values = new AbstractCollection()
{
public int size()
{
return size;
}
public Iterator iterator()
{
// Cannot create the iterator directly, because of LinkedHashMap.
return HashMap.this.iterator(VALUES);
}
public void clear()
{
HashMap.this.clear();
}
};
return values;
}
/**
* Returns a "set view" of this HashMap's entries. The set is backed by
* the HashMap, so changes in one show up in the other. The set supports
* element removal, but not element addition.<p>
*
* Note that the iterators for all three views, from keySet(), entrySet(),
* and values(), traverse the HashMap in the same sequence.
*
* @return a set view of the entries
* @see #keySet()
* @see #values()
* @see Map.Entry
*/
public Set entrySet()
{
if (entries == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overridden easily and efficiently.
entries = new AbstractSet()
{
public int size()
{
return size;
}
public Iterator iterator()
{
// Cannot create the iterator directly, because of LinkedHashMap.
return HashMap.this.iterator(ENTRIES);
}
public void clear()
{
HashMap.this.clear();
}
public boolean contains(Object o)
{
return getEntry(o) != null;
}
public boolean remove(Object o)
{
HashEntry e = getEntry(o);
if (e != null)
{
HashMap.this.remove(e.key);
return true;
}
return false;
}
};
return entries;
}
/**
* Helper method for put, that creates and adds a new Entry. This is
* overridden in LinkedHashMap for bookkeeping purposes.
*
* @param key the key of the new Entry
* @param value the value
* @param idx the index in buckets where the new Entry belongs
* @param callRemove whether to call the removeEldestEntry method
* @see #put(Object, Object)
*/
void addEntry(Object key, Object value, int idx, boolean callRemove)
{
HashEntry e = new HashEntry(key, value);
e.next = buckets[idx];
buckets[idx] = e;
}
/**
* Helper method for entrySet(), which matches both key and value
* simultaneously.
*
* @param o the entry to match
* @return the matching entry, if found, or null
* @see #entrySet()
*/
// Package visible, for use in nested classes.
final HashEntry getEntry(Object o)
{
if (! (o instanceof Map.Entry))
return null;
Map.Entry me = (Map.Entry) o;
Object key = me.getKey();
int idx = hash(key);
HashEntry e = buckets[idx];
while (e != null)
{
if (equals(e.key, key))
return equals(e.value, me.getValue()) ? e : null;
e = e.next;
}
return null;
}
/**
* Helper method that returns an index in the buckets array for `key'
* based on its hashCode(). Package visible for use by subclasses.
*
* @param key the key
* @return the bucket number
*/
final int hash(Object key)
{
return key == null ? 0 : Math.abs(key.hashCode() % buckets.length);
}
/**
* Generates a parameterized iterator. Must be overrideable, since
* LinkedHashMap iterates in a different order.
*
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
* @return the appropriate iterator
*/
Iterator iterator(int type)
{
return new HashIterator(type);
}
/**
* A simplified, more efficient internal implementation of putAll(). clone()
* should not call putAll or put, in order to be compatible with the JDK
* implementation with respect to subclasses.
*
* @param m the map to initialize this from
*/
void putAllInternal(Map m)
{
Iterator itr = m.entrySet().iterator();
size = 0;
while (itr.hasNext())
{
size++;
Map.Entry e = (Map.Entry) itr.next();
Object key = e.getKey();
int idx = hash(key);
addEntry(key, e.getValue(), idx, false);
}
}
/**
* Increases the size of the HashMap and rehashes all keys to new
* array indices; this is called when the addition of a new value
* would cause size() &gt; threshold. Note that the existing Entry
* objects are reused in the new hash table.
*
* <p>This is not specified, but the new size is twice the current size
* plus one; this number is not always prime, unfortunately.
*/
private void rehash()
{
HashEntry[] oldBuckets = buckets;
int newcapacity = (buckets.length * 2) + 1;
threshold = (int) (newcapacity * loadFactor);
buckets = new HashEntry[newcapacity];
for (int i = oldBuckets.length - 1; i >= 0; i--)
{
HashEntry e = oldBuckets[i];
while (e != null)
{
int idx = hash(e.key);
HashEntry dest = buckets[idx];
HashEntry next = e.next;
e.next = buckets[idx];
buckets[idx] = e;
e = next;
}
}
}
/**
* Serializes this object to the given stream.
*
* @param s the stream to write to
* @throws IOException if the underlying stream fails
* @serialData the <i>capacity</i>(int) that is the length of the
* bucket array, the <i>size</i>(int) of the hash map
* are emitted first. They are followed by size entries,
* each consisting of a key (Object) and a value (Object).
*/
private void writeObject(ObjectOutputStream s) throws IOException
{
// Write the threshold and loadFactor fields.
s.defaultWriteObject();
s.writeInt(buckets.length);
s.writeInt(size);
// Avoid creating a wasted Set by creating the iterator directly.
Iterator it = iterator(ENTRIES);
while (it.hasNext())
{
HashEntry entry = (HashEntry) it.next();
s.writeObject(entry.key);
s.writeObject(entry.value);
}
}
/**
* Deserializes this object from the given stream.
*
* @param s the stream to read from
* @throws ClassNotFoundException if the underlying stream fails
* @throws IOException if the underlying stream fails
* @serialData the <i>capacity</i>(int) that is the length of the
* bucket array, the <i>size</i>(int) of the hash map
* are emitted first. They are followed by size entries,
* each consisting of a key (Object) and a value (Object).
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
// Read the threshold and loadFactor fields.
s.defaultReadObject();
// Read and use capacity, followed by key/value pairs.
buckets = new HashEntry[s.readInt()];
int len = s.readInt();
size = len;
while (len-- > 0)
{
Object key = s.readObject();
addEntry(key, s.readObject(), hash(key), false);
}
}
/**
* Iterate over HashMap's entries.
* This implementation is parameterized to give a sequential view of
* keys, values, or entries.
*
* @author Jon Zeppieri
*/
private final class HashIterator implements Iterator
{
/**
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
* or {@link #ENTRIES}.
*/
private final int type;
/**
* The number of modifications to the backing HashMap that we know about.
*/
private int knownMod = modCount;
/** The number of elements remaining to be returned by next(). */
private int count = size;
/** Current index in the physical hash table. */
private int idx = buckets.length;
/** The last Entry returned by a next() call. */
private HashEntry last;
/**
* The next entry that should be returned by next(). It is set to something
* if we're iterating through a bucket that contains multiple linked
* entries. It is null if next() needs to find a new bucket.
*/
private HashEntry next;
/**
* Construct a new HashIterator with the supplied type.
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
*/
HashIterator(int type)
{
this.type = type;
}
/**
* Returns true if the Iterator has more elements.
* @return true if there are more elements
* @throws ConcurrentModificationException if the HashMap was modified
*/
public boolean hasNext()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
return count > 0;
}
/**
* Returns the next element in the Iterator's sequential view.
* @return the next element
* @throws ConcurrentModificationException if the HashMap was modified
* @throws NoSuchElementException if there is none
*/
public Object next()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
if (count == 0)
throw new NoSuchElementException();
count--;
HashEntry e = next;
while (e == null)
e = buckets[--idx];
next = e.next;
last = e;
if (type == VALUES)
return e.value;
if (type == KEYS)
return e.key;
return e;
}
/**
* Removes from the backing HashMap the last element which was fetched
* with the <code>next()</code> method.
* @throws ConcurrentModificationException if the HashMap was modified
* @throws IllegalStateException if called when there is no last element
*/
public void remove()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
if (last == null)
throw new IllegalStateException();
HashMap.this.remove(last.key);
last = null;
knownMod++;
}
}
}
-293
View File
@@ -1,293 +0,0 @@
/* HashSet.java -- a class providing a HashMap-backed Set
Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* This class provides a HashMap-backed implementation of the Set interface.
* <p>
*
* Most operations are O(1), assuming no hash collisions. In the worst
* case (where all hashes collide), operations are O(n). Setting the
* initial capacity too low will force many resizing operations, but
* setting the initial capacity too high (or loadfactor too low) leads
* to wasted memory and slower iteration.
* <p>
*
* HashSet accepts the null key and null values. It is not synchronized,
* so if you need multi-threaded access, consider using:<br>
* <code>Set s = Collections.synchronizedSet(new HashSet(...));</code>
* <p>
*
* The iterators are <i>fail-fast</i>, meaning that any structural
* modification, except for <code>remove()</code> called on the iterator
* itself, cause the iterator to throw a
* {@link ConcurrentModificationException} rather than exhibit
* non-deterministic behavior.
*
* @author Jon Zeppieri
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see Set
* @see TreeSet
* @see Collections#synchronizedSet(Set)
* @see HashMap
* @see LinkedHashSet
* @since 1.2
* @status updated to 1.4
*/
public class HashSet extends AbstractSet
implements Set, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2.
*/
private static final long serialVersionUID = -5024744406713321676L;
/**
* The HashMap which backs this Set.
*/
private transient HashMap map;
/**
* Construct a new, empty HashSet whose backing HashMap has the default
* capacity (11) and loadFacor (0.75).
*/
public HashSet()
{
this(HashMap.DEFAULT_CAPACITY, HashMap.DEFAULT_LOAD_FACTOR);
}
/**
* Construct a new, empty HashSet whose backing HashMap has the supplied
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity of the backing HashMap
* @throws IllegalArgumentException if the capacity is negative
*/
public HashSet(int initialCapacity)
{
this(initialCapacity, HashMap.DEFAULT_LOAD_FACTOR);
}
/**
* Construct a new, empty HashSet whose backing HashMap has the supplied
* capacity and load factor.
*
* @param initialCapacity the initial capacity of the backing HashMap
* @param loadFactor the load factor of the backing HashMap
* @throws IllegalArgumentException if either argument is negative, or
* if loadFactor is POSITIVE_INFINITY or NaN
*/
public HashSet(int initialCapacity, float loadFactor)
{
map = init(initialCapacity, loadFactor);
}
/**
* Construct a new HashSet with the same elements as are in the supplied
* collection (eliminating any duplicates, of course). The backing storage
* has twice the size of the collection, or the default size of 11,
* whichever is greater; and the default load factor (0.75).
*
* @param c a collection of initial set elements
* @throws NullPointerException if c is null
*/
public HashSet(Collection c)
{
this(Math.max(2 * c.size(), HashMap.DEFAULT_CAPACITY));
addAll(c);
}
/**
* Adds the given Object to the set if it is not already in the Set.
* This set permits a null element.
*
* @param o the Object to add to this Set
* @return true if the set did not already contain o
*/
public boolean add(Object o)
{
return map.put(o, "") == null;
}
/**
* Empties this Set of all elements; this takes constant time.
*/
public void clear()
{
map.clear();
}
/**
* Returns a shallow copy of this Set. The Set itself is cloned; its
* elements are not.
*
* @return a shallow clone of the set
*/
public Object clone()
{
HashSet copy = null;
try
{
copy = (HashSet) super.clone();
}
catch (CloneNotSupportedException x)
{
// Impossible to get here.
}
copy.map = (HashMap) map.clone();
return copy;
}
/**
* Returns true if the supplied element is in this Set.
*
* @param o the Object to look for
* @return true if it is in the set
*/
public boolean contains(Object o)
{
return map.containsKey(o);
}
/**
* Returns true if this set has no elements in it.
*
* @return <code>size() == 0</code>.
*/
public boolean isEmpty()
{
return map.size == 0;
}
/**
* Returns an Iterator over the elements of this Set, which visits the
* elements in no particular order. For this class, the Iterator allows
* removal of elements. The iterator is fail-fast, and will throw a
* ConcurrentModificationException if the set is modified externally.
*
* @return a set iterator
* @see ConcurrentModificationException
*/
public Iterator iterator()
{
// Avoid creating intermediate keySet() object by using non-public API.
return map.iterator(HashMap.KEYS);
}
/**
* Removes the supplied Object from this Set if it is in the Set.
*
* @param o the object to remove
* @return true if an element was removed
*/
public boolean remove(Object o)
{
return (map.remove(o) != null);
}
/**
* Returns the number of elements in this Set (its cardinality).
*
* @return the size of the set
*/
public int size()
{
return map.size;
}
/**
* Helper method which initializes the backing Map. Overridden by
* LinkedHashSet for correct semantics.
*
* @param capacity the initial capacity
* @param load the initial load factor
* @return the backing HashMap
*/
HashMap init(int capacity, float load)
{
return new HashMap(capacity, load);
}
/**
* Serializes this object to the given stream.
*
* @param s the stream to write to
* @throws IOException if the underlying stream fails
* @serialData the <i>capacity</i> (int) and <i>loadFactor</i> (float)
* of the backing store, followed by the set size (int),
* then a listing of its elements (Object) in no order
*/
private void writeObject(ObjectOutputStream s) throws IOException
{
s.defaultWriteObject();
// Avoid creating intermediate keySet() object by using non-public API.
Iterator it = map.iterator(HashMap.KEYS);
s.writeInt(map.buckets.length);
s.writeFloat(map.loadFactor);
s.writeInt(map.size);
while (it.hasNext())
s.writeObject(it.next());
}
/**
* Deserializes this object from the given stream.
*
* @param s the stream to read from
* @throws ClassNotFoundException if the underlying stream fails
* @throws IOException if the underlying stream fails
* @serialData the <i>capacity</i> (int) and <i>loadFactor</i> (float)
* of the backing store, followed by the set size (int),
* then a listing of its elements (Object) in no order
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
map = init(s.readInt(), s.readFloat());
for (int size = s.readInt(); size > 0; size--)
map.put(s.readObject(), "");
}
}
File diff suppressed because it is too large Load Diff
-935
View File
@@ -1,935 +0,0 @@
/* IdentityHashMap.java -- a class providing a hashtable data structure,
mapping Object --> Object, which uses object identity for hashing.
Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* This class provides a hashtable-backed implementation of the
* Map interface, but uses object identity to do its hashing. In fact,
* it uses object identity for comparing values, as well. It uses a
* linear-probe hash table, which may have faster performance
* than the chaining employed by HashMap.
* <p>
*
* <em>WARNING: This is not a general purpose map. Because it uses
* System.identityHashCode and ==, instead of hashCode and equals, for
* comparison, it violated Map's general contract, and may cause
* undefined behavior when compared to other maps which are not
* IdentityHashMaps. This is designed only for the rare cases when
* identity semantics are needed.</em> An example use is
* topology-preserving graph transformations, such as deep cloning,
* or as proxy object mapping such as in debugging.
* <p>
*
* This map permits <code>null</code> keys and values, and does not
* guarantee that elements will stay in the same order over time. The
* basic operations (<code>get</code> and <code>put</code>) take
* constant time, provided System.identityHashCode is decent. You can
* tune the behavior by specifying the expected maximum size. As more
* elements are added, the map may need to allocate a larger table,
* which can be expensive.
* <p>
*
* This implementation is unsynchronized. If you want multi-thread
* access to be consistent, you must synchronize it, perhaps by using
* <code>Collections.synchronizedMap(new IdentityHashMap(...));</code>.
* The iterators are <i>fail-fast</i>, meaning that a structural modification
* made to the map outside of an iterator's remove method cause the
* iterator, and in the case of the entrySet, the Map.Entry, to
* fail with a {@link ConcurrentModificationException}.
*
* @author Tom Tromey (tromey@redhat.com)
* @author Eric Blake (ebb9@email.byu.edu)
* @see System#identityHashCode(Object)
* @see Collection
* @see Map
* @see HashMap
* @see TreeMap
* @see LinkedHashMap
* @see WeakHashMap
* @since 1.4
* @status updated to 1.4
*/
public class IdentityHashMap extends AbstractMap
implements Map, Serializable, Cloneable
{
/** The default capacity. */
private static final int DEFAULT_CAPACITY = 21;
/**
* This object is used to mark deleted items. Package visible for use by
* nested classes.
*/
static final Object tombstone = new Object();
/**
* This object is used to mark empty slots. We need this because
* using null is ambiguous. Package visible for use by nested classes.
*/
static final Object emptyslot = new Object();
/**
* Compatible with JDK 1.4.
*/
private static final long serialVersionUID = 8188218128353913216L;
/**
* The number of mappings in the table. Package visible for use by nested
* classes.
* @serial
*/
int size;
/**
* The table itself. Package visible for use by nested classes.
*/
transient Object[] table;
/**
* The number of structural modifications made so far. Package visible for
* use by nested classes.
*/
transient int modCount;
/**
* The cache for {@link #entrySet()}.
*/
private transient Set entries;
/**
* The threshold for rehashing, which is 75% of (table.length / 2).
*/
private transient int threshold;
/**
* Create a new IdentityHashMap with the default capacity (21 entries).
*/
public IdentityHashMap()
{
this(DEFAULT_CAPACITY);
}
/**
* Create a new IdentityHashMap with the indicated number of
* entries. If the number of elements added to this hash map
* exceeds this maximum, the map will grow itself; however, that
* incurs a performance penalty.
*
* @param max initial size
* @throws IllegalArgumentException if max is negative
*/
public IdentityHashMap(int max)
{
if (max < 0)
throw new IllegalArgumentException();
// Need at least two slots, or hash() will break.
if (max < 2)
max = 2;
table = new Object[max << 1];
Arrays.fill(table, emptyslot);
threshold = (max >> 2) * 3;
}
/**
* Create a new IdentityHashMap whose contents are taken from the
* given Map.
*
* @param m The map whose elements are to be put in this map
* @throws NullPointerException if m is null
*/
public IdentityHashMap(Map m)
{
this(Math.max(m.size() << 1, DEFAULT_CAPACITY));
putAll(m);
}
/**
* Remove all mappings from this map.
*/
public void clear()
{
if (size != 0)
{
modCount++;
Arrays.fill(table, emptyslot);
size = 0;
}
}
/**
* Creates a shallow copy where keys and values are not cloned.
*/
public Object clone()
{
try
{
IdentityHashMap copy = (IdentityHashMap) super.clone();
copy.table = (Object[]) table.clone();
copy.entries = null; // invalidate the cache
return copy;
}
catch (CloneNotSupportedException e)
{
// Can't happen.
return null;
}
}
/**
* Tests whether the specified key is in this map. Unlike normal Maps,
* this test uses <code>entry == key</code> instead of
* <code>entry == null ? key == null : entry.equals(key)</code>.
*
* @param key the key to look for
* @return true if the key is contained in the map
* @see #containsValue(Object)
* @see #get(Object)
*/
public boolean containsKey(Object key)
{
return key == table[hash(key)];
}
/**
* Returns true if this HashMap contains the value. Unlike normal maps,
* this test uses <code>entry == value</code> instead of
* <code>entry == null ? value == null : entry.equals(value)</code>.
*
* @param value the value to search for in this HashMap
* @return true if at least one key maps to the value
* @see #containsKey(Object)
*/
public boolean containsValue(Object value)
{
for (int i = table.length - 1; i > 0; i -= 2)
if (table[i] == value)
return true;
return false;
}
/**
* Returns a "set view" of this Map's entries. The set is backed by
* the Map, so changes in one show up in the other. The set supports
* element removal, but not element addition.
* <p>
*
* <em>The semantics of this set, and of its contained entries, are
* different from the contract of Set and Map.Entry in order to make
* IdentityHashMap work. This means that while you can compare these
* objects between IdentityHashMaps, comparing them with regular sets
* or entries is likely to have undefined behavior.</em> The entries
* in this set are reference-based, rather than the normal object
* equality. Therefore, <code>e1.equals(e2)</code> returns
* <code>e1.getKey() == e2.getKey() && e1.getValue() == e2.getValue()</code>,
* and <code>e.hashCode()</code> returns
* <code>System.identityHashCode(e.getKey()) ^
* System.identityHashCode(e.getValue())</code>.
* <p>
*
* Note that the iterators for all three views, from keySet(), entrySet(),
* and values(), traverse the Map in the same sequence.
*
* @return a set view of the entries
* @see #keySet()
* @see #values()
* @see Map.Entry
*/
public Set entrySet()
{
if (entries == null)
entries = new AbstractSet()
{
public int size()
{
return size;
}
public Iterator iterator()
{
return new IdentityIterator(ENTRIES);
}
public void clear()
{
IdentityHashMap.this.clear();
}
public boolean contains(Object o)
{
if (! (o instanceof Map.Entry))
return false;
Map.Entry m = (Map.Entry) o;
return m.getValue() == table[hash(m.getKey()) + 1];
}
public int hashCode()
{
return IdentityHashMap.this.hashCode();
}
public boolean remove(Object o)
{
if (! (o instanceof Map.Entry))
return false;
Object key = ((Map.Entry) o).getKey();
int h = hash(key);
if (table[h] == key)
{
size--;
modCount++;
table[h] = tombstone;
table[h + 1] = tombstone;
return true;
}
return false;
}
};
return entries;
}
/**
* Compares two maps for equality. This returns true only if both maps
* have the same reference-identity comparisons. While this returns
* <code>this.entrySet().equals(m.entrySet())</code> as specified by Map,
* this will not work with normal maps, since the entry set compares
* with == instead of .equals.
*
* @param o the object to compare to
* @return true if it is equal
*/
public boolean equals(Object o)
{
// Why did Sun specify this one? The superclass does the right thing.
return super.equals(o);
}
/**
* Return the value in this Map associated with the supplied key, or
* <code>null</code> if the key maps to nothing.
*
* <p>NOTE: Since the value could also be null, you must use
* containsKey to see if this key actually maps to something.
* Unlike normal maps, this tests for the key with <code>entry ==
* key</code> instead of <code>entry == null ? key == null :
* entry.equals(key)</code>.
*
* @param key the key for which to fetch an associated value
* @return what the key maps to, if present
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
public Object get(Object key)
{
int h = hash(key);
return table[h] == key ? table[h + 1] : null;
}
/**
* Returns the hashcode of this map. This guarantees that two
* IdentityHashMaps that compare with equals() will have the same hash code,
* but may break with comparison to normal maps since it uses
* System.identityHashCode() instead of hashCode().
*
* @return the hash code
*/
public int hashCode()
{
int hash = 0;
for (int i = table.length - 2; i >= 0; i -= 2)
{
Object key = table[i];
if (key == emptyslot || key == tombstone)
continue;
hash += (System.identityHashCode(key)
^ System.identityHashCode(table[i + 1]));
}
return hash;
}
/**
* Returns true if there are no key-value mappings currently in this Map
* @return <code>size() == 0</code>
*/
public boolean isEmpty()
{
return size == 0;
}
/**
* Returns a "set view" of this Map's keys. The set is backed by the
* Map, so changes in one show up in the other. The set supports
* element removal, but not element addition.
* <p>
*
* <em>The semantics of this set are different from the contract of Set
* in order to make IdentityHashMap work. This means that while you can
* compare these objects between IdentityHashMaps, comparing them with
* regular sets is likely to have undefined behavior.</em> The hashCode
* of the set is the sum of the identity hash codes, instead of the
* regular hashCodes, and equality is determined by reference instead
* of by the equals method.
* <p>
*
* @return a set view of the keys
* @see #values()
* @see #entrySet()
*/
public Set keySet()
{
if (keys == null)
keys = new AbstractSet()
{
public int size()
{
return size;
}
public Iterator iterator()
{
return new IdentityIterator(KEYS);
}
public void clear()
{
IdentityHashMap.this.clear();
}
public boolean contains(Object o)
{
return containsKey(o);
}
public int hashCode()
{
int hash = 0;
for (int i = table.length - 2; i >= 0; i -= 2)
{
Object key = table[i];
if (key == emptyslot || key == tombstone)
continue;
hash += System.identityHashCode(key);
}
return hash;
}
public boolean remove(Object o)
{
int h = hash(o);
if (table[h] == o)
{
size--;
modCount++;
table[h] = tombstone;
table[h + 1] = tombstone;
return true;
}
return false;
}
};
return keys;
}
/**
* Puts the supplied value into the Map, mapped by the supplied key.
* The value may be retrieved by any object which <code>equals()</code>
* this key. NOTE: Since the prior value could also be null, you must
* first use containsKey if you want to see if you are replacing the
* key's mapping. Unlike normal maps, this tests for the key
* with <code>entry == key</code> instead of
* <code>entry == null ? key == null : entry.equals(key)</code>.
*
* @param key the key used to locate the value
* @param value the value to be stored in the HashMap
* @return the prior mapping of the key, or null if there was none
* @see #get(Object)
*/
public Object put(Object key, Object value)
{
// Rehash if the load factor is too high.
if (size > threshold)
{
Object[] old = table;
// This isn't necessarily prime, but it is an odd number of key/value
// slots, which has a higher probability of fewer collisions.
table = new Object[(old.length * 2) + 2];
Arrays.fill(table, emptyslot);
size = 0;
threshold = (table.length >>> 3) * 3;
for (int i = old.length - 2; i >= 0; i -= 2)
{
Object oldkey = old[i];
if (oldkey != tombstone && oldkey != emptyslot)
// Just use put. This isn't very efficient, but it is ok.
put(oldkey, old[i + 1]);
}
}
int h = hash(key);
if (table[h] == key)
{
Object r = table[h + 1];
table[h + 1] = value;
return r;
}
// At this point, we add a new mapping.
modCount++;
size++;
table[h] = key;
table[h + 1] = value;
return null;
}
/**
* Copies all of the mappings from the specified map to this. If a key
* is already in this map, its value is replaced.
*
* @param m the map to copy
* @throws NullPointerException if m is null
*/
public void putAll(Map m)
{
// Why did Sun specify this one? The superclass does the right thing.
super.putAll(m);
}
/**
* Removes from the HashMap and returns the value which is mapped by
* the supplied key. If the key maps to nothing, then the HashMap
* remains unchanged, and <code>null</code> is returned.
*
* NOTE: Since the value could also be null, you must use
* containsKey to see if you are actually removing a mapping.
* Unlike normal maps, this tests for the key with <code>entry ==
* key</code> instead of <code>entry == null ? key == null :
* entry.equals(key)</code>.
*
* @param key the key used to locate the value to remove
* @return whatever the key mapped to, if present
*/
public Object remove(Object key)
{
int h = hash(key);
if (table[h] == key)
{
modCount++;
size--;
Object r = table[h + 1];
table[h] = tombstone;
table[h + 1] = tombstone;
return r;
}
return null;
}
/**
* Returns the number of kay-value mappings currently in this Map
* @return the size
*/
public int size()
{
return size;
}
/**
* Returns a "collection view" (or "bag view") of this Map's values.
* The collection is backed by the Map, so changes in one show up
* in the other. The collection supports element removal, but not element
* addition.
* <p>
*
* <em>The semantics of this set are different from the contract of
* Collection in order to make IdentityHashMap work. This means that
* while you can compare these objects between IdentityHashMaps, comparing
* them with regular sets is likely to have undefined behavior.</em>
* Likewise, contains and remove go by == instead of equals().
* <p>
*
* @return a bag view of the values
* @see #keySet()
* @see #entrySet()
*/
public Collection values()
{
if (values == null)
values = new AbstractCollection()
{
public int size()
{
return size;
}
public Iterator iterator()
{
return new IdentityIterator(VALUES);
}
public void clear()
{
IdentityHashMap.this.clear();
}
public boolean remove(Object o)
{
for (int i = table.length - 1; i > 0; i -= 2)
if (table[i] == o)
{
modCount++;
table[i - 1] = tombstone;
table[i] = tombstone;
size--;
return true;
}
return false;
}
};
return values;
}
/**
* Helper method which computes the hash code, then traverses the table
* until it finds the key, or the spot where the key would go.
*
* @param key the key to check
* @return the index where the key belongs
* @see #IdentityHashMap(int)
* @see #put(Object, Object)
*/
// Package visible for use by nested classes.
int hash(Object key)
{
// Implementation note: it is feasible for the table to have no
// emptyslots, if it is full with entries and tombstones, so we must
// remember where we started. If we encounter the key or an emptyslot,
// we are done. If we encounter a tombstone, the key may still be in
// the array. If we don't encounter the key, we use the first emptyslot
// or tombstone we encountered as the location where the key would go.
// By requiring at least 2 key/value slots, and rehashing at 75%
// capacity, we guarantee that there will always be either an emptyslot
// or a tombstone somewhere in the table.
int h = Math.abs(System.identityHashCode(key) % (table.length >> 1)) << 1;
int del = -1;
int save = h;
do
{
if (table[h] == key)
return h;
if (table[h] == emptyslot)
break;
if (table[h] == tombstone && del < 0)
del = h;
h -= 2;
if (h < 0)
h = table.length - 2;
}
while (h != save);
return del < 0 ? h : del;
}
/**
* This class allows parameterized iteration over IdentityHashMaps. Based
* on its construction, it returns the key or value of a mapping, or
* creates the appropriate Map.Entry object with the correct fail-fast
* semantics and identity comparisons.
*
* @author Tom Tromey (tromey@redhat.com)
* @author Eric Blake (ebb9@email.byu.edu)
*/
private class IdentityIterator implements Iterator
{
/**
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
* or {@link #ENTRIES}.
*/
final int type;
/** The number of modifications to the backing Map that we know about. */
int knownMod = modCount;
/** The number of elements remaining to be returned by next(). */
int count = size;
/** Location in the table. */
int loc = table.length;
/**
* Construct a new Iterator with the supplied type.
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
*/
IdentityIterator(int type)
{
this.type = type;
}
/**
* Returns true if the Iterator has more elements.
* @return true if there are more elements
* @throws ConcurrentModificationException if the Map was modified
*/
public boolean hasNext()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
return count > 0;
}
/**
* Returns the next element in the Iterator's sequential view.
* @return the next element
* @throws ConcurrentModificationException if the Map was modified
* @throws NoSuchElementException if there is none
*/
public Object next()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
if (count == 0)
throw new NoSuchElementException();
count--;
Object key;
do
{
loc -= 2;
key = table[loc];
}
while (key == emptyslot || key == tombstone);
return type == KEYS ? key : (type == VALUES ? table[loc + 1]
: new IdentityEntry(loc));
}
/**
* Removes from the backing Map the last element which was fetched
* with the <code>next()</code> method.
*
* @throws ConcurrentModificationException if the Map was modified
* @throws IllegalStateException if called when there is no last element
*/
public void remove()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
if (loc == table.length || table[loc] == tombstone)
throw new IllegalStateException();
modCount++;
size--;
table[loc] = tombstone;
table[loc + 1] = tombstone;
knownMod++;
}
} // class IdentityIterator
/**
* This class provides Map.Entry objects for IdentityHashMaps. The entry
* is fail-fast, and will throw a ConcurrentModificationException if
* the underlying map is modified, or if remove is called on the iterator
* that generated this object. It is identity based, so it violates
* the general contract of Map.Entry, and is probably unsuitable for
* comparison to normal maps; but it works among other IdentityHashMaps.
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
private final class IdentityEntry implements Map.Entry
{
/** The location of this entry. */
final int loc;
/** The number of modifications to the backing Map that we know about. */
final int knownMod = modCount;
/**
* Constructs the Entry.
*
* @param loc the location of this entry in table
*/
IdentityEntry(int loc)
{
this.loc = loc;
}
/**
* Compares the specified object with this entry, using identity
* semantics. Note that this can lead to undefined results with
* Entry objects created by normal maps.
*
* @param o the object to compare
* @return true if it is equal
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
public boolean equals(Object o)
{
if (knownMod != modCount || table[loc] == tombstone)
throw new ConcurrentModificationException();
if (! (o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry) o;
return table[loc] == e.getKey() && table[loc + 1] == e.getValue();
}
/**
* Returns the key of this entry.
*
* @return the key
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
public Object getKey()
{
if (knownMod != modCount || table[loc] == tombstone)
throw new ConcurrentModificationException();
return table[loc];
}
/**
* Returns the value of this entry.
*
* @return the value
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
public Object getValue()
{
if (knownMod != modCount || table[loc] == tombstone)
throw new ConcurrentModificationException();
return table[loc + 1];
}
/**
* Returns the hashcode of the entry, using identity semantics.
* Note that this can lead to undefined results with Entry objects
* created by normal maps.
*
* @return the hash code
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
public int hashCode()
{
if (knownMod != modCount || table[loc] == tombstone)
throw new ConcurrentModificationException();
return (System.identityHashCode(table[loc])
^ System.identityHashCode(table[loc + 1]));
}
/**
* Replaces the value of this mapping, and returns the old value.
*
* @param value the new value
* @return the old value
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
public Object setValue(Object value)
{
if (knownMod != modCount || table[loc] == tombstone)
throw new ConcurrentModificationException();
Object r = table[loc + 1];
table[loc + 1] = value;
return r;
}
/**
* This provides a string representation of the entry. It is of the form
* "key=value", where string concatenation is used on key and value.
*
* @return the string representation
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
public String toString()
{
if (knownMod != modCount || table[loc] == tombstone)
throw new ConcurrentModificationException();
return table[loc] + "=" + table[loc + 1];
}
} // class IdentityEntry
/**
* Reads the object from a serial stream.
*
* @param s the stream to read from
* @throws ClassNotFoundException if the underlying stream fails
* @throws IOException if the underlying stream fails
* @serialData expects the size (int), followed by that many key (Object)
* and value (Object) pairs, with the pairs in no particular
* order
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
int num = s.readInt();
table = new Object[Math.max(num << 1, DEFAULT_CAPACITY) << 1];
// Read key/value pairs.
while (--num >= 0)
put(s.readObject(), s.readObject());
}
/**
* Writes the object to a serial stream.
*
* @param s the stream to write to
* @throws IOException if the underlying stream fails
* @serialData outputs the size (int), followed by that many key (Object)
* and value (Object) pairs, with the pairs in no particular
* order
*/
private void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
s.writeInt(size);
for (int i = table.length - 2; i >= 0; i -= 2)
{
Object key = table[i];
if (key != tombstone && key != emptyslot)
{
s.writeObject(key);
s.writeObject(table[i + 1]);
}
}
}
}
-87
View File
@@ -1,87 +0,0 @@
/* Iterator.java -- Interface for iterating over collections
Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* An object which iterates over a collection. An Iterator is used to return
* the items once only, in sequence, by successive calls to the next method.
* It is also possible to remove elements from the underlying collection by
* using the optional remove method. Iterator is intended as a replacement
* for the Enumeration interface of previous versions of Java, which did not
* have the remove method and had less conveniently named methods.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see ListIterator
* @see Enumeration
* @since 1.2
* @status updated to 1.4
*/
public interface Iterator
{
/**
* Tests whether there are elements remaining in the collection. In other
* words, calling <code>next()</code> will not throw an exception.
*
* @return true if there is at least one more element in the collection
*/
boolean hasNext();
/**
* Obtain the next element in the collection.
*
* @return the next element in the collection
* @throws NoSuchElementException if there are no more elements
*/
Object next();
/**
* Remove from the underlying collection the last element returned by next
* (optional operation). This method can be called only once after each
* call to <code>next()</code>. It does not affect what will be returned
* by subsequent calls to next.
*
* @throws IllegalStateException if next has not yet been called or remove
* has already been called since the last call to next.
* @throws UnsupportedOperationException if this Iterator does not support
* the remove operation.
*/
void remove();
}
-501
View File
@@ -1,501 +0,0 @@
/* LinkedHashMap.java -- a class providing hashtable data structure,
mapping Object --> Object, with linked list traversal
Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* This class provides a hashtable-backed implementation of the
* Map interface, with predictable traversal order.
* <p>
*
* It uses a hash-bucket approach; that is, hash collisions are handled
* by linking the new node off of the pre-existing node (or list of
* nodes). In this manner, techniques such as linear probing (which
* can cause primary clustering) and rehashing (which does not fit very
* well with Java's method of precomputing hash codes) are avoided. In
* addition, this maintains a doubly-linked list which tracks either
* insertion or access order.
* <p>
*
* In insertion order, calling <code>put</code> adds the key to the end of
* traversal, unless the key was already in the map; changing traversal order
* requires removing and reinserting a key. On the other hand, in access
* order, all calls to <code>put</code> and <code>get</code> cause the
* accessed key to move to the end of the traversal list. Note that any
* accesses to the map's contents via its collection views and iterators do
* not affect the map's traversal order, since the collection views do not
* call <code>put</code> or <code>get</code>.
* <p>
*
* One of the nice features of tracking insertion order is that you can
* copy a hashtable, and regardless of the implementation of the original,
* produce the same results when iterating over the copy. This is possible
* without needing the overhead of <code>TreeMap</code>.
* <p>
*
* When using this {@link #LinkedHashMap(int, float, boolean) constructor},
* you can build an access-order mapping. This can be used to implement LRU
* caches, for example. By overriding {@link #removeEldestEntry(Map.Entry)},
* you can also control the removal of the oldest entry, and thereby do
* things like keep the map at a fixed size.
* <p>
*
* Under ideal circumstances (no collisions), LinkedHashMap offers O(1)
* performance on most operations (<code>containsValue()</code> is,
* of course, O(n)). In the worst case (all keys map to the same
* hash code -- very unlikely), most operations are O(n). Traversal is
* faster than in HashMap (proportional to the map size, and not the space
* allocated for the map), but other operations may be slower because of the
* overhead of the maintaining the traversal order list.
* <p>
*
* LinkedHashMap accepts the null key and null values. It is not
* synchronized, so if you need multi-threaded access, consider using:<br>
* <code>Map m = Collections.synchronizedMap(new LinkedHashMap(...));</code>
* <p>
*
* The iterators are <i>fail-fast</i>, meaning that any structural
* modification, except for <code>remove()</code> called on the iterator
* itself, cause the iterator to throw a
* {@link ConcurrentModificationException} rather than exhibit
* non-deterministic behavior.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @see Object#hashCode()
* @see Collection
* @see Map
* @see HashMap
* @see TreeMap
* @see Hashtable
* @since 1.4
* @status updated to 1.4
*/
public class LinkedHashMap extends HashMap
{
/**
* Compatible with JDK 1.4.
*/
private static final long serialVersionUID = 3801124242820219131L;
/**
* The oldest Entry to begin iteration at.
*/
transient LinkedHashEntry root;
/**
* The iteration order of this linked hash map: <code>true</code> for
* access-order, <code>false</code> for insertion-order.
*
* @serial true for access order traversal
*/
final boolean accessOrder;
/**
* Class to represent an entry in the hash table. Holds a single key-value
* pair and the doubly-linked insertion order list.
*/
class LinkedHashEntry extends HashEntry
{
/**
* The predecessor in the iteration list. If this entry is the root
* (eldest), pred points to the newest entry.
*/
LinkedHashEntry pred;
/** The successor in the iteration list, null if this is the newest. */
LinkedHashEntry succ;
/**
* Simple constructor.
*
* @param key the key
* @param value the value
*/
LinkedHashEntry(Object key, Object value)
{
super(key, value);
if (root == null)
{
root = this;
pred = this;
}
else
{
pred = root.pred;
pred.succ = this;
root.pred = this;
}
}
/**
* Called when this entry is accessed via put or get. This version does
* the necessary bookkeeping to keep the doubly-linked list in order,
* after moving this element to the newest position in access order.
*/
void access()
{
if (accessOrder && succ != null)
{
modCount++;
if (this == root)
{
root = succ;
pred.succ = this;
succ = null;
}
else
{
pred.succ = succ;
succ.pred = pred;
succ = null;
pred = root.pred;
pred.succ = this;
root.pred = this;
}
}
}
/**
* Called when this entry is removed from the map. This version does
* the necessary bookkeeping to keep the doubly-linked list in order.
*
* @return the value of this key as it is removed
*/
Object cleanup()
{
if (this == root)
{
root = succ;
if (succ != null)
succ.pred = pred;
}
else if (succ == null)
{
pred.succ = null;
root.pred = pred;
}
else
{
pred.succ = succ;
succ.pred = pred;
}
return value;
}
} // class LinkedHashEntry
/**
* Construct a new insertion-ordered LinkedHashMap with the default
* capacity (11) and the default load factor (0.75).
*/
public LinkedHashMap()
{
super();
accessOrder = false;
}
/**
* Construct a new insertion-ordered LinkedHashMap from the given Map,
* with initial capacity the greater of the size of <code>m</code> or
* the default of 11.
* <p>
*
* Every element in Map m will be put into this new HashMap, in the
* order of m's iterator.
*
* @param m a Map whose key / value pairs will be put into
* the new HashMap. <b>NOTE: key / value pairs
* are not cloned in this constructor.</b>
* @throws NullPointerException if m is null
*/
public LinkedHashMap(Map m)
{
super(m);
accessOrder = false;
}
/**
* Construct a new insertion-ordered LinkedHashMap with a specific
* inital capacity and default load factor of 0.75.
*
* @param initialCapacity the initial capacity of this HashMap (&gt;= 0)
* @throws IllegalArgumentException if (initialCapacity &lt; 0)
*/
public LinkedHashMap(int initialCapacity)
{
super(initialCapacity);
accessOrder = false;
}
/**
* Construct a new insertion-orderd LinkedHashMap with a specific
* inital capacity and load factor.
*
* @param initialCapacity the initial capacity (&gt;= 0)
* @param loadFactor the load factor (&gt; 0, not NaN)
* @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
* ! (loadFactor &gt; 0.0)
*/
public LinkedHashMap(int initialCapacity, float loadFactor)
{
super(initialCapacity, loadFactor);
accessOrder = false;
}
/**
* Construct a new LinkedHashMap with a specific inital capacity, load
* factor, and ordering mode.
*
* @param initialCapacity the initial capacity (&gt;=0)
* @param loadFactor the load factor (&gt;0, not NaN)
* @param accessOrder true for access-order, false for insertion-order
* @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
* ! (loadFactor &gt; 0.0)
*/
public LinkedHashMap(int initialCapacity, float loadFactor,
boolean accessOrder)
{
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
/**
* Clears the Map so it has no keys. This is O(1).
*/
public void clear()
{
super.clear();
root = null;
}
/**
* Returns <code>true</code> if this HashMap contains a value
* <code>o</code>, such that <code>o.equals(value)</code>.
*
* @param value the value to search for in this HashMap
* @return <code>true</code> if at least one key maps to the value
*/
public boolean containsValue(Object value)
{
LinkedHashEntry e = root;
while (e != null)
{
if (equals(value, e.value))
return true;
e = e.succ;
}
return false;
}
/**
* Return the value in this Map associated with the supplied key,
* or <code>null</code> if the key maps to nothing. If this is an
* access-ordered Map and the key is found, this performs structural
* modification, moving the key to the newest end of the list. NOTE:
* Since the value could also be null, you must use containsKey to
* see if this key actually maps to something.
*
* @param key the key for which to fetch an associated value
* @return what the key maps to, if present
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
public Object get(Object key)
{
int idx = hash(key);
HashEntry e = buckets[idx];
while (e != null)
{
if (equals(key, e.key))
{
e.access();
return e.value;
}
e = e.next;
}
return null;
}
/**
* Returns <code>true</code> if this map should remove the eldest entry.
* This method is invoked by all calls to <code>put</code> and
* <code>putAll</code> which place a new entry in the map, providing
* the implementer an opportunity to remove the eldest entry any time
* a new one is added. This can be used to save memory usage of the
* hashtable, as well as emulating a cache, by deleting stale entries.
* <p>
*
* For example, to keep the Map limited to 100 entries, override as follows:
* <pre>
* private static final int MAX_ENTRIES = 100;
* protected boolean removeEldestEntry(Map.Entry eldest)
* {
* return size() &gt; MAX_ENTRIES;
* }
* </pre><p>
*
* Typically, this method does not modify the map, but just uses the
* return value as an indication to <code>put</code> whether to proceed.
* However, if you override it to modify the map, you must return false
* (indicating that <code>put</code> should leave the modified map alone),
* or you face unspecified behavior. Remember that in access-order mode,
* even calling <code>get</code> is a structural modification, but using
* the collections views (such as <code>keySet</code>) is not.
* <p>
*
* This method is called after the eldest entry has been inserted, so
* if <code>put</code> was called on a previously empty map, the eldest
* entry is the one you just put in! The default implementation just
* returns <code>false</code>, so that this map always behaves like
* a normal one with unbounded growth.
*
* @param eldest the eldest element which would be removed if this
* returns true. For an access-order map, this is the least
* recently accessed; for an insertion-order map, this is the
* earliest element inserted.
* @return true if <code>eldest</code> should be removed
*/
protected boolean removeEldestEntry(Map.Entry eldest)
{
return false;
}
/**
* Helper method called by <code>put</code>, which creates and adds a
* new Entry, followed by performing bookkeeping (like removeEldestEntry).
*
* @param key the key of the new Entry
* @param value the value
* @param idx the index in buckets where the new Entry belongs
* @param callRemove whether to call the removeEldestEntry method
* @see #put(Object, Object)
* @see #removeEldestEntry(Map.Entry)
* @see LinkedHashEntry#LinkedHashEntry(Object, Object)
*/
void addEntry(Object key, Object value, int idx, boolean callRemove)
{
LinkedHashEntry e = new LinkedHashEntry(key, value);
e.next = buckets[idx];
buckets[idx] = e;
if (callRemove && removeEldestEntry(root))
remove(root.key);
}
/**
* Helper method, called by clone() to reset the doubly-linked list.
*
* @param m the map to add entries from
* @see #clone()
*/
void putAllInternal(Map m)
{
root = null;
super.putAllInternal(m);
}
/**
* Generates a parameterized iterator. This allows traversal to follow
* the doubly-linked list instead of the random bin order of HashMap.
*
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
* @return the appropriate iterator
*/
Iterator iterator(final int type)
{
return new Iterator()
{
/** The current Entry. */
LinkedHashEntry current = root;
/** The previous Entry returned by next(). */
LinkedHashEntry last;
/** The number of known modifications to the backing Map. */
int knownMod = modCount;
/**
* Returns true if the Iterator has more elements.
*
* @return true if there are more elements
* @throws ConcurrentModificationException if the HashMap was modified
*/
public boolean hasNext()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
return current != null;
}
/**
* Returns the next element in the Iterator's sequential view.
*
* @return the next element
* @throws ConcurrentModificationException if the HashMap was modified
* @throws NoSuchElementException if there is none
*/
public Object next()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
if (current == null)
throw new NoSuchElementException();
last = current;
current = current.succ;
return type == VALUES ? last.value : type == KEYS ? last.key : last;
}
/**
* Removes from the backing HashMap the last element which was fetched
* with the <code>next()</code> method.
*
* @throws ConcurrentModificationException if the HashMap was modified
* @throws IllegalStateException if called when there is no last element
*/
public void remove()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
if (last == null)
throw new IllegalStateException();
LinkedHashMap.this.remove(last.key);
last = null;
knownMod++;
}
};
}
} // class LinkedHashMap
-160
View File
@@ -1,160 +0,0 @@
/* LinkedHashSet.java -- a set backed by a LinkedHashMap, for linked
list traversal.
Copyright (C) 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.Serializable;
/**
* This class provides a hashtable-backed implementation of the
* Set interface, with predictable traversal order.
* <p>
*
* It uses a hash-bucket approach; that is, hash collisions are handled
* by linking the new node off of the pre-existing node (or list of
* nodes). In this manner, techniques such as linear probing (which
* can cause primary clustering) and rehashing (which does not fit very
* well with Java's method of precomputing hash codes) are avoided. In
* addition, this maintains a doubly-linked list which tracks insertion
* order. Note that the insertion order is not modified if an
* <code>add</code> simply reinserts an element in the set.
* <p>
*
* One of the nice features of tracking insertion order is that you can
* copy a set, and regardless of the implementation of the original,
* produce the same results when iterating over the copy. This is possible
* without needing the overhead of <code>TreeSet</code>.
* <p>
*
* Under ideal circumstances (no collisions), LinkedHashSet offers O(1)
* performance on most operations. In the worst case (all elements map
* to the same hash code -- very unlikely), most operations are O(n).
* <p>
*
* LinkedHashSet accepts the null entry. It is not synchronized, so if
* you need multi-threaded access, consider using:<br>
* <code>Set s = Collections.synchronizedSet(new LinkedHashSet(...));</code>
* <p>
*
* The iterators are <i>fail-fast</i>, meaning that any structural
* modification, except for <code>remove()</code> called on the iterator
* itself, cause the iterator to throw a
* {@link ConcurrentModificationException} rather than exhibit
* non-deterministic behavior.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @see Object#hashCode()
* @see Collection
* @see Set
* @see HashSet
* @see TreeSet
* @see Collections#synchronizedSet(Set)
* @since 1.4
* @status updated to 1.4
*/
public class LinkedHashSet extends HashSet
implements Set, Cloneable, Serializable
{
/**
* Compatible with JDK 1.4.
*/
private static final long serialVersionUID = -2851667679971038690L;
/**
* Construct a new, empty HashSet whose backing HashMap has the default
* capacity (11) and loadFacor (0.75).
*/
public LinkedHashSet()
{
super();
}
/**
* Construct a new, empty HashSet whose backing HashMap has the supplied
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity of the backing HashMap
* @throws IllegalArgumentException if the capacity is negative
*/
public LinkedHashSet(int initialCapacity)
{
super(initialCapacity);
}
/**
* Construct a new, empty HashSet whose backing HashMap has the supplied
* capacity and load factor.
*
* @param initialCapacity the initial capacity of the backing HashMap
* @param loadFactor the load factor of the backing HashMap
* @throws IllegalArgumentException if either argument is negative, or
* if loadFactor is POSITIVE_INFINITY or NaN
*/
public LinkedHashSet(int initialCapacity, float loadFactor)
{
super(initialCapacity, loadFactor);
}
/**
* Construct a new HashSet with the same elements as are in the supplied
* collection (eliminating any duplicates, of course). The backing storage
* has twice the size of the collection, or the default size of 11,
* whichever is greater; and the default load factor (0.75).
*
* @param c a collection of initial set elements
* @throws NullPointerException if c is null
*/
public LinkedHashSet(Collection c)
{
super(c);
}
/**
* Helper method which initializes the backing Map.
*
* @param capacity the initial capacity
* @param load the initial load factor
* @return the backing HashMap
*/
HashMap init(int capacity, float load)
{
return new LinkedHashMap(capacity, load);
}
}
-958
View File
@@ -1,958 +0,0 @@
/* LinkedList.java -- Linked list implementation of the List interface
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
/**
* Linked list implementation of the List interface. In addition to the
* methods of the List interface, this class provides access to the first
* and last list elements in O(1) time for easy stack, queue, or double-ended
* queue (deque) creation. The list is doubly-linked, with traversal to a
* given index starting from the end closest to the element.<p>
*
* LinkedList is not synchronized, so if you need multi-threaded access,
* consider using:<br>
* <code>List l = Collections.synchronizedList(new LinkedList(...));</code>
* <p>
*
* The iterators are <i>fail-fast</i>, meaning that any structural
* modification, except for <code>remove()</code> called on the iterator
* itself, cause the iterator to throw a
* {@link ConcurrentModificationException} rather than exhibit
* non-deterministic behavior.
*
* @author Original author unknown
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
* @see List
* @see ArrayList
* @see Vector
* @see Collections#synchronizedList(List)
* @since 1.2
* @status missing javadoc, but complete to 1.4
*/
public class LinkedList extends AbstractSequentialList
implements List, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2.
*/
private static final long serialVersionUID = 876323262645176354L;
/**
* The first element in the list.
*/
transient Entry first;
/**
* The last element in the list.
*/
transient Entry last;
/**
* The current length of the list.
*/
transient int size = 0;
/**
* Class to represent an entry in the list. Holds a single element.
*/
private static final class Entry
{
/** The element in the list. */
Object data;
/** The next list entry, null if this is last. */
Entry next;
/** The previous list entry, null if this is first. */
Entry previous;
/**
* Construct an entry.
* @param data the list element
*/
Entry(Object data)
{
this.data = data;
}
} // class Entry
/**
* Obtain the Entry at a given position in a list. This method of course
* takes linear time, but it is intelligent enough to take the shorter of the
* paths to get to the Entry required. This implies that the first or last
* entry in the list is obtained in constant time, which is a very desirable
* property.
* For speed and flexibility, range checking is not done in this method:
* Incorrect values will be returned if (n &lt; 0) or (n &gt;= size).
*
* @param n the number of the entry to get
* @return the entry at position n
*/
// Package visible for use in nested classes.
Entry getEntry(int n)
{
Entry e;
if (n < size / 2)
{
e = first;
// n less than size/2, iterate from start
while (n-- > 0)
e = e.next;
}
else
{
e = last;
// n greater than size/2, iterate from end
while (++n < size)
e = e.previous;
}
return e;
}
/**
* Remove an entry from the list. This will adjust size and deal with
* `first' and `last' appropriatly.
*
* @param e the entry to remove
*/
// Package visible for use in nested classes.
void removeEntry(Entry e)
{
modCount++;
size--;
if (size == 0)
first = last = null;
else
{
if (e == first)
{
first = e.next;
e.next.previous = null;
}
else if (e == last)
{
last = e.previous;
e.previous.next = null;
}
else
{
e.next.previous = e.previous;
e.previous.next = e.next;
}
}
}
/**
* Checks that the index is in the range of possible elements (inclusive).
*
* @param index the index to check
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size
*/
private void checkBoundsInclusive(int index)
{
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ size);
}
/**
* Checks that the index is in the range of existing elements (exclusive).
*
* @param index the index to check
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size
*/
private void checkBoundsExclusive(int index)
{
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ size);
}
/**
* Create an empty linked list.
*/
public LinkedList()
{
}
/**
* Create a linked list containing the elements, in order, of a given
* collection.
*
* @param c the collection to populate this list from
* @throws NullPointerException if c is null
*/
public LinkedList(Collection c)
{
addAll(c);
}
/**
* Returns the first element in the list.
*
* @return the first list element
* @throws NoSuchElementException if the list is empty
*/
public Object getFirst()
{
if (size == 0)
throw new NoSuchElementException();
return first.data;
}
/**
* Returns the last element in the list.
*
* @return the last list element
* @throws NoSuchElementException if the list is empty
*/
public Object getLast()
{
if (size == 0)
throw new NoSuchElementException();
return last.data;
}
/**
* Remove and return the first element in the list.
*
* @return the former first element in the list
* @throws NoSuchElementException if the list is empty
*/
public Object removeFirst()
{
if (size == 0)
throw new NoSuchElementException();
modCount++;
size--;
Object r = first.data;
if (first.next != null)
first.next.previous = null;
else
last = null;
first = first.next;
return r;
}
/**
* Remove and return the last element in the list.
*
* @return the former last element in the list
* @throws NoSuchElementException if the list is empty
*/
public Object removeLast()
{
if (size == 0)
throw new NoSuchElementException();
modCount++;
size--;
Object r = last.data;
if (last.previous != null)
last.previous.next = null;
else
first = null;
last = last.previous;
return r;
}
/**
* Insert an element at the first of the list.
*
* @param o the element to insert
*/
public void addFirst(Object o)
{
Entry e = new Entry(o);
modCount++;
if (size == 0)
first = last = e;
else
{
e.next = first;
first.previous = e;
first = e;
}
size++;
}
/**
* Insert an element at the last of the list.
*
* @param o the element to insert
*/
public void addLast(Object o)
{
addLastEntry(new Entry(o));
}
/**
* Inserts an element at the end of the list.
*
* @param e the entry to add
*/
private void addLastEntry(Entry e)
{
modCount++;
if (size == 0)
first = last = e;
else
{
e.previous = last;
last.next = e;
last = e;
}
size++;
}
/**
* Returns true if the list contains the given object. Comparison is done by
* <code>o == null ? e = null : o.equals(e)</code>.
*
* @param o the element to look for
* @return true if it is found
*/
public boolean contains(Object o)
{
Entry e = first;
while (e != null)
{
if (equals(o, e.data))
return true;
e = e.next;
}
return false;
}
/**
* Returns the size of the list.
*
* @return the list size
*/
public int size()
{
return size;
}
/**
* Adds an element to the end of the list.
*
* @param e the entry to add
* @return true, as it always succeeds
*/
public boolean add(Object o)
{
addLastEntry(new Entry(o));
return true;
}
/**
* Removes the entry at the lowest index in the list that matches the given
* object, comparing by <code>o == null ? e = null : o.equals(e)</code>.
*
* @param o the object to remove
* @return true if an instance of the object was removed
*/
public boolean remove(Object o)
{
Entry e = first;
while (e != null)
{
if (equals(o, e.data))
{
removeEntry(e);
return true;
}
e = e.next;
}
return false;
}
/**
* Append the elements of the collection in iteration order to the end of
* this list. If this list is modified externally (for example, if this
* list is the collection), behavior is unspecified.
*
* @param c the collection to append
* @return true if the list was modified
* @throws NullPointerException if c is null
*/
public boolean addAll(Collection c)
{
return addAll(size, c);
}
/**
* Insert the elements of the collection in iteration order at the given
* index of this list. If this list is modified externally (for example,
* if this list is the collection), behavior is unspecified.
*
* @param c the collection to append
* @return true if the list was modified
* @throws NullPointerException if c is null
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
public boolean addAll(int index, Collection c)
{
checkBoundsInclusive(index);
int csize = c.size();
if (csize == 0)
return false;
Iterator itr = c.iterator();
// Get the entries just before and after index. If index is at the start
// of the list, BEFORE is null. If index is at the end of the list, AFTER
// is null. If the list is empty, both are null.
Entry after = null;
Entry before = null;
if (index != size)
{
after = getEntry(index);
before = after.previous;
}
else
before = last;
// Create the first new entry. We do not yet set the link from `before'
// to the first entry, in order to deal with the case where (c == this).
// [Actually, we don't have to handle this case to fufill the
// contract for addAll(), but Sun's implementation appears to.]
Entry e = new Entry(itr.next());
e.previous = before;
Entry prev = e;
Entry firstNew = e;
// Create and link all the remaining entries.
for (int pos = 1; pos < csize; pos++)
{
e = new Entry(itr.next());
e.previous = prev;
prev.next = e;
prev = e;
}
// Link the new chain of entries into the list.
modCount++;
size += csize;
prev.next = after;
if (after != null)
after.previous = e;
else
last = e;
if (before != null)
before.next = firstNew;
else
first = firstNew;
return true;
}
/**
* Remove all elements from this list.
*/
public void clear()
{
if (size > 0)
{
modCount++;
first = null;
last = null;
size = 0;
}
}
/**
* Return the element at index.
*
* @param index the place to look
* @return the element at index
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
public Object get(int index)
{
checkBoundsExclusive(index);
return getEntry(index).data;
}
/**
* Replace the element at the given location in the list.
*
* @param index which index to change
* @param o the new element
* @return the prior element
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
public Object set(int index, Object o)
{
checkBoundsExclusive(index);
Entry e = getEntry(index);
Object old = e.data;
e.data = o;
return old;
}
/**
* Inserts an element in the given position in the list.
*
* @param index where to insert the element
* @param o the element to insert
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
public void add(int index, Object o)
{
checkBoundsInclusive(index);
Entry e = new Entry(o);
if (index < size)
{
modCount++;
Entry after = getEntry(index);
e.next = after;
e.previous = after.previous;
if (after.previous == null)
first = e;
else
after.previous.next = e;
after.previous = e;
size++;
}
else
addLastEntry(e);
}
/**
* Removes the element at the given position from the list.
*
* @param index the location of the element to remove
* @return the removed element
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
public Object remove(int index)
{
checkBoundsExclusive(index);
Entry e = getEntry(index);
removeEntry(e);
return e.data;
}
/**
* Returns the first index where the element is located in the list, or -1.
*
* @param o the element to look for
* @return its position, or -1 if not found
*/
public int indexOf(Object o)
{
int index = 0;
Entry e = first;
while (e != null)
{
if (equals(o, e.data))
return index;
index++;
e = e.next;
}
return -1;
}
/**
* Returns the last index where the element is located in the list, or -1.
*
* @param o the element to look for
* @return its position, or -1 if not found
*/
public int lastIndexOf(Object o)
{
int index = size - 1;
Entry e = last;
while (e != null)
{
if (equals(o, e.data))
return index;
index--;
e = e.previous;
}
return -1;
}
/**
* Obtain a ListIterator over this list, starting at a given index. The
* ListIterator returned by this method supports the add, remove and set
* methods.
*
* @param index the index of the element to be returned by the first call to
* next(), or size() to be initially positioned at the end of the list
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
public ListIterator listIterator(int index)
{
checkBoundsInclusive(index);
return new LinkedListItr(index);
}
/**
* Create a shallow copy of this LinkedList (the elements are not cloned).
*
* @return an object of the same class as this object, containing the
* same elements in the same order
*/
public Object clone()
{
LinkedList copy = null;
try
{
copy = (LinkedList) super.clone();
}
catch (CloneNotSupportedException ex)
{
}
copy.clear();
copy.addAll(this);
return copy;
}
/**
* Returns an array which contains the elements of the list in order.
*
* @return an array containing the list elements
*/
public Object[] toArray()
{
Object[] array = new Object[size];
Entry e = first;
for (int i = 0; i < size; i++)
{
array[i] = e.data;
e = e.next;
}
return array;
}
/**
* Returns an Array whose component type is the runtime component type of
* the passed-in Array. The returned Array is populated with all of the
* elements in this LinkedList. If the passed-in Array is not large enough
* to store all of the elements in this List, a new Array will be created
* and returned; if the passed-in Array is <i>larger</i> than the size
* of this List, then size() index will be set to null.
*
* @param a the passed-in Array
* @return an array representation of this list
* @throws ArrayStoreException if the runtime type of a does not allow
* an element in this list
* @throws NullPointerException if a is null
*/
public Object[] toArray(Object[] a)
{
if (a.length < size)
a = (Object[]) Array.newInstance(a.getClass().getComponentType(), size);
else if (a.length > size)
a[size] = null;
Entry e = first;
for (int i = 0; i < size; i++)
{
a[i] = e.data;
e = e.next;
}
return a;
}
/**
* Serializes this object to the given stream.
*
* @param s the stream to write to
* @throws IOException if the underlying stream fails
* @serialData the size of the list (int), followed by all the elements
* (Object) in proper order
*/
private void writeObject(ObjectOutputStream s) throws IOException
{
s.defaultWriteObject();
s.writeInt(size);
Entry e = first;
while (e != null)
{
s.writeObject(e.data);
e = e.next;
}
}
/**
* Deserializes this object from the given stream.
*
* @param s the stream to read from
* @throws ClassNotFoundException if the underlying stream fails
* @throws IOException if the underlying stream fails
* @serialData the size of the list (int), followed by all the elements
* (Object) in proper order
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
int i = s.readInt();
while (--i >= 0)
addLastEntry(new Entry(s.readObject()));
}
/**
* A ListIterator over the list. This class keeps track of its
* position in the list and the two list entries it is between.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
*/
private final class LinkedListItr implements ListIterator
{
/** Number of modifications we know about. */
private int knownMod = modCount;
/** Entry that will be returned by next(). */
private Entry next;
/** Entry that will be returned by previous(). */
private Entry previous;
/** Entry that will be affected by remove() or set(). */
private Entry lastReturned;
/** Index of `next'. */
private int position;
/**
* Initialize the iterator.
*
* @param index the initial index
*/
LinkedListItr(int index)
{
if (index == size)
{
next = null;
previous = last;
}
else
{
next = getEntry(index);
previous = next.previous;
}
position = index;
}
/**
* Checks for iterator consistency.
*
* @throws ConcurrentModificationException if the list was modified
*/
private void checkMod()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
}
/**
* Returns the index of the next element.
*
* @return the next index
* @throws ConcurrentModificationException if the list was modified
*/
public int nextIndex()
{
checkMod();
return position;
}
/**
* Returns the index of the previous element.
*
* @return the previous index
* @throws ConcurrentModificationException if the list was modified
*/
public int previousIndex()
{
checkMod();
return position - 1;
}
/**
* Returns true if more elements exist via next.
*
* @return true if next will succeed
* @throws ConcurrentModificationException if the list was modified
*/
public boolean hasNext()
{
checkMod();
return (next != null);
}
/**
* Returns true if more elements exist via previous.
*
* @return true if previous will succeed
* @throws ConcurrentModificationException if the list was modified
*/
public boolean hasPrevious()
{
checkMod();
return (previous != null);
}
/**
* Returns the next element.
*
* @return the next element
* @throws ConcurrentModificationException if the list was modified
* @throws NoSuchElementException if there is no next
*/
public Object next()
{
checkMod();
if (next == null)
throw new NoSuchElementException();
position++;
lastReturned = previous = next;
next = lastReturned.next;
return lastReturned.data;
}
/**
* Returns the previous element.
*
* @return the previous element
* @throws ConcurrentModificationException if the list was modified
* @throws NoSuchElementException if there is no previous
*/
public Object previous()
{
checkMod();
if (previous == null)
throw new NoSuchElementException();
position--;
lastReturned = next = previous;
previous = lastReturned.previous;
return lastReturned.data;
}
/**
* Remove the most recently returned element from the list.
*
* @throws ConcurrentModificationException if the list was modified
* @throws IllegalStateException if there was no last element
*/
public void remove()
{
checkMod();
if (lastReturned == null)
throw new IllegalStateException();
// Adjust the position to before the removed element, if the element
// being removed is behind the cursor.
if (lastReturned == previous)
position--;
next = lastReturned.next;
previous = lastReturned.previous;
removeEntry(lastReturned);
knownMod++;
lastReturned = null;
}
/**
* Adds an element between the previous and next, and advance to the next.
*
* @param o the element to add
* @throws ConcurrentModificationException if the list was modified
*/
public void add(Object o)
{
checkMod();
modCount++;
knownMod++;
size++;
position++;
Entry e = new Entry(o);
e.previous = previous;
e.next = next;
if (previous != null)
previous.next = e;
else
first = e;
if (next != null)
next.previous = e;
else
last = e;
previous = e;
lastReturned = null;
}
/**
* Changes the contents of the element most recently returned.
*
* @param o the new element
* @throws ConcurrentModificationException if the list was modified
* @throws IllegalStateException if there was no last element
*/
public void set(Object o)
{
checkMod();
if (lastReturned == null)
throw new IllegalStateException();
lastReturned.data = o;
}
} // class LinkedListItr
}
-451
View File
@@ -1,451 +0,0 @@
/* List.java -- An ordered collection which allows indexed access
Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* An ordered collection (also known as a list). This collection allows
* access to elements by position, as well as control on where elements
* are inserted. Unlike sets, duplicate elements are permitted by this
* general contract (if a subclass forbids duplicates, this should be
* documented).
* <p>
*
* List places additional requirements on <code>iterator</code>,
* <code>add</code>, <code>remove</code>, <code>equals</code>, and
* <code>hashCode</code>, in addition to requiring more methods. List
* indexing is 0-based (like arrays), although some implementations may
* require time proportional to the index to obtain an arbitrary element.
* The List interface is incompatible with Set; you cannot implement both
* simultaneously.
* <p>
*
* Lists also provide a <code>ListIterator</code> which allows bidirectional
* traversal and other features atop regular iterators. Lists can be
* searched for arbitrary elements, and allow easy insertion and removal
* of multiple elements in one method call.
* <p>
*
* Note: While lists may contain themselves as elements, this leads to
* undefined (usually infinite recursive) behavior for some methods like
* hashCode or equals.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see Set
* @see ArrayList
* @see LinkedList
* @see Vector
* @see Arrays#asList(Object[])
* @see Collections#nCopies(int, Object)
* @see Collections#EMPTY_LIST
* @see AbstractList
* @see AbstractSequentialList
* @since 1.2
* @status updated to 1.4
*/
public interface List extends Collection
{
/**
* Insert an element into the list at a given position (optional operation).
* This shifts all existing elements from that position to the end one
* index to the right. This version of add has no return, since it is
* assumed to always succeed if there is no exception.
*
* @param index the location to insert the item
* @param o the object to insert
* @throws UnsupportedOperationException if this list does not support the
* add operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
* @throws ClassCastException if o cannot be added to this list due to its
* type
* @throws IllegalArgumentException if o cannot be added to this list for
* some other reason
* @throws NullPointerException if o is null and this list doesn't support
* the addition of null values.
*/
void add(int index, Object o);
/**
* Add an element to the end of the list (optional operation). If the list
* imposes restraints on what can be inserted, such as no null elements,
* this should be documented.
*
* @param o the object to add
* @return true, as defined by Collection for a modified list
* @throws UnsupportedOperationException if this list does not support the
* add operation
* @throws ClassCastException if o cannot be added to this list due to its
* type
* @throws IllegalArgumentException if o cannot be added to this list for
* some other reason
* @throws NullPointerException if o is null and this list doesn't support
* the addition of null values.
*/
boolean add(Object o);
/**
* Insert the contents of a collection into the list at a given position
* (optional operation). Shift all elements at that position to the right
* by the number of elements inserted. This operation is undefined if
* this list is modified during the operation (for example, if you try
* to insert a list into itself).
*
* @param index the location to insert the collection
* @param c the collection to insert
* @return true if the list was modified by this action, that is, if c is
* non-empty
* @throws UnsupportedOperationException if this list does not support the
* addAll operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
* @throws ClassCastException if some element of c cannot be added to this
* list due to its type
* @throws IllegalArgumentException if some element of c cannot be added
* to this list for some other reason
* @throws NullPointerException if some element of c is null and this list
* doesn't support the addition of null values.
* @throws NullPointerException if the specified collection is null
* @see #add(int, Object)
*/
boolean addAll(int index, Collection c);
/**
* Add the contents of a collection to the end of the list (optional
* operation). This operation is undefined if this list is modified
* during the operation (for example, if you try to insert a list into
* itself).
*
* @param c the collection to add
* @return true if the list was modified by this action, that is, if c is
* non-empty
* @throws UnsupportedOperationException if this list does not support the
* addAll operation
* @throws ClassCastException if some element of c cannot be added to this
* list due to its type
* @throws IllegalArgumentException if some element of c cannot be added
* to this list for some other reason
* @throws NullPointerException if the specified collection is null
* @throws NullPointerException if some element of c is null and this list
* doesn't support the addition of null values.
* @see #add(Object)
*/
boolean addAll(Collection c);
/**
* Clear the list, such that a subsequent call to isEmpty() would return
* true (optional operation).
*
* @throws UnsupportedOperationException if this list does not support the
* clear operation
*/
void clear();
/**
* Test whether this list contains a given object as one of its elements.
* This is defined as the existence of an element e such that
* <code>o == null ? e == null : o.equals(e)</code>.
*
* @param o the element to look for
* @return true if this list contains the element
* @throws ClassCastException if the type of o is not a valid type
* for this list.
* @throws NullPointerException if o is null and the list doesn't
* support null values.
*/
boolean contains(Object o);
/**
* Test whether this list contains every element in a given collection.
*
* @param c the collection to test for
* @return true if for every element o in c, contains(o) would return true
* @throws NullPointerException if the collection is null
* @throws ClassCastException if the type of any element in c is not a valid
* type for this list.
* @throws NullPointerException if some element of c is null and this
* list does not support null values.
* @see #contains(Object)
*/
boolean containsAll(Collection c);
/**
* Test whether this list is equal to another object. A List is defined to be
* equal to an object if and only if that object is also a List, and the two
* lists have the same sequence. Two lists l1 and l2 are equal if and only
* if <code>l1.size() == l2.size()</code>, and for every integer n between 0
* and <code>l1.size() - 1</code> inclusive, <code>l1.get(n) == null ?
* l2.get(n) == null : l1.get(n).equals(l2.get(n))</code>.
*
* @param o the object to test for equality with this list
* @return true if o is equal to this list
* @see Object#equals(Object)
* @see #hashCode()
*/
boolean equals(Object o);
/**
* Get the element at a given index in this list.
*
* @param index the index of the element to be returned
* @return the element at index index in this list
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
Object get(int index);
/**
* Obtains a hash code for this list. In order to obey the general
* contract of the hashCode method of class Object, this value is
* calculated as follows:
*
<p><pre>hashCode = 1;
Iterator i = list.iterator();
while (i.hasNext())
{
Object obj = i.next();
hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
}</pre>
*
* <p>This ensures that the general contract of Object.hashCode()
* is adhered to.
*
* @return the hash code of this list
* @see Object#hashCode()
* @see #equals(Object)
*/
int hashCode();
/**
* Obtain the first index at which a given object is to be found in this
* list.
*
* @param o the object to search for
* @return the least integer n such that <code>o == null ? get(n) == null :
* o.equals(get(n))</code>, or -1 if there is no such index.
* @throws ClassCastException if the type of o is not a valid
* type for this list.
* @throws NullPointerException if o is null and this
* list does not support null values.
*/
int indexOf(Object o);
/**
* Test whether this list is empty, that is, if size() == 0.
*
* @return true if this list contains no elements
*/
boolean isEmpty();
/**
* Obtain an Iterator over this list, whose sequence is the list order.
*
* @return an Iterator over the elements of this list, in order
*/
Iterator iterator();
/**
* Obtain the last index at which a given object is to be found in this
* list.
*
* @return the greatest integer n such that <code>o == null ? get(n) == null
* : o.equals(get(n))</code>, or -1 if there is no such index.
* @throws ClassCastException if the type of o is not a valid
* type for this list.
* @throws NullPointerException if o is null and this
* list does not support null values.
*/
int lastIndexOf(Object o);
/**
* Obtain a ListIterator over this list, starting at the beginning.
*
* @return a ListIterator over the elements of this list, in order, starting
* at the beginning
*/
ListIterator listIterator();
/**
* Obtain a ListIterator over this list, starting at a given position.
* A first call to next() would return the same as get(index), and a
* first call to previous() would return the same as get(index - 1).
*
* @param index the position, between 0 and size() inclusive, to begin the
* iteration from
* @return a ListIterator over the elements of this list, in order, starting
* at index
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
ListIterator listIterator(int index);
/**
* Remove the element at a given position in this list (optional operation).
* Shifts all remaining elements to the left to fill the gap.
*
* @param index the position within the list of the object to remove
* @return the object that was removed
* @throws UnsupportedOperationException if this list does not support the
* remove operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
Object remove(int index);
/**
* Remove the first occurence of an object from this list (optional
* operation). That is, remove the first element e such that
* <code>o == null ? e == null : o.equals(e)</code>.
*
* @param o the object to remove
* @return true if the list changed as a result of this call, that is, if
* the list contained at least one occurrence of o
* @throws UnsupportedOperationException if this list does not support the
* remove operation
* @throws ClassCastException if the type of o is not a valid
* type for this list.
* @throws NullPointerException if o is null and this
* list does not support removing null values.
*/
boolean remove(Object o);
/**
* Remove all elements of a given collection from this list (optional
* operation). That is, remove every element e such that c.contains(e).
*
* @param c the collection to filter out
* @return true if this list was modified as a result of this call
* @throws UnsupportedOperationException if this list does not support the
* removeAll operation
* @throws NullPointerException if the collection is null
* @throws ClassCastException if the type of any element in c is not a valid
* type for this list.
* @throws NullPointerException if some element of c is null and this
* list does not support removing null values.
* @see #remove(Object)
* @see #contains(Object)
*/
boolean removeAll(Collection c);
/**
* Remove all elements of this list that are not contained in a given
* collection (optional operation). That is, remove every element e such
* that !c.contains(e).
*
* @param c the collection to retain
* @return true if this list was modified as a result of this call
* @throws UnsupportedOperationException if this list does not support the
* retainAll operation
* @throws NullPointerException if the collection is null
* @throws ClassCastException if the type of any element in c is not a valid
* type for this list.
* @throws NullPointerException if some element of c is null and this
* list does not support retaining null values.
* @see #remove(Object)
* @see #contains(Object)
*/
boolean retainAll(Collection c);
/**
* Replace an element of this list with another object (optional operation).
*
* @param index the position within this list of the element to be replaced
* @param o the object to replace it with
* @return the object that was replaced
* @throws UnsupportedOperationException if this list does not support the
* set operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
* @throws ClassCastException if o cannot be added to this list due to its
* type
* @throws IllegalArgumentException if o cannot be added to this list for
* some other reason
* @throws NullPointerException if o is null and this
* list does not support null values.
*/
Object set(int index, Object o);
/**
* Get the number of elements in this list. If the list contains more
* than Integer.MAX_VALUE elements, return Integer.MAX_VALUE.
*
* @return the number of elements in the list
*/
int size();
/**
* Obtain a List view of a subsection of this list, from fromIndex
* (inclusive) to toIndex (exclusive). If the two indices are equal, the
* sublist is empty. The returned list should be modifiable if and only
* if this list is modifiable. Changes to the returned list should be
* reflected in this list. If this list is structurally modified in
* any way other than through the returned list, the result of any subsequent
* operations on the returned list is undefined.
*
* @param fromIndex the index that the returned list should start from
* (inclusive)
* @param toIndex the index that the returned list should go to (exclusive)
* @return a List backed by a subsection of this list
* @throws IndexOutOfBoundsException if fromIndex &lt; 0
* || toIndex &gt; size() || fromIndex &gt; toIndex
*/
List subList(int fromIndex, int toIndex);
/**
* Copy the current contents of this list into an array.
*
* @return an array of type Object[] and length equal to the length of this
* list, containing the elements currently in this list, in order
*/
Object[] toArray();
/**
* Copy the current contents of this list into an array. If the array passed
* as an argument has length less than that of this list, an array of the
* same run-time type as a, and length equal to the length of this list, is
* allocated using Reflection. Otherwise, a itself is used. The elements of
* this list are copied into it, and if there is space in the array, the
* following element is set to null. The resultant array is returned.
* Note: The fact that the following element is set to null is only useful
* if it is known that this list does not contain any null elements.
*
* @param a the array to copy this list into
* @return an array containing the elements currently in this list, in
* order
* @throws ArrayStoreException if the type of any element of the
* collection is not a subtype of the element type of a
* @throws NullPointerException if the specified array is null
*/
Object[] toArray(Object[] a);
}
-170
View File
@@ -1,170 +0,0 @@
/* ListIterator.java -- Extended Iterator for iterating over ordered lists
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* An extended version of Iterator to support the extra features of Lists. The
* elements may be accessed in forward or reverse order, elements may be
* replaced as well as removed, and new elements may be inserted, during the
* traversal of the list.
* <p>
*
* A list with n elements provides n+1 iterator positions (the front, the end,
* or between two elements). Note that <code>remove</code> and <code>set</code>
* operate on the last element returned, whether it was by <code>next</code>
* or <code>previous</code>.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see List
* @see Iterator
* @see Enumeration
* @since 1.2
* @status updated to 1.4
*/
public interface ListIterator extends Iterator
{
/**
* Tests whether there are elements remaining in the list in the forward
* direction. In other words, next() will not fail with a
* NoSuchElementException.
*
* @return true if the list continues in the forward direction
*/
boolean hasNext();
/**
* Tests whether there are elements remaining in the list in the reverse
* direction. In other words, previous() will not fail with a
* NoSuchElementException.
*
* @return true if the list continues in the reverse direction
*/
boolean hasPrevious();
/**
* Obtain the next element in the list in the forward direction. Repeated
* calls to next may be used to iterate over the entire list, or calls to
* next and previous may be used together to go forwards and backwards.
* Alternating calls to next and previous will return the same element.
*
* @return the next element in the list in the forward direction
* @throws NoSuchElementException if there are no more elements
*/
Object next();
/**
* Obtain the next element in the list in the reverse direction. Repeated
* calls to previous may be used to iterate backwards over the entire list,
* or calls to next and previous may be used together to go forwards and
* backwards. Alternating calls to next and previous will return the same
* element.
*
* @return the next element in the list in the reverse direction
* @throws NoSuchElementException if there are no more elements
*/
Object previous();
/**
* Find the index of the element that would be returned by a call to next.
* If hasNext() returns false, this returns the list size.
*
* @return the index of the element that would be returned by next()
*/
int nextIndex();
/**
* Find the index of the element that would be returned by a call to
* previous. If hasPrevious() returns false, this returns -1.
*
* @return the index of the element that would be returned by previous()
*/
int previousIndex();
/**
* Insert an element into the list at the current position of the iterator
* (optional operation). The element is inserted in between the element that
* would be returned by previous and the element that would be returned by
* next. After the insertion, a subsequent call to next is unaffected, but
* a call to previous returns the item that was added. The values returned
* by nextIndex() and previousIndex() are incremented.
*
* @param o the object to insert into the list
* @throws ClassCastException if the object is of a type which cannot be added
* to this list.
* @throws IllegalArgumentException if some other aspect of the object stops
* it being added to this list.
* @throws UnsupportedOperationException if this ListIterator does not
* support the add operation.
*/
void add(Object o);
/**
* Remove from the list the element last returned by a call to next or
* previous (optional operation). This method may only be called if neither
* add nor remove have been called since the last call to next or previous.
*
* @throws IllegalStateException if neither next or previous have been
* called, or if add or remove has been called since the last call
* to next or previous
* @throws UnsupportedOperationException if this ListIterator does not
* support the remove operation
*/
void remove();
/**
* Replace the element last returned by a call to next or previous with a
* given object (optional operation). This method may only be called if
* neither add nor remove have been called since the last call to next or
* previous.
*
* @param o the object to replace the element with
* @throws ClassCastException the object is of a type which cannot be added
* to this list
* @throws IllegalArgumentException some other aspect of the object stops
* it being added to this list
* @throws IllegalStateException if neither next or previous have been
* called, or if add or remove has been called since the last call
* to next or previous
* @throws UnsupportedOperationException if this ListIterator does not
* support the set operation
*/
void set(Object o);
}
-140
View File
@@ -1,140 +0,0 @@
/* ListResourceBundle -- a resource bundle build around a list
Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* A <code>ListResouceBundle</code> provides an easy way, to create your own
* resource bundle. It is an abstract class that you can subclass. You should
* then overwrite the getContents method, that provides a key/value list.
*
* <p>The key/value list is a two dimensional list of Object. The first
* dimension ranges over the resources. The second dimension ranges from
* zero (key) to one (value). The keys must be of type String, and they are
* case-sensitive. For example:
*
<br><pre>public class MyResources
extends ListResourceBundle
{
public Object[][] getContents()
{
return contents;
}
static final Object[][] contents =
{
// LOCALIZED STRINGS
{"s1", "The disk \"{1}\" contains {0}."}, // MessageFormat pattern
{"s2", "1"}, // location of {0} in pattern
{"s3", "My Disk"}, // sample disk name
{"s4", "no files"}, // first ChoiceFormat choice
{"s5", "one file"}, // second ChoiceFormat choice
{"s6", "{0,number} files"} // third ChoiceFormat choice
{"s7", "3 Mar 96"}, // sample date
{"s8", new Dimension(1,5)} // real object, not just string
// END OF LOCALIZED MATERIAL
};
}</pre>
*
* @author Jochen Hoenicke
* @author Eric Blake (ebb9@email.byu.edu)
* @see Locale
* @see PropertyResourceBundle
* @since 1.1
* @status updated to 1.4
*/
public abstract class ListResourceBundle extends ResourceBundle
{
/**
* The constructor. It does nothing special.
*/
public ListResourceBundle()
{
}
/**
* Gets a resource for a given key. This is called by <code>getObject</code>.
*
* @param key the key of the resource
* @return the resource for the key, or null if it doesn't exist
*/
public final Object handleGetObject(String key)
{
Object[][] contents = getContents();
int i = contents.length;
while (--i >= 0)
if (key.equals(contents[i][0]))
return contents[i][1];
return null;
}
/**
* This method should return all keys for which a resource exists.
*
* @return an enumeration of the keys
*/
public Enumeration getKeys()
{
// We make a new Set that holds all the keys, then return an enumeration
// for that. This prevents modifications from ruining the enumeration,
// as well as ignoring duplicates.
final Object[][] contents = getContents();
Set s = new HashSet();
int i = contents.length;
while (--i >= 0)
s.add(contents[i][0]);
ResourceBundle bundle = parent;
// Eliminate tail recursion.
while (bundle != null)
{
Enumeration e = bundle.getKeys();
while (e.hasMoreElements())
s.add(e.nextElement());
bundle = bundle.parent;
}
return Collections.enumeration(s);
}
/**
* Gets the key/value list. You must override this method, and should not
* provide duplicate keys or null entries.
*
* @return a two dimensional list of String key / Object resouce pairs
*/
protected abstract Object[][] getContents();
} // class ListResourceBundle
-338
View File
@@ -1,338 +0,0 @@
/* Map.java: interface Map -- An object that maps keys to values
interface Map.Entry -- an Entry in a Map
Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* An object that maps keys onto values. Keys cannot be duplicated. This
* interface replaces the obsolete {@link Dictionary} abstract class.
* <p>
*
* The map has three collection views, which are backed by the map
* (modifications on one show up on the other): a set of keys, a collection
* of values, and a set of key-value mappings. Some maps have a guaranteed
* order, but not all do.
* <p>
*
* Note: Be careful about using mutable keys. Behavior is unspecified if
* a key's comparison behavior is changed after the fact. As a corollary
* to this rule, don't use a Map as one of its own keys or values, as it makes
* hashCode and equals have undefined behavior.
* <p>
*
* All maps are recommended to provide a no argument constructor, which builds
* an empty map, and one that accepts a Map parameter and copies the mappings
* (usually by putAll), to create an equivalent map. Unfortunately, Java
* cannot enforce these suggestions.
* <p>
*
* The map may be unmodifiable, in which case unsupported operations will
* throw an UnsupportedOperationException. Note that some operations may be
* safe, such as putAll(m) where m is empty, even if the operation would
* normally fail with a non-empty argument.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see HashMap
* @see TreeMap
* @see Hashtable
* @see SortedMap
* @see Collection
* @see Set
* @since 1.2
* @status updated to 1.4
*/
public interface Map
{
/**
* Remove all entries from this Map (optional operation).
*
* @throws UnsupportedOperationException if clear is not supported
*/
void clear();
/**
* Returns true if this contains a mapping for the given key.
*
* @param key the key to search for
* @return true if the map contains the key
* @throws ClassCastException if the key is of an inappropriate type
* @throws NullPointerException if key is <code>null</code> but the map
* does not permit null keys
*/
boolean containsKey(Object key);
/**
* Returns true if this contains at least one mapping with the given value.
* In other words, returns true if a value v exists where
* <code>(value == null ? v == null : value.equals(v))</code>. This usually
* requires linear time.
*
* @param value the value to search for
* @return true if the map contains the value
* @throws ClassCastException if the type of the value is not a valid type
* for this map.
* @throws NullPointerException if the value is null and the map doesn't
* support null values.
*/
boolean containsValue(Object value);
/**
* Returns a set view of the mappings in this Map. Each element in the
* set is a Map.Entry. The set is backed by the map, so that changes in
* one show up in the other. Modifications made while an iterator is
* in progress cause undefined behavior. If the set supports removal,
* these methods remove the underlying mapping from the map:
* <code>Iterator.remove</code>, <code>Set.remove</code>,
* <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
* Element addition, via <code>add</code> or <code>addAll</code>, is
* not supported via this set.
*
* @return the set view of all mapping entries
* @see Map.Entry
*/
Set entrySet();
/**
* Compares the specified object with this map for equality. Returns
* <code>true</code> if the other object is a Map with the same mappings,
* that is,<br>
* <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
* This allows comparison of maps, regardless of implementation.
*
* @param o the object to be compared
* @return true if the object equals this map
* @see Set#equals(Object)
*/
boolean equals(Object o);
/**
* Returns the value mapped by the given key. Returns <code>null</code> if
* there is no mapping. However, in Maps that accept null values, you
* must rely on <code>containsKey</code> to determine if a mapping exists.
*
* @param key the key to look up
* @return the value associated with the key, or null if key not in map
* @throws ClassCastException if the key is an inappropriate type
* @throws NullPointerException if this map does not accept null keys
* @see #containsKey(Object)
*/
Object get(Object key);
/**
* Associates the given key to the given value (optional operation). If the
* map already contains the key, its value is replaced. Be aware that in
* a map that permits <code>null</code> values, a null return does not
* always imply that the mapping was created.
*
* @param key the key to map
* @param value the value to be mapped
* @return the previous value of the key, or null if there was no mapping
* @throws UnsupportedOperationException if the operation is not supported
* @throws ClassCastException if the key or value is of the wrong type
* @throws IllegalArgumentException if something about this key or value
* prevents it from existing in this map
* @throws NullPointerException if either the key or the value is null,
* and the map forbids null keys or values
* @see #containsKey(Object)
*/
Object put(Object key, Object value);
/**
* Returns the hash code for this map. This is the sum of all hashcodes
* for each Map.Entry object in entrySet. This allows comparison of maps,
* regardless of implementation, and satisfies the contract of
* Object.hashCode.
*
* @return the hash code
* @see Map.Entry#hashCode()
*/
int hashCode();
/**
* Returns true if the map contains no mappings.
*
* @return true if the map is empty
*/
boolean isEmpty();
/**
* Returns a set view of the keys in this Map. The set is backed by the
* map, so that changes in one show up in the other. Modifications made
* while an iterator is in progress cause undefined behavior. If the set
* supports removal, these methods remove the underlying mapping from
* the map: <code>Iterator.remove</code>, <code>Set.remove</code>,
* <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
* Element addition, via <code>add</code> or <code>addAll</code>, is
* not supported via this set.
*
* @return the set view of all keys
*/
Set keySet();
/**
* Copies all entries of the given map to this one (optional operation). If
* the map already contains a key, its value is replaced.
*
* @param m the mapping to load into this map
* @throws UnsupportedOperationException if the operation is not supported
* @throws ClassCastException if a key or value is of the wrong type
* @throws IllegalArgumentException if something about a key or value
* prevents it from existing in this map
* @throws NullPointerException if the map forbids null keys or values, or
* if <code>m</code> is null.
* @see #put(Object, Object)
*/
void putAll(Map m);
/**
* Removes the mapping for this key if present (optional operation). If
* the key is not present, this returns null. Note that maps which permit
* null values may also return null if the key was removed.
*
* @param key the key to remove
* @return the value the key mapped to, or null if not present.
* @throws UnsupportedOperationException if deletion is unsupported
* @throws NullPointerException if the key is null and this map doesn't
* support null keys.
* @throws ClassCastException if the type of the key is not a valid type
* for this map.
*/
Object remove(Object key);
/**
* Returns the number of key-value mappings in the map. If there are more
* than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE.
*
* @return the number of mappings
*/
int size();
/**
* Returns a collection (or bag) view of the values in this Map. The
* collection is backed by the map, so that changes in one show up in
* the other. Modifications made while an iterator is in progress cause
* undefined behavior. If the collection supports removal, these methods
* remove the underlying mapping from the map: <code>Iterator.remove</code>,
* <code>Collection.remove</code>, <code>removeAll</code>,
* <code>retainAll</code>, and <code>clear</code>. Element addition, via
* <code>add</code> or <code>addAll</code>, is not supported via this
* collection.
*
* @return the collection view of all values
*/
Collection values();
/**
* A map entry (key-value pair). The Map.entrySet() method returns a set
* view of these objects; there is no other valid way to come across them.
* These objects are only valid for the duration of an iteration; in other
* words, if you mess with one after modifying the map, you are asking
* for undefined behavior.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Map
* @see Map#entrySet()
* @since 1.2
* @status updated to 1.4
*/
interface Entry
{
/**
* Get the key corresponding to this entry.
*
* @return the key
*/
Object getKey();
/**
* Get the value corresponding to this entry. If you already called
* Iterator.remove(), this is undefined.
*
* @return the value
*/
Object getValue();
/**
* Replaces the value with the specified object (optional operation).
* This writes through to the map, and is undefined if you already
* called Iterator.remove().
*
* @param value the new value to store
* @return the old value
* @throws UnsupportedOperationException if the operation is not supported
* @throws ClassCastException if the value is of the wrong type
* @throws IllegalArgumentException if something about the value
* prevents it from existing in this map
* @throws NullPointerException if the map forbids null values
*/
Object setValue(Object value);
/**
* Returns the hash code of the entry. This is defined as the
* exclusive-or of the hashcodes of the key and value (using 0 for
* <code>null</code>). In other words, this must be:
*
<p><pre>(getKey() == null ? 0 : getKey().hashCode())
^ (getValue() == null ? 0 : getValue().hashCode())</pre>
*
* @return the hash code
*/
int hashCode();
/**
* Compares the specified object with this entry. Returns true only if
* the object is a mapping of identical key and value. In other words,
* this must be:
*
<p><pre>(o instanceof Map.Entry)
&& (getKey() == null ? ((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
*/
boolean equals(Object o);
}
}
@@ -1,105 +0,0 @@
/* MissingResourceException.java -- thrown for a missing resource
Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* This exception is thrown when a resource is missing.
*
* @author Jochen Hoenicke
* @author Warren Levy (warrenl@cygnus.com)
* @see ResourceBundle
* @since 1.1
* @status updated to 1.4
*/
public class MissingResourceException extends RuntimeException
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = -4876345176062000401L;
/**
* The name of the resource bundle requested by user.
*
* @serial the class name of the resource bundle
*/
private final String className;
/**
* The key of the resource in the bundle requested by user.
*
* @serial the name of the resouce
*/
private final String key;
/**
* Creates a new exception, with the specified parameters.
*
* @param s the detail message
* @param className the name of the resource bundle
* @param key the key of the missing resource
*/
public MissingResourceException(String s, String className, String key)
{
super(s);
this.className = className;
this.key = key;
}
/**
* Gets the name of the resource bundle, for which a resource is missing.
*
* @return the name of the resource bundle
*/
public String getClassName()
{
return className;
}
/**
* Gets the key of the resource that is missing bundle, this is an empty
* string if the whole resource bundle is missing.
*
* @return the name of the resource bundle
*/
public String getKey()
{
return key;
}
}
@@ -1,88 +0,0 @@
/* NoSuchElementException.java -- Attempt to access element that does not exist
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
*/
/**
* Exception thrown when an attempt is made to access an element that does not
* exist. This exception is thrown by the Enumeration, Iterator and
* ListIterator classes if the nextElement, next or previous method goes
* beyond the end of the list of elements that are being accessed. It is also
* thrown by Vector and Stack when attempting to access the first or last
* element of an empty collection.
*
* @author Warren Levy (warrenl@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
* @see Enumeration
* @see Iterator
* @see ListIterator
* @see Enumeration#nextElement()
* @see Iterator#next()
* @see ListIterator#previous()
* @since 1.0
* @status updated to 1.4
*/
public class NoSuchElementException extends RuntimeException
{
/**
* Compatible with JDK 1.0.
*/
private static final long serialVersionUID = 6769829250639411880L;
/**
* Constructs a NoSuchElementException with no detail message.
*/
public NoSuchElementException()
{
}
/**
* Constructs a NoSuchElementException with a detail message.
*
* @param detail the detail message for the exception
*/
public NoSuchElementException(String detail)
{
super(detail);
}
}
-180
View File
@@ -1,180 +0,0 @@
/* Observable.java -- an object to be observed
Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* This class represents an object which is observable. Other objects may
* register their intent to be notified when this object changes; and when
* this object does change, it will trigger the <code>update</code> method
* of each observer.
*
* Note that the <code>notifyObservers()</code> method of this class is
* unrelated to the <code>notify()</code> of Object.
*
* @author Warren Levy (warrenl@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
* @see Observer
* @status updated to 1.4
*/
public class Observable
{
/** Tracks whether this object has changed. */
private boolean changed;
/* List of the Observers registered as interested in this Observable. */
private LinkedHashSet observers;
/**
* Constructs an Observable with zero Observers.
*/
public Observable()
{
observers = new LinkedHashSet();
}
/**
* Adds an Observer. If the observer was already added this method does
* nothing.
*
* @param observer Observer to add
* @throws NullPointerException if observer is null
*/
public synchronized void addObserver(Observer observer)
{
observers.add(observer);
}
/**
* Reset this Observable's state to unchanged. This is called automatically
* by <code>notifyObservers</code> once all observers have been notified.
*
* @see #notifyObservers()
*/
protected synchronized void clearChanged()
{
changed = false;
}
/**
* Returns the number of observers for this object.
*
* @return number of Observers for this
*/
public synchronized int countObservers()
{
return observers.size();
}
/**
* Deletes an Observer of this Observable.
*
* @param victim Observer to delete
*/
public synchronized void deleteObserver(Observer victim)
{
observers.remove(victim);
}
/**
* Deletes all Observers of this Observable.
*/
public synchronized void deleteObservers()
{
observers.clear();
}
/**
* True if <code>setChanged</code> has been called more recently than
* <code>clearChanged</code>.
*
* @return whether or not this Observable has changed
*/
public synchronized boolean hasChanged()
{
return changed;
}
/**
* If the Observable has actually changed then tell all Observers about it,
* then reset state to unchanged.
*
* @see #notifyObservers(Object)
* @see Observer#update(Observable, Object)
*/
public void notifyObservers()
{
notifyObservers(null);
}
/**
* If the Observable has actually changed then tell all Observers about it,
* then reset state to unchanged. Note that though the order of
* notification is unspecified in subclasses, in Observable it is in the
* order of registration.
*
* @param obj argument to Observer's update method
* @see Observer#update(Observable, Object)
*/
public void notifyObservers(Object obj)
{
if (! hasChanged())
return;
// Create clone inside monitor, as that is relatively fast and still
// important to keep threadsafe, but update observers outside of the
// lock since update() can call arbitrary code.
Set s;
synchronized (this)
{
s = (Set) observers.clone();
}
int i = s.size();
Iterator iter = s.iterator();
while (--i >= 0)
((Observer) iter.next()).update(this, obj);
clearChanged();
}
/**
* Marks this Observable as having changed.
*/
protected synchronized void setChanged()
{
changed = true;
}
}
-60
View File
@@ -1,60 +0,0 @@
/* Observer.java -- an object that will be informed of changes in an Observable
Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* Interface that is implemented when a class wants to be informed of changes
* in Observable objects.
*
* @author Warren Levy (warrenl@cygnus.com)
* @see Observable
* @status updated to 1.4
*/
public interface Observer
{
/**
* This method is called whenever the observable object changes, and has
* called <code>notifyObservers</code>. The Observable object can pass
* arbitrary information in the second parameter.
*
* @param observable the Observable object that changed
* @param arg arbitrary information, usually relating to the change
*/
void update(Observable observable, Object arg);
}
-574
View File
@@ -1,574 +0,0 @@
/* Properties.java -- a set of persistent properties
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* A set of persistent properties, which can be saved or loaded from a stream.
* A property list may also contain defaults, searched if the main list
* does not contain a property for a given key.
*
* An example of a properties file for the german language is given
* here. This extends the example given in ListResourceBundle.
* Create a file MyResource_de.properties with the following contents
* and put it in the CLASSPATH. (The character
* <code>\</code><code>u00e4</code> is the german umlaut)
*
*
<pre>s1=3
s2=MeineDisk
s3=3. M\<code></code>u00e4rz 96
s4=Die Diskette ''{1}'' enth\<code></code>u00e4lt {0} in {2}.
s5=0
s6=keine Dateien
s7=1
s8=eine Datei
s9=2
s10={0,number} Dateien
s11=Das Formatieren schlug fehl mit folgender Exception: {0}
s12=FEHLER
s13=Ergebnis
s14=Dialog
s15=Auswahlkriterium
s16=1,3</pre>
*
* <p>Although this is a sub class of a hash table, you should never
* insert anything other than strings to this property, or several
* methods, that need string keys and values, will fail. To ensure
* this, you should use the <code>get/setProperty</code> method instead
* of <code>get/put</code>.
*
* Properties are saved in ISO 8859-1 encoding, using Unicode escapes with
* a single <code>u</code> for any character which cannot be represented.
*
* @author Jochen Hoenicke
* @author Eric Blake (ebb9@email.byu.edu)
* @see PropertyResourceBundle
* @status updated to 1.4
*/
public class Properties extends Hashtable
{
// WARNING: Properties is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
/**
* The property list that contains default values for any keys not
* in this property list.
*
* @serial the default properties
*/
protected Properties defaults;
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = 4112578634029874840L;
/**
* Creates a new empty property list with no default values.
*/
public Properties()
{
}
/**
* Create a new empty property list with the specified default values.
*
* @param defaults a Properties object containing the default values
*/
public Properties(Properties defaults)
{
this.defaults = defaults;
}
/**
* Adds the given key/value pair to this properties. This calls
* the hashtable method put.
*
* @param key the key for this property
* @param value the value for this property
* @return The old value for the given key
* @see #getProperty(String)
* @since 1.2
*/
public Object setProperty(String key, String value)
{
return put(key, value);
}
/**
* Reads a property list from an input stream. The stream should
* have the following format: <br>
*
* An empty line or a line starting with <code>#</code> or
* <code>!</code> is ignored. An backslash (<code>\</code>) at the
* end of the line makes the line continueing on the next line
* (but make sure there is no whitespace after the backslash).
* Otherwise, each line describes a key/value pair. <br>
*
* The chars up to the first whitespace, = or : are the key. You
* can include this caracters in the key, if you precede them with
* a backslash (<code>\</code>). The key is followed by optional
* whitespaces, optionally one <code>=</code> or <code>:</code>,
* and optionally some more whitespaces. The rest of the line is
* the resource belonging to the key. <br>
*
* Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a
* space), and unicode characters with the
* <code>\\u</code><em>xxxx</em> notation are detected, and
* converted to the corresponding single character. <br>
*
*
<pre># This is a comment
key = value
k\:5 \ a string starting with space and ending with newline\n
# This is a multiline specification; note that the value contains
# no white space.
weekdays: Sunday,Monday,Tuesday,Wednesday,\\
Thursday,Friday,Saturday
# The safest way to include a space at the end of a value:
label = Name:\\u0020</pre>
*
* @param in the input stream
* @throws IOException if an error occurred when reading the input
* @throws NullPointerException if in is null
*/
public void load(InputStream inStream) throws IOException
{
// The spec says that the file must be encoded using ISO-8859-1.
BufferedReader reader =
new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1"));
String line;
while ((line = reader.readLine()) != null)
{
char c = 0;
int pos = 0;
// Leading whitespaces must be deleted first.
while (pos < line.length()
&& Character.isWhitespace(c = line.charAt(pos)))
pos++;
// If empty line or begins with a comment character, skip this line.
if ((line.length() - pos) == 0
|| line.charAt(pos) == '#' || line.charAt(pos) == '!')
continue;
// The characters up to the next Whitespace, ':', or '='
// describe the key. But look for escape sequences.
StringBuffer key = new StringBuffer();
while (pos < line.length()
&& ! Character.isWhitespace(c = line.charAt(pos++))
&& c != '=' && c != ':')
{
if (c == '\\')
{
if (pos == line.length())
{
// The line continues on the next line.
line = reader.readLine();
pos = 0;
while (pos < line.length()
&& Character.isWhitespace(c = line.charAt(pos)))
pos++;
}
else
{
c = line.charAt(pos++);
switch (c)
{
case 'n':
key.append('\n');
break;
case 't':
key.append('\t');
break;
case 'r':
key.append('\r');
break;
case 'u':
if (pos + 4 <= line.length())
{
char uni = (char) Integer.parseInt
(line.substring(pos, pos + 4), 16);
key.append(uni);
pos += 4;
} // else throw exception?
break;
default:
key.append(c);
break;
}
}
}
else
key.append(c);
}
boolean isDelim = (c == ':' || c == '=');
while (pos < line.length()
&& Character.isWhitespace(c = line.charAt(pos)))
pos++;
if (! isDelim && (c == ':' || c == '='))
{
pos++;
while (pos < line.length()
&& Character.isWhitespace(c = line.charAt(pos)))
pos++;
}
StringBuffer element = new StringBuffer(line.length() - pos);
while (pos < line.length())
{
c = line.charAt(pos++);
if (c == '\\')
{
if (pos == line.length())
{
// The line continues on the next line.
line = reader.readLine();
// We might have seen a backslash at the end of
// the file. The JDK ignores the backslash in
// this case, so we follow for compatibility.
if (line == null)
break;
pos = 0;
while (pos < line.length()
&& Character.isWhitespace(c = line.charAt(pos)))
pos++;
element.ensureCapacity(line.length() - pos +
element.length());
}
else
{
c = line.charAt(pos++);
switch (c)
{
case 'n':
element.append('\n');
break;
case 't':
element.append('\t');
break;
case 'r':
element.append('\r');
break;
case 'u':
if (pos + 4 <= line.length())
{
char uni = (char) Integer.parseInt
(line.substring(pos, pos + 4), 16);
element.append(uni);
pos += 4;
} // else throw exception?
break;
default:
element.append(c);
break;
}
}
}
else
element.append(c);
}
put(key.toString(), element.toString());
}
}
/**
* Calls <code>store(OutputStream out, String header)</code> and
* ignores the IOException that may be thrown.
*
* @param out the stream to write to
* @param header a description of the property list
* @throws ClassCastException if this property contains any key or
* value that are not strings
* @deprecated use {@link #store(OutputStream, String)} instead
*/
public void save(OutputStream out, String header)
{
try
{
store(out, header);
}
catch (IOException ex)
{
}
}
/**
* Writes the key/value pairs to the given output stream, in a format
* suitable for <code>load</code>.<br>
*
* If header is not null, this method writes a comment containing
* the header as first line to the stream. The next line (or first
* line if header is null) contains a comment with the current date.
* Afterwards the key/value pairs are written to the stream in the
* following format.<br>
*
* Each line has the form <code>key = value</code>. Newlines,
* Returns and tabs are written as <code>\n,\t,\r</code> resp.
* The characters <code>\, !, #, =</code> and <code>:</code> are
* preceeded by a backslash. Spaces are preceded with a backslash,
* if and only if they are at the beginning of the key. Characters
* that are not in the ascii range 33 to 127 are written in the
* <code>\</code><code>u</code>xxxx Form.<br>
*
* Following the listing, the output stream is flushed but left open.
*
* @param out the output stream
* @param header the header written in the first line, may be null
* @throws ClassCastException if this property contains any key or
* value that isn't a string
* @throws IOException if writing to the stream fails
* @throws NullPointerException if out is null
* @since 1.2
*/
public void store(OutputStream out, String header) throws IOException
{
// The spec says that the file must be encoded using ISO-8859-1.
PrintWriter writer
= new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
if (header != null)
writer.println("#" + header);
writer.println ("#" + Calendar.getInstance ().getTime ());
Iterator iter = entrySet ().iterator ();
int i = size ();
StringBuffer s = new StringBuffer (); // Reuse the same buffer.
while (--i >= 0)
{
Map.Entry entry = (Map.Entry) iter.next ();
formatForOutput ((String) entry.getKey (), s, true);
s.append ('=');
formatForOutput ((String) entry.getValue (), s, false);
writer.println (s);
}
writer.flush ();
}
/**
* Gets the property with the specified key in this property list.
* If the key is not found, the default property list is searched.
* If the property is not found in the default, null is returned.
*
* @param key The key for this property
* @return the value for the given key, or null if not found
* @throws ClassCastException if this property contains any key or
* value that isn't a string
* @see #defaults
* @see #setProperty(String, String)
* @see #getProperty(String, String)
*/
public String getProperty(String key)
{
return getProperty(key, null);
}
/**
* Gets the property with the specified key in this property list. If
* the key is not found, the default property list is searched. If the
* property is not found in the default, the specified defaultValue is
* returned.
*
* @param key The key for this property
* @param defaultValue A default value
* @return The value for the given key
* @throws ClassCastException if this property contains any key or
* value that isn't a string
* @see #defaults
* @see #setProperty(String, String)
*/
public String getProperty(String key, String defaultValue)
{
Properties prop = this;
// Eliminate tail recursion.
do
{
String value = (String) prop.get(key);
if (value != null)
return value;
prop = prop.defaults;
}
while (prop != null);
return defaultValue;
}
/**
* Returns an enumeration of all keys in this property list, including
* the keys in the default property list.
*
* @return an Enumeration of all defined keys
*/
public Enumeration propertyNames()
{
// We make a new Set that holds all the keys, then return an enumeration
// for that. This prevents modifications from ruining the enumeration,
// as well as ignoring duplicates.
Properties prop = this;
Set s = new HashSet();
// Eliminate tail recursion.
do
{
s.addAll(prop.keySet());
prop = prop.defaults;
}
while (prop != null);
return Collections.enumeration(s);
}
/**
* Prints the key/value pairs to the given print stream. This is
* mainly useful for debugging purposes.
*
* @param out the print stream, where the key/value pairs are written to
* @throws ClassCastException if this property contains a key or a
* value that isn't a string
* @see #list(PrintWriter)
*/
public void list(PrintStream out)
{
PrintWriter writer = new PrintWriter (out);
list (writer);
}
/**
* Prints the key/value pairs to the given print writer. This is
* mainly useful for debugging purposes.
*
* @param out the print writer where the key/value pairs are written to
* @throws ClassCastException if this property contains a key or a
* value that isn't a string
* @see #list(PrintStream)
* @since 1.1
*/
public void list(PrintWriter out)
{
out.println ("-- listing properties --");
Iterator iter = entrySet ().iterator ();
int i = size ();
while (--i >= 0)
{
Map.Entry entry = (Map.Entry) iter.next ();
out.print ((String) entry.getKey () + "=");
// JDK 1.3/1.4 restrict the printed value, but not the key,
// to 40 characters, including the truncating ellipsis.
String s = (String ) entry.getValue ();
if (s != null && s.length () > 40)
out.println (s.substring (0, 37) + "...");
else
out.println (s);
}
out.flush ();
}
/**
* Formats a key or value for output in a properties file.
* See store for a description of the format.
*
* @param str the string to format
* @param buffer the buffer to add it to
* @param key true if all ' ' must be escaped for the key, false if only
* leading spaces must be escaped for the value
* @see #store(OutputStream, String)
*/
private void formatForOutput(String str, 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);
break;
default:
if (c < ' ' || c > '~')
{
String hex = Integer.toHexString(c);
buffer.append("\\u0000".substring(0, 6 - hex.length()));
buffer.append(hex);
}
else
buffer.append(c);
}
if (c != ' ')
head = key;
}
}
} // class Properties
-271
View File
@@ -1,271 +0,0 @@
/* PropertyPermission.java -- permission to get and set System properties
Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.security.BasicPermission;
import java.security.Permission;
import java.security.PermissionCollection;
/**
* This class represents the permission to access and modify a property.<br>
*
* The name is the name of the property, e.g. xxx. You can also
* use an asterisk "*" as described in BasicPermission.<br>
*
* The action string is a comma-separated list of keywords. There are
* two possible actions:
* <dl>
* <dt>read</dt>
* <dd>Allows to read the property via <code>System.getProperty</code>.</dd>
* <dt>write</dt>
* <dd>Allows to write the property via <code>System.setProperty</code>.</dd>
* </dl>
*
* The action string is case insensitive (it is converted to lower case).
*
* @see Permission
* @see BasicPermission
* @see SecurityManager
* @author Jochen Hoenicke
* @since 1.2
* @status updated to 1.4
*/
public final class PropertyPermission extends BasicPermission
{
/**
* PropertyPermission uses a more efficient representation than the
* serialized form; this documents the difference.
*
* @serialField action String the action string
*/
private static final ObjectStreamField[] serialPersistentFields =
{
new ObjectStreamField("action", String.class)
};
/**
* Compatible with JDK 1.2+.
*/
private static final long serialVersionUID = 885438825399942851L;
/** Permission to read. */
private static final int READ = 1;
/** Permission to write. */
private static final int WRITE = 2;
/** The set of actions permitted. */
// Package visible for use by PropertyPermissionCollection.
transient int actions;
/**
* The String forms of the actions permitted.
*/
private static final String actionStrings[] =
{
"", "read", "write", "read,write"
};
/**
* Constructs a PropertyPermission with the specified property. Possible
* actions are read and write, comma-separated and case-insensitive.
*
* @param name the name of the property
* @param actions the action string
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if name string contains an
* illegal wildcard or actions string contains an illegal action
* (this includes a null actions string)
*/
public PropertyPermission(String name, String actions)
{
super(name);
if (actions == null)
throw new IllegalArgumentException();
setActions(actions);
}
/**
* Parse the action string and convert actions from external to internal
* form. This will set the internal actions field.
*
* @param str the action string
* @throws IllegalArgumentException if actions string contains an
* illegal action
*/
private void setActions(String str)
{
// Initialising the class java.util.Locale ...
// tries to initialise the Locale.defaultLocale static
// which calls System.getProperty,
// which calls SecurityManager.checkPropertiesAccess,
// which creates a PropertyPermission with action "read,write",
// which calls setActions("read,write").
// If we now were to call toLowerCase on 'str',
// this would call Locale.getDefault() which returns null
// because Locale.defaultLocale hasn't been set yet
// then toLowerCase will fail with a null pointer exception.
//
// The solution is to take a punt on 'str' being lower case, and
// test accordingly. If that fails, we convert 'str' to lower case
// and try the tests again.
if ("read".equals(str))
actions = READ;
else if ("write".equals(str))
actions = WRITE;
else if ("read,write".equals(str) || "write,read".equals(str))
actions = READ | WRITE;
else
{
String lstr = str.toLowerCase();
if ("read".equals(lstr))
actions = READ;
else if ("write".equals(lstr))
actions = WRITE;
else if ("read,write".equals(lstr) || "write,read".equals(lstr))
actions = READ | WRITE;
else
throw new IllegalArgumentException("illegal action " + str);
}
}
/**
* Reads an object from the stream. This converts the external to the
* internal representation.
*
* @param s the stream to read from
* @throws IOException if the stream fails
* @throws ClassNotFoundException if reserialization fails
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
ObjectInputStream.GetField fields = s.readFields();
setActions((String) fields.get("actions", null));
}
/**
* Writes an object to the stream. This converts the internal to the
* external representation.
*
* @param s the stram to write to
* @throws IOException if the stream fails
*/
private void writeObject(ObjectOutputStream s) throws IOException
{
ObjectOutputStream.PutField fields = s.putFields();
fields.put("actions", getActions());
s.writeFields();
}
/**
* Check if this permission implies p. This returns true iff all of
* the following conditions are true:
* <ul>
* <li> p is a PropertyPermission </li>
* <li> this.getName() implies p.getName(),
* e.g. <code>java.*</code> implies <code>java.home</code> </li>
* <li> this.getActions is a subset of p.getActions </li>
* </ul>
*
* @param p the permission to check
* @return true if this permission implies p
*/
public boolean implies(Permission p)
{
// BasicPermission checks for name and type.
if (super.implies(p))
{
// We have to check the actions.
PropertyPermission pp = (PropertyPermission) p;
return (pp.actions & ~actions) == 0;
}
return false;
}
/**
* Check to see whether this object is the same as another
* PropertyPermission object; this is true if it has the same name and
* actions.
*
* @param obj the other object
* @return true if the two are equivalent
*/
public boolean equals(Object obj)
{
return super.equals(obj) && actions == ((PropertyPermission) obj).actions;
}
/**
* Returns the hash code for this permission. It is equivalent to
* <code>getName().hashCode()</code>.
*
* @return the hash code
*/
public int hashCode()
{
return super.hashCode();
}
/**
* Returns the action string. Note that this may differ from the string
* given at the constructor: The actions are converted to lowercase and
* may be reordered.
*
* @return one of "read", "write", or "read,write"
*/
public String getActions()
{
return actionStrings[actions];
}
/**
* Returns a permission collection suitable to take
* PropertyPermission objects.
*
* @return a new empty PermissionCollection
*/
public PermissionCollection newPermissionCollection()
{
return new PropertyPermissionCollection();
}
}
@@ -1,166 +0,0 @@
/* PropertyPermissionCollection.java -- a collection of PropertyPermissions
Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.security.Permission;
import java.security.PermissionCollection;
/**
* This class provides the implementation for
* <code>PropertyPermission.newPermissionCollection()</code>. It only accepts
* PropertyPermissions, and correctly implements <code>implies</code>. It
* is synchronized, as specified in the superclass.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @status an undocumented class, but this matches Sun's serialization
*/
class PropertyPermissionCollection extends PermissionCollection
{
/**
* Compatible with JDK 1.4.
*/
private static final long serialVersionUID = 7015263904581634791L;
/**
* The permissions.
*
* @serial the table of permissions in the collection
*/
private final Hashtable permissions = new Hashtable();
/**
* A flag to detect if "*" is in the collection.
*
* @serial true if "*" is in the collection
*/
private boolean all_allowed;
/**
* Adds a PropertyPermission to this collection.
*
* @param permission the permission to add
* @throws IllegalArgumentException if permission is not a PropertyPermission
* @throws SecurityException if collection is read-only
*/
public void add(Permission permission)
{
if (isReadOnly())
throw new SecurityException("readonly");
if (! (permission instanceof PropertyPermission))
throw new IllegalArgumentException();
PropertyPermission pp = (PropertyPermission) permission;
String name = pp.getName();
if (name.equals("*"))
all_allowed = true;
PropertyPermission old = (PropertyPermission) permissions.get(name);
if (old != null)
{
if ((pp.actions | old.actions) == old.actions)
pp = old; // Old implies pp.
else if ((pp.actions | old.actions) != pp.actions)
// Here pp doesn't imply old; the only case left is both actions.
pp = new PropertyPermission(name, "read,write");
}
permissions.put(name, pp);
}
/**
* Returns true if this collection implies the given permission. This even
* returns true for this case:
*
* <pre>
* collection.add(new PropertyPermission("a.*", "read"));
* collection.add(new PropertyPermission("a.b.*", "write"));
* collection.implies(new PropertyPermission("a.b.c", "read,write"));
* </pre>
*
* @param permission the permission to check
* @return true if it is implied by this
*/
public boolean implies(Permission permission)
{
if (! (permission instanceof PropertyPermission))
return false;
PropertyPermission toImply = (PropertyPermission) permission;
int actions = toImply.actions;
if (all_allowed)
{
int all_actions = ((PropertyPermission) permissions.get("*")).actions;
actions &= ~all_actions;
if (actions == 0)
return true;
}
String name = toImply.getName();
if (name.equals("*"))
return false;
int prefixLength = name.length();
if (name.endsWith("*"))
prefixLength -= 2;
while (true)
{
PropertyPermission forName =
(PropertyPermission) permissions.get(name);
if (forName != null)
{
actions &= ~forName.actions;
if (actions == 0)
return true;
}
prefixLength = name.lastIndexOf('.', prefixLength - 1);
if (prefixLength < 0)
return false;
name = name.substring(0, prefixLength + 1) + '*';
}
}
/**
* Enumerate over the collection.
*
* @return an enumeration of the collection contents
*/
public Enumeration elements()
{
return permissions.elements();
}
}
@@ -1,152 +0,0 @@
/* PropertyResourceBundle -- a resource bundle built from a Property file
Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.InputStream;
/**
* This class is a concrete <code>ResourceBundle</code> that gets it
* resources from a property file. This implies that the resources are
* strings. For more information about resource bundles see the class
* <code>ResourceBundle</code>.
*
* You should not use this class directly, or subclass it, but you get
* an object of this class automatically when you call
* <code>ResourceBundle.getBundle()</code> and there is a properties
* file.
*
* If there is also a class for this resource and the same locale, the
* class will be chosen. The properties file should have the name of the
* resource bundle, appended with the locale (e.g. <code>_de</code> and the
* extension <code>.properties</code>. The file should have the same format
* as for <code>Properties.load()</code>
*
* An example of a properties file for the german language is given
* here. This extends the example given in ListResourceBundle.
* Create a file MyResource_de.properties with the following contents
* and put it in the CLASSPATH. (The char <code>\u00e4</code> is the
* german umlaut)
*
*
<pre>
s1=3
s2=MeineDisk
s3=3. M\u00e4rz 96
s4=Die Diskette ''{1}'' enth\u00e4lt {0} in {2}.
s5=0
s6=keine Dateien
s7=1
s8=eine Datei
s9=2
s10={0,number} Dateien
s11=Die Formatierung warf eine Exception: {0}
s12=FEHLER
s13=Ergebnis
s14=Dialog
s15=Auswahlkriterium
s16=1,3
</pre>
*
* @author Jochen Hoenicke
* @see ResourceBundle
* @see ListResourceBundle
* @see Properties#load()
* @since 1.1
* @status updated to 1.4
*/
public class PropertyResourceBundle extends ResourceBundle
{
/** The properties file this bundle is based on. */
private Properties properties;
/**
* Creates a new property resource bundle.
*
* @param stream an input stream, where the resources are read from
* @throws NullPointerException if stream is null
* @throws IOException if reading the stream fails
*/
public PropertyResourceBundle(InputStream stream) throws IOException
{
properties = new Properties();
properties.load(stream);
}
/**
* Called by <code>getObject</code> when a resource is needed. This
* returns the resource given by the key.
*
* @param key the key of the resource
* @return the resource for the key, or null if it doesn't exist
*/
public Object handleGetObject(String key)
{
return properties.getProperty(key);
}
/**
* This method should return all keys for which a resource exists.
*
* @return an enumeration of the keys
*/
public Enumeration getKeys()
{
if (parent == null)
return properties.propertyNames();
// We make a new Set that holds all the keys, then return an enumeration
// for that. This prevents modifications from ruining the enumeration,
// as well as ignoring duplicates.
Set s = new HashSet();
Enumeration e = properties.propertyNames();
while (e.hasMoreElements())
s.add(e.nextElement());
ResourceBundle bundle = parent;
// Eliminate tail recursion.
do
{
e = bundle.getKeys();
while (e.hasMoreElements())
s.add(e.nextElement());
bundle = bundle.parent;
}
while (bundle != null);
return Collections.enumeration(s);
}
} // class PropertyResourceBundle
-429
View File
@@ -1,429 +0,0 @@
/* Random.java -- a pseudo-random number generator
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.Serializable;
/**
* This class generates pseudorandom numbers. It uses the same
* algorithm as the original JDK-class, so that your programs behave
* exactly the same way, if started with the same seed.
*
* The algorithm is described in <em>The Art of Computer Programming,
* Volume 2</em> by Donald Knuth in Section 3.2.1. It is a 48-bit seed,
* linear congruential formula.
*
* If two instances of this class are created with the same seed and
* the same calls to these classes are made, they behave exactly the
* same way. This should be even true for foreign implementations
* (like this), so every port must use the same algorithm as described
* here.
*
* If you want to implement your own pseudorandom algorithm, you
* should extend this class and overload the <code>next()</code> and
* <code>setSeed(long)</code> method. In that case the above
* paragraph doesn't apply to you.
*
* This class shouldn't be used for security sensitive purposes (like
* generating passwords or encryption keys. See <code>SecureRandom</code>
* in package <code>java.security</code> for this purpose.
*
* For simple random doubles between 0.0 and 1.0, you may consider using
* Math.random instead.
*
* @see java.security.SecureRandom
* @see Math#random()
* @author Jochen Hoenicke
* @author Eric Blake (ebb9@email.byu.edu)
* @status updated to 1.4
*/
public class Random implements Serializable
{
/**
* True if the next nextGaussian is available. This is used by
* nextGaussian, which generates two gaussian numbers by one call,
* and returns the second on the second call.
*
* @serial whether nextNextGaussian is available
* @see #nextGaussian()
* @see #nextNextGaussian
*/
private boolean haveNextNextGaussian;
/**
* The next nextGaussian, when available. This is used by nextGaussian,
* which generates two gaussian numbers by one call, and returns the
* second on the second call.
*
* @serial the second gaussian of a pair
* @see #nextGaussian()
* @see #haveNextNextGaussian
*/
private double nextNextGaussian;
/**
* The seed. This is the number set by setSeed and which is used
* in next.
*
* @serial the internal state of this generator
* @see #next()
*/
private long seed;
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = 3905348978240129619L;
/**
* Creates a new pseudorandom number generator. The seed is initialized
* to the current time, as if by
* <code>setSeed(System.currentTimeMillis());</code>.
*
* @see System#currentTimeMillis()
*/
public Random()
{
this(System.currentTimeMillis());
}
/**
* Creates a new pseudorandom number generator, starting with the
* specified seed, using <code>setSeed(seed);</code>.
*
* @param seed the initial seed
*/
public Random(long seed)
{
setSeed(seed);
}
/**
* Sets the seed for this pseudorandom number generator. As described
* above, two instances of the same random class, starting with the
* same seed, should produce the same results, if the same methods
* are called. The implementation for java.util.Random is:
*
<pre>public synchronized void setSeed(long seed)
{
this.seed = (seed ^ 0x5DEECE66DL) & ((1L &lt;&lt; 48) - 1);
haveNextNextGaussian = false;
}</pre>
*
* @param seed the new seed
*/
public synchronized void setSeed(long seed)
{
this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
haveNextNextGaussian = false;
}
/**
* Generates the next pseudorandom number. This returns
* an int value whose <code>bits</code> low order bits are
* independent chosen random bits (0 and 1 are equally likely).
* The implementation for java.util.Random is:
*
<pre>protected synchronized int next(int bits)
{
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L &lt;&lt; 48) - 1);
return (int) (seed &gt;&gt;&gt; (48 - bits));
}</pre>
*
* @param bits the number of random bits to generate, in the range 1..32
* @return the next pseudorandom value
* @since 1.1
*/
protected synchronized int next(int bits)
{
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int) (seed >>> (48 - bits));
}
/**
* Fills an array of bytes with random numbers. All possible values
* are (approximately) equally likely.
* The JDK documentation gives no implementation, but it seems to be:
*
<pre>public void nextBytes(byte[] bytes)
{
for (int i = 0; i &lt; bytes.length; i += 4)
{
int random = next(32);
for (int j = 0; i + j &lt; bytes.length && j &lt; 4; j++)
{
bytes[i+j] = (byte) (random & 0xff)
random &gt;&gt;= 8;
}
}
}</pre>
*
* @param bytes the byte array that should be filled
* @throws NullPointerException if bytes is null
* @since 1.1
*/
public void nextBytes(byte[] bytes)
{
int random;
// Do a little bit unrolling of the above algorithm.
int max = bytes.length & ~0x3;
for (int i = 0; i < max; i += 4)
{
random = next(32);
bytes[i] = (byte) random;
bytes[i + 1] = (byte) (random >> 8);
bytes[i + 2] = (byte) (random >> 16);
bytes[i + 3] = (byte) (random >> 24);
}
if (max < bytes.length)
{
random = next(32);
for (int j = max; j < bytes.length; j++)
{
bytes[j] = (byte) random;
random >>= 8;
}
}
}
/**
* Generates the next pseudorandom number. This returns
* an int value whose 32 bits are independent chosen random bits
* (0 and 1 are equally likely). The implementation for
* java.util.Random is:
*
<pre>public int nextInt()
{
return next(32);
}</pre>
*
* @return the next pseudorandom value
*/
public int nextInt()
{
return next(32);
}
/**
* Generates the next pseudorandom number. This returns
* a value between 0(inclusive) and <code>n</code>(exclusive), and
* each value has the same likelihodd (1/<code>n</code>).
* (0 and 1 are equally likely). The implementation for
* java.util.Random is:
*
<pre>
public int nextInt(int n)
{
if (n &lt;= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long) next(31)) &gt;&gt; 31);
int bits, val;
do
{
bits = next(31);
val = bits % n;
}
while(bits - val + (n-1) &lt; 0);
return val;
}</pre>
*
* <p>This algorithm would return every value with exactly the same
* probability, if the next()-method would be a perfect random number
* generator.
*
* The loop at the bottom only accepts a value, if the random
* number was between 0 and the highest number less then 1<<31,
* which is divisible by n. The probability for this is high for small
* n, and the worst case is 1/2 (for n=(1<<30)+1).
*
* The special treatment for n = power of 2, selects the high bits of
* the random number (the loop at the bottom would select the low order
* bits). This is done, because the low order bits of linear congruential
* number generators (like the one used in this class) are known to be
* ``less random'' than the high order bits.
*
* @param n the upper bound
* @throws IllegalArgumentException if the given upper bound is negative
* @return the next pseudorandom value
* @since 1.2
*/
public int nextInt(int n)
{
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int) ((n * (long) next(31)) >> 31);
int bits, val;
do
{
bits = next(31);
val = bits % n;
}
while (bits - val + (n - 1) < 0);
return val;
}
/**
* Generates the next pseudorandom long number. All bits of this
* long are independently chosen and 0 and 1 have equal likelihood.
* The implementation for java.util.Random is:
*
<pre>public long nextLong()
{
return ((long) next(32) &lt;&lt; 32) + next(32);
}</pre>
*
* @return the next pseudorandom value
*/
public long nextLong()
{
return ((long) next(32) << 32) + next(32);
}
/**
* Generates the next pseudorandom boolean. True and false have
* the same probability. The implementation is:
*
<pre>public boolean nextBoolean()
{
return next(1) != 0;
}</pre>
*
* @return the next pseudorandom boolean
* @since 1.2
*/
public boolean nextBoolean()
{
return next(1) != 0;
}
/**
* Generates the next pseudorandom float uniformly distributed
* between 0.0f (inclusive) and 1.0f (exclusive). The
* implementation is as follows.
*
<pre>public float nextFloat()
{
return next(24) / ((float)(1 &lt;&lt; 24));
}</pre>
*
* @return the next pseudorandom float
*/
public float nextFloat()
{
return next(24) / (float) (1 << 24);
}
/**
* Generates the next pseudorandom double uniformly distributed
* between 0.0 (inclusive) and 1.0 (exclusive). The
* implementation is as follows.
*
<pre>public double nextDouble()
{
return (((long) next(26) &lt;&lt; 27) + next(27)) / (double)(1L &lt;&lt; 53);
}</pre>
*
* @return the next pseudorandom double
*/
public double nextDouble()
{
return (((long) next(26) << 27) + next(27)) / (double) (1L << 53);
}
/**
* Generates the next pseudorandom, Gaussian (normally) distributed
* double value, with mean 0.0 and standard deviation 1.0.
* The algorithm is as follows.
*
<pre>public synchronized double nextGaussian()
{
if (haveNextNextGaussian)
{
haveNextNextGaussian = false;
return nextNextGaussian;
}
else
{
double v1, v2, s;
do
{
v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
s = v1 * v1 + v2 * v2;
}
while (s >= 1);
double norm = Math.sqrt(-2 * Math.log(s) / s);
nextNextGaussian = v2 * norm;
haveNextNextGaussian = true;
return v1 * norm;
}
}</pre>
*
* <p>This is described in section 3.4.1 of <em>The Art of Computer
* Programming, Volume 2</em> by Donald Knuth.
*
* @return the next pseudorandom Gaussian distributed double
*/
public synchronized double nextGaussian()
{
if (haveNextNextGaussian)
{
haveNextNextGaussian = false;
return nextNextGaussian;
}
double v1, v2, s;
do
{
v1 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
v2 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
s = v1 * v1 + v2 * v2;
}
while (s >= 1);
double norm = Math.sqrt(-2 * Math.log(s) / s);
nextNextGaussian = v2 * norm;
haveNextNextGaussian = true;
return v1 * norm;
}
}
-64
View File
@@ -1,64 +0,0 @@
/* RandomAccess.java -- A tagging interface that lists can use to tailor
operations to the correct algorithm
Copyright (C) 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* Marker interface used to inform <code>List</code> implementations that
* they support fast (usually constant time) random access. This allows
* generic list algorithms to tailor their behavior based on the list
* type.
* <p>
*
* For example, some sorts are n*log(n) on an array, but decay to quadratic
* time on a linked list. As a rule of thumb, this interface should be
* used is this loop:<br>
* <code>for (int i = 0, n = list.size(); i &lt; n; i++) list.get(i);</code>
* <br>runs faster than this loop:<br>
* <code>for (Iterator i = list.iterator(); i.hasNext(); ) i.next();</code>
*
* @author Eric Blake (ebb9@email.byu.edu)
* @see List
* @since 1.4
* @status updated to 1.4
*/
public interface RandomAccess
{
// Tagging interface only.
}
-264
View File
@@ -1,264 +0,0 @@
/* Set.java -- A collection that prohibits duplicates
Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* A collection that contains no duplicates. In other words, for two set
* elements e1 and e2, <code>e1.equals(e2)</code> returns false. There
* are additional stipulations on <code>add</code>, <code>equals</code>
* and <code>hashCode</code>, as well as the requirements that constructors
* do not permit duplicate elements. The Set interface is incompatible with
* List; you cannot implement both simultaneously.
* <p>
*
* Note: Be careful about using mutable objects in sets. In particular,
* if a mutable object changes to become equal to another set element, you
* have violated the contract. As a special case of this, a Set is not
* allowed to be an element of itself, without risking undefined behavior.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see List
* @see SortedSet
* @see HashSet
* @see TreeSet
* @see LinkedHashSet
* @see AbstractSet
* @see Collections#singleton(Object)
* @see Collections#EMPTY_SET
* @since 1.2
* @status updated to 1.4
*/
public interface Set extends Collection
{
/**
* Adds the specified element to the set if it is not already present
* (optional operation). In particular, the comparison algorithm is
* <code>o == null ? e == null : o.equals(e)</code>. Sets need not permit
* all values, and may document what exceptions will be thrown if
* a value is not permitted.
*
* @param o the object to add
* @return true if the object was not previously in the set
* @throws UnsupportedOperationException if this operation is not allowed
* @throws ClassCastException if the class of o prevents it from being added
* @throws IllegalArgumentException if some aspect of o prevents it from
* being added
* @throws NullPointerException if null is not permitted in this set
*/
boolean add(Object o);
/**
* Adds all of the elements of the given collection to this set (optional
* operation). If the argument is also a Set, this returns the mathematical
* <i>union</i> of the two. The behavior is unspecified if the set is
* modified while this is taking place.
*
* @param c the collection to add
* @return true if the set changed as a result
* @throws UnsupportedOperationException if this operation is not allowed
* @throws ClassCastException if the class of an element prevents it from
* being added
* @throws IllegalArgumentException if something about an element prevents
* it from being added
* @throws NullPointerException if null is not permitted in this set, or
* if the argument c is null
* @see #add(Object)
*/
boolean addAll(Collection c);
/**
* Removes all elements from this set (optional operation). This set will
* be empty afterwords, unless an exception occurs.
*
* @throws UnsupportedOperationException if this operation is not allowed
*/
void clear();
/**
* Returns true if the set contains the specified element. In other words,
* this looks for <code>o == null ? e == null : o.equals(e)</code>.
*
* @param o the object to look for
* @return true if it is found in the set
* @throws ClassCastException if the type of o is not a valid type
* for this set.
* @throws NullPointerException if o is null and this set doesn't
* support null values.
*/
boolean contains(Object o);
/**
* Returns true if this set contains all elements in the specified
* collection. If the argument is also a set, this is the <i>subset</i>
* relationship.
*
* @param c the collection to check membership in
* @return true if all elements in this set are in c
* @throws NullPointerException if c is null
* @throws ClassCastException if the type of any element in c is not
* a valid type for this set.
* @throws NullPointerException if some element of c is null and this
* set doesn't support null values.
* @see #contains(Object)
*/
boolean containsAll(Collection c);
/**
* Compares the specified object to this for equality. For sets, the object
* must be a set, the two must have the same size, and every element in
* one must be in the other.
*
* @param o the object to compare to
* @return true if it is an equal set
*/
boolean equals(Object o);
/**
* Returns the hash code for this set. In order to satisfy the contract of
* equals, this is the sum of the hashcode of all elements in the set.
*
* @return the sum of the hashcodes of all set elements
* @see #equals(Object)
*/
int hashCode();
/**
* Returns true if the set contains no elements.
*
* @return true if the set is empty
*/
boolean isEmpty();
/**
* Returns an iterator over the set. The iterator has no specific order,
* unless further specified.
*
* @return a set iterator
*/
Iterator iterator();
/**
* Removes the specified element from this set (optional operation). If
* an element e exists, <code>o == null ? e == null : o.equals(e)</code>,
* it is removed from the set.
*
* @param o the object to remove
* @return true if the set changed (an object was removed)
* @throws UnsupportedOperationException if this operation is not allowed
* @throws ClassCastException if the type of o is not a valid type
* for this set.
* @throws NullPointerException if o is null and this set doesn't allow
* the removal of a null value.
*/
boolean remove(Object o);
/**
* Removes from this set all elements contained in the specified collection
* (optional operation). If the argument is a set, this returns the
* <i>asymmetric set difference</i> of the two sets.
*
* @param c the collection to remove from this set
* @return true if this set changed as a result
* @throws UnsupportedOperationException if this operation is not allowed
* @throws NullPointerException if c is null
* @throws ClassCastException if the type of any element in c is not
* a valid type for this set.
* @throws NullPointerException if some element of c is null and this
* set doesn't support removing null values.
* @see #remove(Object)
*/
boolean removeAll(Collection c);
/**
* Retains only the elements in this set that are also in the specified
* collection (optional operation). If the argument is also a set, this
* performs the <i>intersection</i> of the two sets.
*
* @param c the collection to keep
* @return true if this set was modified
* @throws UnsupportedOperationException if this operation is not allowed
* @throws NullPointerException if c is null
* @throws ClassCastException if the type of any element in c is not
* a valid type for this set.
* @throws NullPointerException if some element of c is null and this
* set doesn't support retaining null values.
* @see #remove(Object)
*/
boolean retainAll(Collection c);
/**
* Returns the number of elements in the set. If there are more
* than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
* the <i>cardinality</i> of the set.
*
* @return the number of elements
*/
int size();
/**
* Returns an array containing the elements of this set. If the set
* makes a guarantee about iteration order, the array has the same
* order. The array is distinct from the set; modifying one does not
* affect the other.
*
* @return an array of this set's elements
* @see #toArray(Object[])
*/
Object[] toArray();
/**
* Returns an array containing the elements of this set, of the same runtime
* type of the argument. If the given set is large enough, it is reused,
* and null is inserted in the first unused slot. Otherwise, reflection
* is used to build a new array. If the set makes a guarantee about iteration
* order, the array has the same order. The array is distinct from the set;
* modifying one does not affect the other.
*
* @param a the array to determine the return type; if it is big enough
* it is used and returned
* @return an array holding the elements of the set
* @throws ArrayStoreException if the runtime type of a is not a supertype
* of all elements in the set
* @throws NullPointerException if a is null
* @see #toArray()
*/
Object[] toArray(Object[] a);
}
-173
View File
@@ -1,173 +0,0 @@
/* SortedMap.java -- A map that makes guarantees about the order of its keys
Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* A map which guarantees its key's iteration order. The entries in the
* map are related by the <i>natural ordering</i> of the keys if they
* are Comparable, or by the provided Comparator. Additional operations
* take advantage of the sorted nature of the map.
* <p>
*
* All keys entered in the map must be mutually comparable; in other words,
* <code>k1.compareTo(k2)</code> or <code>comparator.compare(k1, k2)</code>
* must not throw a ClassCastException. The ordering must be <i>consistent
* with equals</i> (see {@link Comparator} for this definition), if the
* map is to obey the general contract of the Map interface. If not,
* the results are well-defined, but probably not what you wanted.
* <p>
*
* It is recommended that all implementing classes provide four constructors:
* 1) one that takes no arguments and builds an empty map sorted by natural
* order of the keys; 2) one that takes a Comparator for the sorting order;
* 3) one that takes a Map and sorts according to the natural order of its
* keys; and 4) one that takes a SortedMap and sorts by the same comparator.
* Unfortunately, the Java language does not provide a way to enforce this.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Map
* @see TreeMap
* @see SortedSet
* @see Comparable
* @see Comparator
* @see Collection
* @see ClassCastException
* @since 1.2
* @status updated to 1.4
*/
public interface SortedMap extends Map
{
/**
* Returns the comparator used in sorting this map, or null if it is
* the keys' natural ordering.
*
* @return the sorting comparator
*/
Comparator comparator();
/**
* Returns the first (lowest sorted) key in the map.
*
* @return the first key
* @throws NoSuchElementException if this map is empty.
*/
Object firstKey();
/**
* Returns a view of the portion of the map strictly less than toKey. The
* view is backed by this map, so changes in one show up in the other.
* The submap supports all optional operations of the original.
* <p>
*
* The returned map throws an IllegalArgumentException any time a key is
* used which is out of the range of toKey. Note that the endpoint, toKey,
* is not included; if you want this value to be included, pass its successor
* object in to toKey. For example, for Integers, you could request
* <code>headMap(new Integer(limit.intValue() + 1))</code>.
*
* @param toKey the exclusive upper range of the submap
* @return the submap
* @throws ClassCastException if toKey is not comparable to the map contents
* @throws IllegalArgumentException if this is a subMap, and toKey is out
* of range
* @throws NullPointerException if toKey is null but the map does not allow
* null keys
*/
SortedMap headMap(Object toKey);
/**
* Returns the last (highest sorted) key in the map.
*
* @return the last key
* @throws NoSuchElementException if this map is empty.
*/
Object lastKey();
/**
* Returns a view of the portion of the map greater than or equal to
* fromKey, and strictly less than toKey. The view is backed by this map,
* so changes in one show up in the other. The submap supports all
* optional operations of the original.
* <p>
*
* The returned map throws an IllegalArgumentException any time a key is
* used which is out of the range of fromKey and toKey. Note that the
* lower endpoint is included, but the upper is not; if you want to
* change the inclusion or exclusion of an endpoint, pass its successor
* object in instead. For example, for Integers, you could request
* <code>subMap(new Integer(lowlimit.intValue() + 1),
* new Integer(highlimit.intValue() + 1))</code> to reverse
* the inclusiveness of both endpoints.
*
* @param fromKey the inclusive lower range of the submap
* @param toKey the exclusive upper range of the submap
* @return the submap
* @throws ClassCastException if fromKey or toKey is not comparable to
* the map contents
* @throws IllegalArgumentException if this is a subMap, and fromKey or
* toKey is out of range
* @throws NullPointerException if fromKey or toKey is null but the map
* does not allow null keys
*/
SortedMap subMap(Object fromKey, Object toKey);
/**
* Returns a view of the portion of the map greater than or equal to
* fromKey. The view is backed by this map, so changes in one show up
* in the other. The submap supports all optional operations of the original.
* <p>
*
* The returned map throws an IllegalArgumentException any time a key is
* used which is out of the range of fromKey. Note that the endpoint, fromKey, is
* included; if you do not want this value to be included, pass its successor object in
* to fromKey. For example, for Integers, you could request
* <code>tailMap(new Integer(limit.intValue() + 1))</code>.
*
* @param fromKey the inclusive lower range of the submap
* @return the submap
* @throws ClassCastException if fromKey is not comparable to the map
* contents
* @throws IllegalArgumentException if this is a subMap, and fromKey is out
* of range
* @throws NullPointerException if fromKey is null but the map does not allow
* null keys
*/
SortedMap tailMap(Object fromKey);
}
-176
View File
@@ -1,176 +0,0 @@
/* SortedSet.java -- A set that makes guarantees about the order of its
elements
Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* A set which guarantees its iteration order. The elements in the set
* are related by the <i>natural ordering</i> if they are Comparable, or
* by the provided Comparator. Additional operations take advantage of
* the sorted nature of the set.
* <p>
*
* All elements entered in the set must be mutually comparable; in other words,
* <code>k1.compareTo(k2)</code> or <code>comparator.compare(k1, k2)</code>
* must not throw a ClassCastException. The ordering must be <i>consistent
* with equals</i> (see {@link Comparator} for this definition), if the
* set is to obey the general contract of the Set interface. If not,
* the results are well-defined, but probably not what you wanted.
* <p>
*
* It is recommended that all implementing classes provide four constructors:
* 1) one that takes no arguments and builds an empty set sorted by natural
* order of the elements; 2) one that takes a Comparator for the sorting order;
* 3) one that takes a Set and sorts according to the natural order of its
* elements; and 4) one that takes a SortedSet and sorts by the same
* comparator. Unfortunately, the Java language does not provide a way to
* enforce this.
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
* @see Set
* @see TreeSet
* @see SortedMap
* @see Collection
* @see Comparable
* @see Comparator
* @see ClassCastException
* @since 1.2
* @status updated to 1.4
*/
public interface SortedSet extends Set
{
/**
* Returns the comparator used in sorting this set, or null if it is
* the elements' natural ordering.
*
* @return the sorting comparator
*/
Comparator comparator();
/**
* Returns the first (lowest sorted) element in the set.
*
* @return the first element
* @throws NoSuchElementException if the set is empty.
*/
Object first();
/**
* Returns a view of the portion of the set strictly less than toElement. The
* view is backed by this set, so changes in one show up in the other.
* The subset supports all optional operations of the original.
* <p>
*
* The returned set throws an IllegalArgumentException any time an element is
* used which is out of the range of toElement. Note that the endpoint, toElement,
* is not included; if you want this value included, pass its successor object in to
* toElement. For example, for Integers, you could request
* <code>headSet(new Integer(limit.intValue() + 1))</code>.
*
* @param toElement the exclusive upper range of the subset
* @return the subset
* @throws ClassCastException if toElement is not comparable to the set
* contents
* @throws IllegalArgumentException if this is a subSet, and toElement is out
* of range
* @throws NullPointerException if toElement is null but the set does not
* allow null elements
*/
SortedSet headSet(Object toElement);
/**
* Returns the last (highest sorted) element in the set.
*
* @return the last element
* @throws NoSuchElementException if the set is empty.
*/
Object last();
/**
* Returns a view of the portion of the set greater than or equal to
* fromElement, and strictly less than toElement. The view is backed by
* this set, so changes in one show up in the other. The subset supports all
* optional operations of the original.
* <p>
*
* The returned set throws an IllegalArgumentException any time an element is
* used which is out of the range of fromElement and toElement. Note that the
* lower endpoint is included, but the upper is not; if you want to
* change the inclusion or exclusion of an endpoint, pass its successor
* object in instead. For example, for Integers, you can request
* <code>subSet(new Integer(lowlimit.intValue() + 1),
* new Integer(highlimit.intValue() + 1))</code> to reverse
* the inclusiveness of both endpoints.
*
* @param fromElement the inclusive lower range of the subset
* @param toElement the exclusive upper range of the subset
* @return the subset
* @throws ClassCastException if fromElement or toElement is not comparable
* to the set contents
* @throws IllegalArgumentException if this is a subSet, and fromElement or
* toElement is out of range
* @throws NullPointerException if fromElement or toElement is null but the
* set does not allow null elements
*/
SortedSet subSet(Object fromElement, Object toElement);
/**
* Returns a view of the portion of the set greater than or equal to
* fromElement. The view is backed by this set, so changes in one show up
* in the other. The subset supports all optional operations of the original.
* <p>
*
* The returned set throws an IllegalArgumentException any time an element is
* used which is out of the range of fromElement. Note that the endpoint,
* fromElement, is included; if you do not want this value to be included, pass its
* successor object in to fromElement. For example, for Integers, you could request
* <code>tailSet(new Integer(limit.intValue() + 1))</code>.
*
* @param fromElement the inclusive lower range of the subset
* @return the subset
* @throws ClassCastException if fromElement is not comparable to the set
* contents
* @throws IllegalArgumentException if this is a subSet, and fromElement is
* out of range
* @throws NullPointerException if fromElement is null but the set does not
* allow null elements
*/
SortedSet tailSet(Object fromElement);
}
-158
View File
@@ -1,158 +0,0 @@
/* Stack.java - Class that provides a Last In First Out (LIFO)
datatype, known more commonly as a Stack
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct
/**
* Stack provides a Last In First Out (LIFO) data type, commonly known
* as a Stack. Stack itself extends Vector and provides the additional
* methods for stack manipulation (push, pop, peek). You can also seek for
* the 1-based position of an element on the stack.
*
* @author Warren Levy (warrenl@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
* @see List
* @see AbstractList
* @see LinkedList
* @since 1.0
* @status updated to 1.4
*/
public class Stack extends Vector
{
// We could use Vector methods internally for the following methods,
// but have used Vector fields directly for efficiency (i.e. this
// often reduces out duplicate bounds checking).
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = 1224463164541339165L;
/**
* This constructor creates a new Stack, initially empty
*/
public Stack()
{
}
/**
* Pushes an Object onto the top of the stack. This method is effectively
* the same as addElement(item).
*
* @param item the Object to push onto the stack
* @return the Object pushed onto the stack
* @see Vector#addElement(Object)
*/
public Object push(Object item)
{
// When growing the Stack, use the Vector routines in case more
// memory is needed.
// Note: spec indicates that this method *always* returns obj passed in!
addElement(item);
return item;
}
/**
* Pops an item from the stack and returns it. The item popped is
* removed from the Stack.
*
* @return the Object popped from the stack
* @throws EmptyStackException if the stack is empty
*/
public synchronized Object pop()
{
if (elementCount == 0)
throw new EmptyStackException();
modCount++;
Object obj = elementData[--elementCount];
// Set topmost element to null to assist the gc in cleanup.
elementData[elementCount] = null;
return obj;
}
/**
* Returns the top Object on the stack without removing it.
*
* @return the top Object on the stack
* @throws EmptyStackException if the stack is empty
*/
public synchronized Object peek()
{
if (elementCount == 0)
throw new EmptyStackException();
return elementData[elementCount - 1];
}
/**
* Tests if the stack is empty.
*
* @return true if the stack contains no items, false otherwise
*/
public synchronized boolean empty()
{
return elementCount == 0;
}
/**
* Returns the position of an Object on the stack, with the top
* most Object being at position 1, and each Object deeper in the
* stack at depth + 1.
*
* @param o The object to search for
* @return The 1 based depth of the Object, or -1 if the Object
* is not on the stack
*/
public synchronized int search(Object o)
{
int i = elementCount;
while (--i >= 0)
if (equals(o, elementData[i]))
return elementCount - i;
return -1;
}
}
-268
View File
@@ -1,268 +0,0 @@
/* StringTokenizer -- breaks a String into tokens
Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* This class splits a string into tokens. The caller can set on which
* delimiters the string should be split and if the delimiters should be
* returned. This is much simpler than {@link java.io.StreamTokenizer}.
*
* <p>You may change the delimiter set on the fly by calling
* nextToken(String). But the semantic is quite difficult; it even
* depends on calling <code>hasMoreTokens()</code>. You should call
* <code>hasMoreTokens()</code> before, otherwise the old delimiters
* after the last token are candidates for being returned.
*
* <p>If you want to get the delimiters, you have to use the three argument
* constructor. The delimiters are returned as token consisting of a
* single character.
*
* @author Jochen Hoenicke
* @author Warren Levy (warrenl@cygnus.com)
* @see java.io.StreamTokenizer
* @status updated to 1.4
*/
public class StringTokenizer implements Enumeration
{
// WARNING: StringTokenizer is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
/**
* The position in the str, where we currently are.
*/
private int pos;
/**
* The string that should be split into tokens.
*/
private final String str;
/**
* The length of the string.
*/
private final int len;
/**
* The string containing the delimiter characters.
*/
private String delim;
/**
* Tells, if we should return the delimiters.
*/
private final boolean retDelims;
/**
* Creates a new StringTokenizer for the string <code>str</code>,
* that should split on the default delimiter set (space, tab,
* newline, return and formfeed), and which doesn't return the
* delimiters.
*
* @param str The string to split
* @throws NullPointerException if str is null
*/
public StringTokenizer(String str)
{
this(str, " \t\n\r\f", false);
}
/**
* Create a new StringTokenizer, that splits the given string on
* the given delimiter characters. It doesn't return the delimiter
* characters.
*
* @param str the string to split
* @param delim a string containing all delimiter characters
* @throws NullPointerException if either argument is null
*/
public StringTokenizer(String str, String delim)
{
this(str, delim, false);
}
/**
* Create a new StringTokenizer, that splits the given string on
* the given delimiter characters. If you set
* <code>returnDelims</code> to <code>true</code>, the delimiter
* characters are returned as tokens of their own. The delimiter
* tokens always consist of a single character.
*
* @param str the string to split
* @param delim a string containing all delimiter characters
* @param returnDelims tells, if you want to get the delimiters
* @throws NullPointerException if str or delim is null
*/
public StringTokenizer(String str, String delim, boolean returnDelims)
{
len = str.length();
this.str = str;
// The toString() hack causes the NullPointerException.
this.delim = delim.toString();
this.retDelims = returnDelims;
this.pos = 0;
}
/**
* Tells if there are more tokens.
*
* @return true if the next call of nextToken() will succeed
*/
public boolean hasMoreTokens()
{
if (! retDelims)
{
while (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
pos++;
}
return pos < len;
}
/**
* Returns the nextToken, changing the delimiter set to the given
* <code>delim</code>. The change of the delimiter set is
* permanent, ie. the next call of nextToken(), uses the same
* delimiter set.
*
* @param delim a string containing the new delimiter characters
* @return the next token with respect to the new delimiter characters
* @throws NoSuchElementException if there are no more tokens
* @throws NullPointerException if delim is null
*/
public String nextToken(String delim) throws NoSuchElementException
{
this.delim = delim;
return nextToken();
}
/**
* Returns the nextToken of the string.
*
* @return the next token with respect to the current delimiter characters
* @throws NoSuchElementException if there are no more tokens
*/
public String nextToken() throws NoSuchElementException
{
if (pos < len && delim.indexOf(str.charAt(pos)) >= 0)
{
if (retDelims)
return str.substring(pos, ++pos);
while (++pos < len && delim.indexOf(str.charAt(pos)) >= 0);
}
if (pos < len)
{
int start = pos;
while (++pos < len && delim.indexOf(str.charAt(pos)) < 0);
return str.substring(start, pos);
}
throw new NoSuchElementException();
}
/**
* This does the same as hasMoreTokens. This is the
* <code>Enumeration</code> interface method.
*
* @return true, if the next call of nextElement() will succeed
* @see #hasMoreTokens()
*/
public boolean hasMoreElements()
{
return hasMoreTokens();
}
/**
* This does the same as nextTokens. This is the
* <code>Enumeration</code> interface method.
*
* @return the next token with respect to the current delimiter characters
* @throws NoSuchElementException if there are no more tokens
* @see #nextToken()
*/
public Object nextElement() throws NoSuchElementException
{
return nextToken();
}
/**
* This counts the number of remaining tokens in the string, with
* respect to the current delimiter set.
*
* @return the number of times <code>nextTokens()</code> will succeed
* @see #nextToken()
*/
public int countTokens()
{
int count = 0;
int delimiterCount = 0;
boolean tokenFound = false; // Set when a non-delimiter is found
int tmpPos = pos;
// Note for efficiency, we count up the delimiters rather than check
// retDelims every time we encounter one. That way, we can
// just do the conditional once at the end of the method
while (tmpPos < len)
{
if (delim.indexOf(str.charAt(tmpPos++)) >= 0)
{
if (tokenFound)
{
// Got to the end of a token
count++;
tokenFound = false;
}
delimiterCount++; // Increment for this delimiter
}
else
{
tokenFound = true;
// Get to the end of the token
while (tmpPos < len
&& delim.indexOf(str.charAt(tmpPos)) < 0)
++tmpPos;
}
}
// Make sure to count the last token
if (tokenFound)
count++;
// if counting delmiters add them into the token count
return retDelims ? count + delimiterCount : count;
}
} // class StringTokenizer
File diff suppressed because it is too large Load Diff
-615
View File
@@ -1,615 +0,0 @@
/* Timer.java -- Timer that runs TimerTasks at a later time.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* Timer that can run TimerTasks at a later time.
* TimerTasks can be scheduled for one time execution at some time in the
* future. They can be scheduled to be rescheduled at a time period after the
* task was last executed. Or they can be scheduled to be executed repeatedly
* at a fixed rate.
* <p>
* The normal scheduling will result in a more or less even delay in time
* between successive executions, but the executions could drift in time if
* the task (or other tasks) takes a long time to execute. Fixed delay
* scheduling guarantees more or less that the task will be executed at a
* specific time, but if there is ever a delay in execution then the period
* between successive executions will be shorter. The first method of
* repeated scheduling is preferred for repeated tasks in response to user
* interaction, the second method of repeated scheduling is preferred for tasks
* that act like alarms.
* <p>
* The Timer keeps a binary heap as a task priority queue which means that
* scheduling and serving of a task in a queue of n tasks costs O(log n).
*
* @see TimerTask
* @since 1.3
* @author Mark Wielaard (mark@klomp.org)
*/
public class Timer
{
/**
* Priority Task Queue.
* TimerTasks are kept in a binary heap.
* The scheduler calls sleep() on the queue when it has nothing to do or
* has to wait. A sleeping scheduler can be notified by calling interrupt()
* which is automatically called by the enqueue(), cancel() and
* timerFinalized() methods.
*/
private static final class TaskQueue
{
/** Default size of this queue */
private static final int DEFAULT_SIZE = 32;
/** Whether to return null when there is nothing in the queue */
private boolean nullOnEmpty;
/**
* The heap containing all the scheduled TimerTasks
* sorted by the TimerTask.scheduled field.
* Null when the stop() method has been called.
*/
private TimerTask heap[];
/**
* The actual number of elements in the heap
* Can be less then heap.length.
* Note that heap[0] is used as a sentinel.
*/
private int elements;
/**
* Creates a TaskQueue of default size without any elements in it.
*/
public TaskQueue()
{
heap = new TimerTask[DEFAULT_SIZE];
elements = 0;
nullOnEmpty = false;
}
/**
* Adds a TimerTask at the end of the heap.
* Grows the heap if necessary by doubling the heap in size.
*/
private void add(TimerTask task)
{
elements++;
if (elements == heap.length)
{
TimerTask new_heap[] = new TimerTask[heap.length * 2];
System.arraycopy(heap, 0, new_heap, 0, heap.length);
heap = new_heap;
}
heap[elements] = task;
}
/**
* Removes the last element from the heap.
* Shrinks the heap in half if
* elements+DEFAULT_SIZE/2 <= heap.length/4.
*/
private void remove()
{
// clear the entry first
heap[elements] = null;
elements--;
if (elements + DEFAULT_SIZE / 2 <= (heap.length / 4))
{
TimerTask new_heap[] = new TimerTask[heap.length / 2];
System.arraycopy(heap, 0, new_heap, 0, elements + 1);
heap = new_heap;
}
}
/**
* Adds a task to the queue and puts it at the correct place
* in the heap.
*/
public synchronized void enqueue(TimerTask task)
{
// Check if it is legal to add another element
if (heap == null)
{
throw new IllegalStateException
("cannot enqueue when stop() has been called on queue");
}
heap[0] = task; // sentinel
add(task); // put the new task at the end
// Now push the task up in the heap until it has reached its place
int child = elements;
int parent = child / 2;
while (heap[parent].scheduled > task.scheduled)
{
heap[child] = heap[parent];
child = parent;
parent = child / 2;
}
// This is the correct place for the new task
heap[child] = task;
heap[0] = null; // clear sentinel
// Maybe sched() is waiting for a new element
this.notify();
}
/**
* Returns the top element of the queue.
* Can return null when no task is in the queue.
*/
private TimerTask top()
{
if (elements == 0)
{
return null;
}
else
{
return heap[1];
}
}
/**
* Returns the top task in the Queue.
* Removes the element from the heap and reorders the heap first.
* Can return null when there is nothing in the queue.
*/
public synchronized TimerTask serve()
{
// The task to return
TimerTask task = null;
while (task == null)
{
// Get the next task
task = top();
// return null when asked to stop
// or if asked to return null when the queue is empty
if ((heap == null) || (task == null && nullOnEmpty))
{
return null;
}
// Do we have a task?
if (task != null)
{
// The time to wait until the task should be served
long time = task.scheduled - System.currentTimeMillis();
if (time > 0)
{
// This task should not yet be served
// So wait until this task is ready
// or something else happens to the queue
task = null; // set to null to make sure we call top()
try
{
this.wait(time);
}
catch (InterruptedException _)
{
}
}
}
else
{
// wait until a task is added
// or something else happens to the queue
try
{
this.wait();
}
catch (InterruptedException _)
{
}
}
}
// reconstruct the heap
TimerTask lastTask = heap[elements];
remove();
// drop lastTask at the beginning and move it down the heap
int parent = 1;
int child = 2;
heap[1] = lastTask;
while (child <= elements)
{
if (child < elements)
{
if (heap[child].scheduled > heap[child + 1].scheduled)
{
child++;
}
}
if (lastTask.scheduled <= heap[child].scheduled)
break; // found the correct place (the parent) - done
heap[parent] = heap[child];
parent = child;
child = parent * 2;
}
// this is the correct new place for the lastTask
heap[parent] = lastTask;
// return the task
return task;
}
/**
* When nullOnEmpty is true the serve() method will return null when
* there are no tasks in the queue, otherwise it will wait until
* a new element is added to the queue. It is used to indicate to
* the scheduler that no new tasks will ever be added to the queue.
*/
public synchronized void setNullOnEmpty(boolean nullOnEmpty)
{
this.nullOnEmpty = nullOnEmpty;
this.notify();
}
/**
* When this method is called the current and all future calls to
* serve() will return null. It is used to indicate to the Scheduler
* that it should stop executing since no more tasks will come.
*/
public synchronized void stop()
{
this.heap = null;
this.elements = 0;
this.notify();
}
} // TaskQueue
/**
* The scheduler that executes all the tasks on a particular TaskQueue,
* reschedules any repeating tasks and that waits when no task has to be
* executed immediatly. Stops running when canceled or when the parent
* Timer has been finalized and no more tasks have to be executed.
*/
private static final class Scheduler implements Runnable
{
// The priority queue containing all the TimerTasks.
private TaskQueue queue;
/**
* Creates a new Scheduler that will schedule the tasks on the
* given TaskQueue.
*/
public Scheduler(TaskQueue queue)
{
this.queue = queue;
}
public void run()
{
TimerTask task;
while ((task = queue.serve()) != null)
{
// If this task has not been canceled
if (task.scheduled >= 0)
{
// Mark execution time
task.lastExecutionTime = task.scheduled;
// Repeatable task?
if (task.period < 0)
{
// Last time this task is executed
task.scheduled = -1;
}
// Run the task
try
{
task.run();
}
catch (ThreadDeath death)
{
// If an exception escapes, the Timer becomes invalid.
queue.stop();
throw death;
}
catch (Throwable t)
{
// If an exception escapes, the Timer becomes invalid.
queue.stop();
}
}
// Calculate next time and possibly re-enqueue.
if (task.scheduled >= 0)
{
if (task.fixed)
{
task.scheduled += task.period;
}
else
{
task.scheduled = task.period + System.currentTimeMillis();
}
try
{
queue.enqueue(task);
}
catch (IllegalStateException ise)
{
// Ignore. Apparently the Timer queue has been stopped.
}
}
}
}
} // Scheduler
// Number of Timers created.
// Used for creating nice Thread names.
private static int nr;
// The queue that all the tasks are put in.
// Given to the scheduler
private TaskQueue queue;
// The Scheduler that does all the real work
private Scheduler scheduler;
// Used to run the scheduler.
// Also used to checked if the Thread is still running by calling
// thread.isAlive(). Sometimes a Thread is suddenly killed by the system
// (if it belonged to an Applet).
private Thread thread;
// When cancelled we don't accept any more TimerTasks.
private boolean canceled;
/**
* Creates a new Timer with a non daemon Thread as Scheduler, with normal
* priority and a default name.
*/
public Timer()
{
this(false);
}
/**
* Creates a new Timer with a daemon Thread as scheduler if daemon is true,
* with normal priority and a default name.
*/
public Timer(boolean daemon)
{
this(daemon, Thread.NORM_PRIORITY);
}
/**
* Creates a new Timer with a daemon Thread as scheduler if daemon is true,
* with the priority given and a default name.
*/
private Timer(boolean daemon, int priority)
{
this(daemon, priority, "Timer-" + (++nr));
}
/**
* Creates a new Timer with a daemon Thread as scheduler if daemon is true,
* with the priority and name given.E
*/
private Timer(boolean daemon, int priority, String name)
{
canceled = false;
queue = new TaskQueue();
scheduler = new Scheduler(queue);
thread = new Thread(scheduler, name);
thread.setDaemon(daemon);
thread.setPriority(priority);
thread.start();
}
/**
* Cancels the execution of the scheduler. If a task is executing it will
* normally finish execution, but no other tasks will be executed and no
* more tasks can be scheduled.
*/
public void cancel()
{
canceled = true;
queue.stop();
}
/**
* Schedules the task at Time time, repeating every period
* milliseconds if period is positive and at a fixed rate if fixed is true.
*
* @exception IllegalArgumentException if time is negative
* @exception IllegalStateException if the task was already scheduled or
* canceled or this Timer is canceled or the scheduler thread has died
*/
private void schedule(TimerTask task, long time, long period, boolean fixed)
{
if (time < 0)
throw new IllegalArgumentException("negative time");
if (task.scheduled == 0 && task.lastExecutionTime == -1)
{
task.scheduled = time;
task.period = period;
task.fixed = fixed;
}
else
{
throw new IllegalStateException
("task was already scheduled or canceled");
}
if (!this.canceled && this.thread != null)
{
queue.enqueue(task);
}
else
{
throw new IllegalStateException
("timer was canceled or scheduler thread has died");
}
}
private static void positiveDelay(long delay)
{
if (delay < 0)
{
throw new IllegalArgumentException("delay is negative");
}
}
private static void positivePeriod(long period)
{
if (period < 0)
{
throw new IllegalArgumentException("period is negative");
}
}
/**
* Schedules the task at the specified data for one time execution.
*
* @exception IllegalArgumentException if date.getTime() is negative
* @exception IllegalStateException if the task was already scheduled or
* canceled or this Timer is canceled or the scheduler thread has died
*/
public void schedule(TimerTask task, Date date)
{
long time = date.getTime();
schedule(task, time, -1, false);
}
/**
* Schedules the task at the specified date and reschedules the task every
* period milliseconds after the last execution of the task finishes until
* this timer or the task is canceled.
*
* @exception IllegalArgumentException if period or date.getTime() is
* negative
* @exception IllegalStateException if the task was already scheduled or
* canceled or this Timer is canceled or the scheduler thread has died
*/
public void schedule(TimerTask task, Date date, long period)
{
positivePeriod(period);
long time = date.getTime();
schedule(task, time, period, false);
}
/**
* Schedules the task after the specified delay milliseconds for one time
* execution.
*
* @exception IllegalArgumentException if delay or
* System.currentTimeMillis + delay is negative
* @exception IllegalStateException if the task was already scheduled or
* canceled or this Timer is canceled or the scheduler thread has died
*/
public void schedule(TimerTask task, long delay)
{
positiveDelay(delay);
long time = System.currentTimeMillis() + delay;
schedule(task, time, -1, false);
}
/**
* Schedules the task after the delay milliseconds and reschedules the
* task every period milliseconds after the last execution of the task
* finishes until this timer or the task is canceled.
*
* @exception IllegalArgumentException if delay or period is negative
* @exception IllegalStateException if the task was already scheduled or
* canceled or this Timer is canceled or the scheduler thread has died
*/
public void schedule(TimerTask task, long delay, long period)
{
positiveDelay(delay);
positivePeriod(period);
long time = System.currentTimeMillis() + delay;
schedule(task, time, period, false);
}
/**
* Schedules the task at the specified date and reschedules the task at a
* fixed rate every period milliseconds until this timer or the task is
* canceled.
*
* @exception IllegalArgumentException if period or date.getTime() is
* negative
* @exception IllegalStateException if the task was already scheduled or
* canceled or this Timer is canceled or the scheduler thread has died
*/
public void scheduleAtFixedRate(TimerTask task, Date date, long period)
{
positivePeriod(period);
long time = date.getTime();
schedule(task, time, period, true);
}
/**
* Schedules the task after the delay milliseconds and reschedules the task
* at a fixed rate every period milliseconds until this timer or the task
* is canceled.
*
* @exception IllegalArgumentException if delay or
* System.currentTimeMillis + delay is negative
* @exception IllegalStateException if the task was already scheduled or
* canceled or this Timer is canceled or the scheduler thread has died
*/
public void scheduleAtFixedRate(TimerTask task, long delay, long period)
{
positiveDelay(delay);
positivePeriod(period);
long time = System.currentTimeMillis() + delay;
schedule(task, time, period, true);
}
/**
* Tells the scheduler that the Timer task died
* so there will be no more new tasks scheduled.
*/
protected void finalize() throws Throwable
{
queue.setNullOnEmpty(true);
}
}
-145
View File
@@ -1,145 +0,0 @@
/* TimerTask.java -- Task that can be run at a later time if given to a Timer.
Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* Task that can be run at a later time if given to a Timer.
* The TimerTask must implement a run method that will be called by the
* Timer when the task is scheduled for execution. The task can check when
* it should have been scheduled and cancel itself when no longer needed.
* <p>
* Example:
* <pre>
* Timer timer = new Timer();
* TimerTask task = new TimerTask() {
* public void run() {
* if (this.scheduledExecutionTime() &lt; System.currentTimeMillis() + 500)
* // Do something
* else
* // Complain: We are more then half a second late!
* if (someStopCondition)
* this.cancel(); // This was our last execution
* };
* timer.scheduleAtFixedRate(task, 1000, 1000); // schedule every second
* </pre>
* <p>
* Note that a TimerTask object is a one shot object and can only given once
* to a Timer. (The Timer will use the TimerTask object for bookkeeping,
* in this implementation).
* <p>
* This class also implements <code>Runnable</code> to make it possible to
* give a TimerTask directly as a target to a <code>Thread</code>.
*
* @see Timer
* @since 1.3
* @author Mark Wielaard (mark@klomp.org)
*/
public abstract class TimerTask implements Runnable
{
/**
* If positive the next time this task should be run.
* If negative this TimerTask is canceled or executed for the last time.
*/
long scheduled;
/**
* If positive the last time this task was run.
* If negative this TimerTask has not yet been scheduled.
*/
long lastExecutionTime;
/**
* If positive the number of milliseconds between runs of this task.
* If -1 this task doesn't have to be run more then once.
*/
long period;
/**
* If true the next time this task should be run is relative to
* the last scheduled time, otherwise it can drift in time.
*/
boolean fixed;
/**
* Creates a TimerTask and marks it as not yet scheduled.
*/
protected TimerTask()
{
this.scheduled = 0;
this.lastExecutionTime = -1;
}
/**
* Marks the task as canceled and prevents any further execution.
* Returns true if the task was scheduled for any execution in the future
* and this cancel operation prevents that execution from happening.
* <p>
* A task that has been canceled can never be scheduled again.
* <p>
* In this implementation the TimerTask it is possible that the Timer does
* keep a reference to the TimerTask until the first time the TimerTask
* is actually scheduled. But the reference will disappear immediatly when
* cancel is called from within the TimerTask run method.
*/
public boolean cancel()
{
boolean prevented_execution = (this.scheduled >= 0);
this.scheduled = -1;
return prevented_execution;
}
/**
* Method that is called when this task is scheduled for execution.
*/
public abstract void run();
/**
* Returns the last time this task was scheduled or (when called by the
* task from the run method) the time the current execution of the task
* was scheduled. When the task has not yet run the return value is
* undefined.
* <p>
* Can be used (when the task is scheduled at fixed rate) to see the
* difference between the requested schedule time and the actual time
* that can be found with <code>System.currentTimeMillis()</code>.
*/
public long scheduledExecutionTime()
{
return lastExecutionTime;
}
}
@@ -1,78 +0,0 @@
/* TooManyListenersException.java -- thrown when a unicast event can't accept
another Listener
Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
/**
* This exception is part of the java event model. It is thrown if an
* event listener is added via the addXyzEventListener method, but the
* object doesn't support any more listeners, e.g. it only supports a
* single event listener.
*
* @author Jochen Hoenicke
* @author Warren Levy (warrenl@cygnus.com)
* @see EventListener
* @see EventObject
* @since 1.1
* @status updated to 1.4
*/
public class TooManyListenersException extends Exception
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = 5074640544770687831L;
/**
* Constructs a TooManyListenersException with no detail message.
*/
public TooManyListenersException()
{
}
/**
* Constructs a TooManyListenersException with a detail message.
*
* @param detail the detail message
*/
public TooManyListenersException(String detail)
{
super(detail);
}
}
File diff suppressed because it is too large Load Diff
-416
View File
@@ -1,416 +0,0 @@
/* TreeSet.java -- a class providing a TreeMap-backed SortedSet
Copyright (C) 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* This class provides a TreeMap-backed implementation of the SortedSet
* interface. The elements will be sorted according to their <i>natural
* order</i>, or according to the provided <code>Comparator</code>.<p>
*
* Most operations are O(log n), but there is so much overhead that this
* makes small sets expensive. Note that the ordering must be <i>consistent
* with equals</i> to correctly implement the Set interface. If this
* condition is violated, the set is still well-behaved, but you may have
* suprising results when comparing it to other sets.<p>
*
* This implementation is not synchronized. If you need to share this between
* multiple threads, do something like:<br>
* <code>SortedSet s
* = Collections.synchronizedSortedSet(new TreeSet(...));</code><p>
*
* The iterators are <i>fail-fast</i>, meaning that any structural
* modification, except for <code>remove()</code> called on the iterator
* itself, cause the iterator to throw a
* <code>ConcurrentModificationException</code> rather than exhibit
* non-deterministic behavior.
*
* @author Jon Zeppieri
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see Set
* @see HashSet
* @see LinkedHashSet
* @see Comparable
* @see Comparator
* @see Collections#synchronizedSortedSet(SortedSet)
* @see TreeMap
* @since 1.2
* @status updated to 1.4
*/
public class TreeSet extends AbstractSet
implements SortedSet, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2.
*/
private static final long serialVersionUID = -2479143000061671589L;
/**
* The SortedMap which backs this Set.
*/
// Not final because of readObject. This will always be one of TreeMap or
// TreeMap.SubMap, which both extend AbstractMap.
private transient SortedMap map;
/**
* Construct a new TreeSet whose backing TreeMap using the "natural"
* ordering of keys. Elements that are not mutually comparable will cause
* ClassCastExceptions down the road.
*
* @see Comparable
*/
public TreeSet()
{
map = new TreeMap();
}
/**
* Construct a new TreeSet whose backing TreeMap uses the supplied
* Comparator. Elements that are not mutually comparable will cause
* ClassCastExceptions down the road.
*
* @param comparator the Comparator this Set will use
*/
public TreeSet(Comparator comparator)
{
map = new TreeMap(comparator);
}
/**
* Construct a new TreeSet whose backing TreeMap uses the "natural"
* orering of the keys and which contains all of the elements in the
* supplied Collection. This runs in n*log(n) time.
*
* @param collection the new Set will be initialized with all
* of the elements in this Collection
* @throws ClassCastException if the elements of the collection are not
* comparable
* @throws NullPointerException if the collection is null
* @see Comparable
*/
public TreeSet(Collection collection)
{
map = new TreeMap();
addAll(collection);
}
/**
* Construct a new TreeSet, using the same key ordering as the supplied
* SortedSet and containing all of the elements in the supplied SortedSet.
* This constructor runs in linear time.
*
* @param sortedSet the new TreeSet will use this SortedSet's comparator
* and will initialize itself with all its elements
* @throws NullPointerException if sortedSet is null
*/
public TreeSet(SortedSet sortedSet)
{
map = new TreeMap(sortedSet.comparator());
Iterator itr = sortedSet.iterator();
((TreeMap) map).putKeysLinear(itr, sortedSet.size());
}
/**
* This private constructor is used to implement the subSet() calls around
* a backing TreeMap.SubMap.
*
* @param backingMap the submap
*/
private TreeSet(SortedMap backingMap)
{
map = backingMap;
}
/**
* Adds the spplied Object to the Set if it is not already in the Set;
* returns true if the element is added, false otherwise.
*
* @param obj the Object to be added to this Set
* @throws ClassCastException if the element cannot be compared with objects
* already in the set
*/
public boolean add(Object obj)
{
return map.put(obj, "") == null;
}
/**
* Adds all of the elements in the supplied Collection to this TreeSet.
*
* @param c The collection to add
* @return true if the Set is altered, false otherwise
* @throws NullPointerException if c is null
* @throws ClassCastException if an element in c cannot be compared with
* objects already in the set
*/
public boolean addAll(Collection c)
{
boolean result = false;
int pos = c.size();
Iterator itr = c.iterator();
while (--pos >= 0)
result |= (map.put(itr.next(), "") == null);
return result;
}
/**
* Removes all elements in this Set.
*/
public void clear()
{
map.clear();
}
/**
* Returns a shallow copy of this Set. The elements are not cloned.
*
* @return the cloned set
*/
public Object clone()
{
TreeSet copy = null;
try
{
copy = (TreeSet) super.clone();
// Map may be either TreeMap or TreeMap.SubMap, hence the ugly casts.
copy.map = (SortedMap) ((AbstractMap) map).clone();
}
catch (CloneNotSupportedException x)
{
// Impossible result.
}
return copy;
}
/**
* Returns this Set's comparator.
*
* @return the comparator, or null if the set uses natural ordering
*/
public Comparator comparator()
{
return map.comparator();
}
/**
* Returns true if this Set contains the supplied Object, false otherwise.
*
* @param obj the Object to check for
* @return true if it is in the set
* @throws ClassCastException if obj cannot be compared with objects
* already in the set
*/
public boolean contains(Object obj)
{
return map.containsKey(obj);
}
/**
* Returns the first (by order) element in this Set.
*
* @return the first element
* @throws NoSuchElementException if the set is empty
*/
public Object first()
{
return map.firstKey();
}
/**
* Returns a view of this Set including all elements less than
* <code>to</code>. The returned set is backed by the original, so changes
* in one appear in the other. The subset will throw an
* {@link IllegalArgumentException} for any attempt to access or add an
* element beyond the specified cutoff. The returned set does not include
* the endpoint; if you want inclusion, pass the successor element.
*
* @param to the (exclusive) cutoff point
* @return a view of the set less than the cutoff
* @throws ClassCastException if <code>to</code> is not compatible with
* the comparator (or is not Comparable, for natural ordering)
* @throws NullPointerException if to is null, but the comparator does not
* tolerate null elements
*/
public SortedSet headSet(Object to)
{
return new TreeSet(map.headMap(to));
}
/**
* Returns true if this Set has size 0, false otherwise.
*
* @return true if the set is empty
*/
public boolean isEmpty()
{
return map.isEmpty();
}
/**
* Returns in Iterator over the elements in this TreeSet, which traverses
* in ascending order.
*
* @return an iterator
*/
public Iterator iterator()
{
return map.keySet().iterator();
}
/**
* Returns the last (by order) element in this Set.
*
* @return the last element
* @throws NoSuchElementException if the set is empty
*/
public Object last()
{
return map.lastKey();
}
/**
* If the supplied Object is in this Set, it is removed, and true is
* returned; otherwise, false is returned.
*
* @param obj the Object to remove from this Set
* @return true if the set was modified
* @throws ClassCastException if obj cannot be compared to set elements
*/
public boolean remove(Object obj)
{
return map.remove(obj) != null;
}
/**
* Returns the number of elements in this Set
*
* @return the set size
*/
public int size()
{
return map.size();
}
/**
* Returns a view of this Set including all elements greater or equal to
* <code>from</code> and less than <code>to</code> (a half-open interval).
* The returned set is backed by the original, so changes in one appear in
* the other. The subset will throw an {@link IllegalArgumentException}
* for any attempt to access or add an element beyond the specified cutoffs.
* The returned set includes the low endpoint but not the high; if you want
* to reverse this behavior on either end, pass in the successor element.
*
* @param from the (inclusive) low cutoff point
* @param to the (exclusive) high cutoff point
* @return a view of the set between the cutoffs
* @throws ClassCastException if either cutoff is not compatible with
* the comparator (or is not Comparable, for natural ordering)
* @throws NullPointerException if from or to is null, but the comparator
* does not tolerate null elements
* @throws IllegalArgumentException if from is greater than to
*/
public SortedSet subSet(Object from, Object to)
{
return new TreeSet(map.subMap(from, to));
}
/**
* Returns a view of this Set including all elements greater or equal to
* <code>from</code>. The returned set is backed by the original, so
* changes in one appear in the other. The subset will throw an
* {@link IllegalArgumentException} for any attempt to access or add an
* element beyond the specified cutoff. The returned set includes the
* endpoint; if you want to exclude it, pass in the successor element.
*
* @param from the (inclusive) low cutoff point
* @return a view of the set above the cutoff
* @throws ClassCastException if <code>from</code> is not compatible with
* the comparator (or is not Comparable, for natural ordering)
* @throws NullPointerException if from is null, but the comparator
* does not tolerate null elements
*/
public SortedSet tailSet(Object from)
{
return new TreeSet(map.tailMap(from));
}
/**
* Serializes this object to the given stream.
*
* @param s the stream to write to
* @throws IOException if the underlying stream fails
* @serialData the <i>comparator</i> (Object), followed by the set size
* (int), the the elements in sorted order (Object)
*/
private void writeObject(ObjectOutputStream s) throws IOException
{
s.defaultWriteObject();
Iterator itr = map.keySet().iterator();
int pos = map.size();
s.writeObject(map.comparator());
s.writeInt(pos);
while (--pos >= 0)
s.writeObject(itr.next());
}
/**
* Deserializes this object from the given stream.
*
* @param s the stream to read from
* @throws ClassNotFoundException if the underlying stream fails
* @throws IOException if the underlying stream fails
* @serialData the <i>comparator</i> (Object), followed by the set size
* (int), the the elements in sorted order (Object)
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
Comparator comparator = (Comparator) s.readObject();
int size = s.readInt();
map = new TreeMap(comparator);
((TreeMap) map).putFromObjStream(s, size, false);
}
}
-931
View File
@@ -1,931 +0,0 @@
/* Vector.java -- Class that provides growable arrays.
Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
/**
* The <code>Vector</code> classes implements growable arrays of Objects.
* You can access elements in a Vector with an index, just as you
* can in a built in array, but Vectors can grow and shrink to accommodate
* more or fewer objects.<p>
*
* Vectors try to mantain efficiency in growing by having a
* <code>capacityIncrement</code> that can be specified at instantiation.
* When a Vector can no longer hold a new Object, it grows by the amount
* in <code>capacityIncrement</code>. If this value is 0, the vector doubles in
* size.<p>
*
* Vector implements the JDK 1.2 List interface, and is therefore a fully
* compliant Collection object. The iterators are fail-fast - if external
* code structurally modifies the vector, any operation on the iterator will
* then throw a {@link ConcurrentModificationException}. The Vector class is
* fully synchronized, but the iterators are not. So, when iterating over a
* vector, be sure to synchronize on the vector itself. If you don't want the
* expense of synchronization, use ArrayList instead. On the other hand, the
* Enumeration of elements() is not thread-safe, nor is it fail-fast; so it
* can lead to undefined behavior even in a single thread if you modify the
* vector during iteration.<p>
*
* Note: Some methods, especially those specified by List, specify throwing
* {@link IndexOutOfBoundsException}, but it is easier to implement by
* throwing the subclass {@link ArrayIndexOutOfBoundsException}. Others
* directly specify this subclass.
*
* @author Scott G. Miller
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
* @see Collection
* @see List
* @see ArrayList
* @see LinkedList
* @since 1.0
* @status updated to 1.4
*/
public class Vector extends AbstractList
implements List, RandomAccess, Cloneable, Serializable
{
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = -2767605614048989439L;
/**
* The internal array used to hold members of a Vector. The elements are
* in positions 0 through elementCount - 1, and all remaining slots are null.
* @serial the elements
*/
protected Object[] elementData;
/**
* The number of elements currently in the vector, also returned by
* {@link #size}.
* @serial the size
*/
protected int elementCount;
/**
* The amount the Vector's internal array should be increased in size when
* a new element is added that exceeds the current size of the array,
* or when {@link #ensureCapacity} is called. If &lt;= 0, the vector just
* doubles in size.
* @serial the amount to grow the vector by
*/
protected int capacityIncrement;
/**
* Constructs an empty vector with an initial size of 10, and
* a capacity increment of 0
*/
public Vector()
{
this(10, 0);
}
/**
* Constructs a vector containing the contents of Collection, in the
* order given by the collection.
*
* @param c collection of elements to add to the new vector
* @throws NullPointerException if c is null
* @since 1.2
*/
public Vector(Collection c)
{
elementCount = c.size();
elementData = c.toArray(new Object[elementCount]);
}
/**
* Constructs a Vector with the initial capacity and capacity
* increment specified.
*
* @param initialCapacity the initial size of the Vector's internal array
* @param capacityIncrement the amount the internal array should be
* increased by when necessary, 0 to double the size
* @throws IllegalArgumentException if initialCapacity &lt; 0
*/
public Vector(int initialCapacity, int capacityIncrement)
{
if (initialCapacity < 0)
throw new IllegalArgumentException();
elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
/**
* Constructs a Vector with the initial capacity specified, and a capacity
* increment of 0 (double in size).
*
* @param initialCapacity the initial size of the Vector's internal array
* @throws IllegalArgumentException if initialCapacity &lt; 0
*/
public Vector(int initialCapacity)
{
this(initialCapacity, 0);
}
/**
* Copies the contents of a provided array into the Vector. If the
* array is too large to fit in the Vector, an IndexOutOfBoundsException
* is thrown without modifying the array. Old elements in the Vector are
* overwritten by the new elements.
*
* @param a target array for the copy
* @throws IndexOutOfBoundsException the array is not large enough
* @throws NullPointerException the array is null
* @see #toArray(Object[])
*/
public synchronized void copyInto(Object[] a)
{
System.arraycopy(elementData, 0, a, 0, elementCount);
}
/**
* Trims the Vector down to size. If the internal data array is larger
* than the number of Objects its holding, a new array is constructed
* that precisely holds the elements. Otherwise this does nothing.
*/
public synchronized void trimToSize()
{
// Don't bother checking for the case where size() == the capacity of the
// vector since that is a much less likely case; it's more efficient to
// not do the check and lose a bit of performance in that infrequent case
Object[] newArray = new Object[elementCount];
System.arraycopy(elementData, 0, newArray, 0, elementCount);
elementData = newArray;
}
/**
* Ensures that <code>minCapacity</code> elements can fit within this Vector.
* If <code>elementData</code> is too small, it is expanded as follows:
* If the <code>elementCount + capacityIncrement</code> is adequate, that
* is the new size. If <code>capacityIncrement</code> is non-zero, the
* candidate size is double the current. If that is not enough, the new
* size is <code>minCapacity</code>.
*
* @param minCapacity the desired minimum capacity, negative values ignored
*/
public synchronized void ensureCapacity(int minCapacity)
{
if (elementData.length >= minCapacity)
return;
int newCapacity;
if (capacityIncrement <= 0)
newCapacity = elementData.length * 2;
else
newCapacity = elementData.length + capacityIncrement;
Object[] newArray = new Object[Math.max(newCapacity, minCapacity)];
System.arraycopy(elementData, 0, newArray, 0, elementCount);
elementData = newArray;
}
/**
* Explicitly sets the size of the vector (but not necessarily the size of
* the internal data array). If the new size is smaller than the old one,
* old values that don't fit are lost. If the new size is larger than the
* old one, the vector is padded with null entries.
*
* @param newSize The new size of the internal array
* @throws ArrayIndexOutOfBoundsException if the new size is negative
*/
public synchronized void setSize(int newSize)
{
// Don't bother checking for the case where size() == the capacity of the
// vector since that is a much less likely case; it's more efficient to
// not do the check and lose a bit of performance in that infrequent case
modCount++;
ensureCapacity(newSize);
if (newSize < elementCount)
Arrays.fill(elementData, newSize, elementCount, null);
elementCount = newSize;
}
/**
* Returns the size of the internal data array (not the amount of elements
* contained in the Vector).
*
* @return capacity of the internal data array
*/
public synchronized int capacity()
{
return elementData.length;
}
/**
* Returns the number of elements stored in this Vector.
*
* @return the number of elements in this Vector
*/
public synchronized int size()
{
return elementCount;
}
/**
* Returns true if this Vector is empty, false otherwise
*
* @return true if the Vector is empty, false otherwise
*/
public synchronized boolean isEmpty()
{
return elementCount == 0;
}
/**
* Returns an Enumeration of the elements of this Vector. The enumeration
* visits the elements in increasing index order, but is NOT thread-safe.
*
* @return an Enumeration
* @see #iterator()
*/
// No need to synchronize as the Enumeration is not thread-safe!
public Enumeration elements()
{
return new Enumeration()
{
private int i = 0;
public boolean hasMoreElements()
{
return i < elementCount;
}
public Object nextElement()
{
if (i >= elementCount)
throw new NoSuchElementException();
return elementData[i++];
}
};
}
/**
* Returns true when <code>elem</code> is contained in this Vector.
*
* @param elem the element to check
* @return true if the object is contained in this Vector, false otherwise
*/
public boolean contains(Object elem)
{
return indexOf(elem, 0) >= 0;
}
/**
* Returns the first occurrence of <code>elem</code> in the Vector, or -1 if
* <code>elem</code> is not found.
*
* @param elem the object to search for
* @return the index of the first occurrence, or -1 if not found
*/
public int indexOf(Object elem)
{
return indexOf(elem, 0);
}
/**
* Searches the vector starting at <code>index</code> for object
* <code>elem</code> and returns the index of the first occurrence of this
* Object. If the object is not found, or index is larger than the size
* of the vector, -1 is returned.
*
* @param e the Object to search for
* @param index start searching at this index
* @return the index of the next occurrence, or -1 if it is not found
* @throws IndexOutOfBoundsException if index &lt; 0
*/
public synchronized int indexOf(Object e, int index)
{
for (int i = index; i < elementCount; i++)
if (equals(e, elementData[i]))
return i;
return -1;
}
/**
* Returns the last index of <code>elem</code> within this Vector, or -1
* if the object is not within the Vector.
*
* @param elem the object to search for
* @return the last index of the object, or -1 if not found
*/
public int lastIndexOf(Object elem)
{
return lastIndexOf(elem, elementCount - 1);
}
/**
* Returns the index of the first occurrence of <code>elem</code>, when
* searching backwards from <code>index</code>. If the object does not
* occur in this Vector, or index is less than 0, -1 is returned.
*
* @param e the object to search for
* @param index the index to start searching in reverse from
* @return the index of the Object if found, -1 otherwise
* @throws IndexOutOfBoundsException if index &gt;= size()
*/
public synchronized int lastIndexOf(Object e, int index)
{
checkBoundExclusive(index);
for (int i = index; i >= 0; i--)
if (equals(e, elementData[i]))
return i;
return -1;
}
/**
* Returns the Object stored at <code>index</code>.
*
* @param index the index of the Object to retrieve
* @return the object at <code>index</code>
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
* @see #get(int)
*/
public synchronized Object elementAt(int index)
{
checkBoundExclusive(index);
return elementData[index];
}
/**
* Returns the first element (index 0) in the Vector.
*
* @return the first Object in the Vector
* @throws NoSuchElementException the Vector is empty
*/
public synchronized Object firstElement()
{
if (elementCount == 0)
throw new NoSuchElementException();
return elementData[0];
}
/**
* Returns the last element in the Vector.
*
* @return the last Object in the Vector
* @throws NoSuchElementException the Vector is empty
*/
public synchronized Object lastElement()
{
if (elementCount == 0)
throw new NoSuchElementException();
return elementData[elementCount - 1];
}
/**
* Changes the element at <code>index</code> to be <code>obj</code>
*
* @param obj the object to store
* @param index the position in the Vector to store the object
* @throws ArrayIndexOutOfBoundsException the index is out of range
* @see #set(int, Object)
*/
public void setElementAt(Object obj, int index)
{
set(index, obj);
}
/**
* Removes the element at <code>index</code>, and shifts all elements at
* positions greater than index to their index - 1.
*
* @param index the index of the element to remove
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size();
* @see #remove(int)
*/
public void removeElementAt(int index)
{
remove(index);
}
/**
* Inserts a new element into the Vector at <code>index</code>. Any elements
* at or greater than index are shifted up one position.
*
* @param obj the object to insert
* @param index the index at which the object is inserted
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
* @see #add(int, Object)
*/
public synchronized void insertElementAt(Object obj, int index)
{
checkBoundInclusive(index);
if (elementCount == elementData.length)
ensureCapacity(elementCount + 1);
modCount++;
System.arraycopy(elementData, index, elementData, index + 1,
elementCount - index);
elementCount++;
elementData[index] = obj;
}
/**
* Adds an element to the Vector at the end of the Vector. The vector
* is increased by ensureCapacity(size() + 1) if needed.
*
* @param obj the object to add to the Vector
*/
public synchronized void addElement(Object obj)
{
if (elementCount == elementData.length)
ensureCapacity(elementCount + 1);
modCount++;
elementData[elementCount++] = obj;
}
/**
* Removes the first (the lowestindex) occurance of the given object from
* the Vector. If such a remove was performed (the object was found), true
* is returned. If there was no such object, false is returned.
*
* @param obj the object to remove from the Vector
* @return true if the Object was in the Vector, false otherwise
* @see #remove(Object)
*/
public synchronized boolean removeElement(Object obj)
{
int idx = indexOf(obj, 0);
if (idx >= 0)
{
remove(idx);
return true;
}
return false;
}
/**
* Removes all elements from the Vector. Note that this does not
* resize the internal data array.
*
* @see #clear()
*/
public synchronized void removeAllElements()
{
if (elementCount == 0)
return;
modCount++;
Arrays.fill(elementData, 0, elementCount, null);
elementCount = 0;
}
/**
* Creates a new Vector with the same contents as this one. The clone is
* shallow; elements are not cloned.
*
* @return the clone of this vector
*/
public synchronized Object clone()
{
try
{
Vector clone = (Vector) super.clone();
clone.elementData = (Object[]) elementData.clone();
return clone;
}
catch (CloneNotSupportedException ex)
{
// Impossible to get here.
throw new InternalError(ex.toString());
}
}
/**
* Returns an Object array with the contents of this Vector, in the order
* they are stored within this Vector. Note that the Object array returned
* is not the internal data array, and that it holds only the elements
* within the Vector. This is similar to creating a new Object[] with the
* size of this Vector, then calling Vector.copyInto(yourArray).
*
* @return an Object[] containing the contents of this Vector in order
* @since 1.2
*/
public synchronized Object[] toArray()
{
Object[] newArray = new Object[elementCount];
copyInto(newArray);
return newArray;
}
/**
* Returns an array containing the contents of this Vector.
* If the provided array is large enough, the contents are copied
* into that array, and a null is placed in the position size().
* In this manner, you can obtain the size of a Vector by the position
* of the null element, if you know the vector does not itself contain
* null entries. If the array is not large enough, reflection is used
* to create a bigger one of the same runtime type.
*
* @param a an array to copy the Vector into if large enough
* @return an array with the contents of this Vector in order
* @throws ArrayStoreException the runtime type of the provided array
* cannot hold the elements of the Vector
* @throws NullPointerException if <code>a</code> is null
* @since 1.2
*/
public synchronized Object[] toArray(Object[] a)
{
if (a.length < elementCount)
a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
elementCount);
else if (a.length > elementCount)
a[elementCount] = null;
System.arraycopy(elementData, 0, a, 0, elementCount);
return a;
}
/**
* Returns the element at position <code>index</code>.
*
* @param index the position from which an element will be retrieved
* @return the element at that position
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
* @since 1.2
*/
public Object get(int index)
{
return elementAt(index);
}
/**
* Puts <code>element</code> into the Vector at position <code>index</code>
* and returns the Object that previously occupied that position.
*
* @param index the index within the Vector to place the Object
* @param element the Object to store in the Vector
* @return the previous object at the specified index
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
* @since 1.2
*/
public synchronized Object set(int index, Object element)
{
checkBoundExclusive(index);
Object temp = elementData[index];
elementData[index] = element;
return temp;
}
/**
* Adds an object to the Vector.
*
* @param o the element to add to the Vector
* @return true, as specified by List
* @since 1.2
*/
public boolean add(Object o)
{
addElement(o);
return true;
}
/**
* Removes the given Object from the Vector. If it exists, true
* is returned, if not, false is returned.
*
* @param o the object to remove from the Vector
* @return true if the Object existed in the Vector, false otherwise
* @since 1.2
*/
public boolean remove(Object o)
{
return removeElement(o);
}
/**
* Adds an object at the specified index. Elements at or above
* index are shifted up one position.
*
* @param index the index at which to add the element
* @param element the element to add to the Vector
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
* @since 1.2
*/
public void add(int index, Object element)
{
insertElementAt(element, index);
}
/**
* Removes the element at the specified index, and returns it.
*
* @param index the position from which to remove the element
* @return the object removed
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
* @since 1.2
*/
public synchronized Object remove(int index)
{
checkBoundExclusive(index);
Object temp = elementData[index];
modCount++;
elementCount--;
if (index < elementCount)
System.arraycopy(elementData, index + 1, elementData, index,
elementCount - index);
elementData[elementCount] = null;
return temp;
}
/**
* Clears all elements in the Vector and sets its size to 0.
*/
public void clear()
{
removeAllElements();
}
/**
* Returns true if this Vector contains all the elements in c.
*
* @param c the collection to compare to
* @return true if this vector contains all elements of c
* @throws NullPointerException if c is null
* @since 1.2
*/
public synchronized boolean containsAll(Collection c)
{
// Here just for the sychronization.
return super.containsAll(c);
}
/**
* Appends all elements of the given collection to the end of this Vector.
* Behavior is undefined if the collection is modified during this operation
* (for example, if this == c).
*
* @param c the collection to append
* @return true if this vector changed, in other words c was not empty
* @throws NullPointerException if c is null
* @since 1.2
*/
public synchronized boolean addAll(Collection c)
{
return addAll(elementCount, c);
}
/**
* Remove from this vector all elements contained in the given collection.
*
* @param c the collection to filter out
* @return true if this vector changed
* @throws NullPointerException if c is null
* @since 1.2
*/
public synchronized boolean removeAll(Collection c)
{
if (c == null)
throw new NullPointerException();
int i;
int j;
for (i = 0; i < elementCount; i++)
if (c.contains(elementData[i]))
break;
if (i == elementCount)
return false;
modCount++;
for (j = i++; i < elementCount; i++)
if (! c.contains(elementData[i]))
elementData[j++] = elementData[i];
elementCount -= i - j;
return true;
}
/**
* Retain in this vector only the elements contained in the given collection.
*
* @param c the collection to filter by
* @return true if this vector changed
* @throws NullPointerException if c is null
* @since 1.2
*/
public synchronized boolean retainAll(Collection c)
{
if (c == null)
throw new NullPointerException();
int i;
int j;
for (i = 0; i < elementCount; i++)
if (! c.contains(elementData[i]))
break;
if (i == elementCount)
return false;
modCount++;
for (j = i++; i < elementCount; i++)
if (c.contains(elementData[i]))
elementData[j++] = elementData[i];
elementCount -= i - j;
return true;
}
/**
* Inserts all elements of the given collection at the given index of
* this Vector. Behavior is undefined if the collection is modified during
* this operation (for example, if this == c).
*
* @param c the collection to append
* @return true if this vector changed, in other words c was not empty
* @throws NullPointerException if c is null
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
* @since 1.2
*/
public synchronized boolean addAll(int index, Collection c)
{
checkBoundInclusive(index);
Iterator itr = c.iterator();
int csize = c.size();
modCount++;
ensureCapacity(elementCount + csize);
int end = index + csize;
if (elementCount > 0 && index != elementCount)
System.arraycopy(elementData, index,
elementData, end, elementCount - index);
elementCount += csize;
for ( ; index < end; index++)
elementData[index] = itr.next();
return (csize > 0);
}
/**
* Compares this to the given object.
*
* @param o the object to compare to
* @return true if the two are equal
* @since 1.2
*/
public synchronized boolean equals(Object o)
{
// Here just for the sychronization.
return super.equals(o);
}
/**
* Computes the hashcode of this object.
*
* @return the hashcode
* @since 1.2
*/
public synchronized int hashCode()
{
// Here just for the sychronization.
return super.hashCode();
}
/**
* Returns a string representation of this Vector in the form
* "[element0, element1, ... elementN]".
*
* @return the String representation of this Vector
*/
public synchronized String toString()
{
// Here just for the sychronization.
return super.toString();
}
/**
* Obtain a List view of a subsection of this list, from fromIndex
* (inclusive) to toIndex (exclusive). If the two indices are equal, the
* sublist is empty. The returned list is modifiable, and changes in one
* reflect in the other. If this list is structurally modified in
* any way other than through the returned list, the result of any subsequent
* operations on the returned list is undefined.
* <p>
*
* @param fromIndex the index that the returned list should start from
* (inclusive)
* @param toIndex the index that the returned list should go to (exclusive)
* @return a List backed by a subsection of this vector
* @throws IndexOutOfBoundsException if fromIndex &lt; 0
* || toIndex &gt; size()
* @throws IllegalArgumentException if fromIndex &gt; toIndex
* @see ConcurrentModificationException
* @since 1.2
*/
public synchronized List subList(int fromIndex, int toIndex)
{
List sub = super.subList(fromIndex, toIndex);
// We must specify the correct object to synchronize upon, hence the
// use of a non-public API
return new Collections.SynchronizedList(this, sub);
}
/**
* Removes a range of elements from this list.
* Does nothing when toIndex is equal to fromIndex.
*
* @param fromIndex the index to start deleting from (inclusive)
* @param toIndex the index to delete up to (exclusive)
* @throws IndexOutOfBoundsException if fromIndex &gt; toIndex
*/
// This does not need to be synchronized, because it is only called through
// clear() of a sublist, and clear() had already synchronized.
protected void removeRange(int fromIndex, int toIndex)
{
int change = toIndex - fromIndex;
if (change > 0)
{
modCount++;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
elementCount - toIndex);
int save = elementCount;
elementCount -= change;
Arrays.fill(elementData, elementCount, save, null);
}
else if (change < 0)
throw new IndexOutOfBoundsException();
}
/**
* Checks that the index is in the range of possible elements (inclusive).
*
* @param index the index to check
* @throws ArrayIndexOutOfBoundsException if index &gt; size
*/
private void checkBoundInclusive(int index)
{
// Implementation note: we do not check for negative ranges here, since
// use of a negative index will cause an ArrayIndexOutOfBoundsException
// with no effort on our part.
if (index > elementCount)
throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount);
}
/**
* Checks that the index is in the range of existing elements (exclusive).
*
* @param index the index to check
* @throws ArrayIndexOutOfBoundsException if index &gt;= size
*/
private void checkBoundExclusive(int index)
{
// Implementation note: we do not check for negative ranges here, since
// use of a negative index will cause an ArrayIndexOutOfBoundsException
// with no effort on our part.
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
/**
* Serializes this object to the given stream.
*
* @param s the stream to write to
* @throws IOException if the underlying stream fails
* @serialData just calls default write function
*/
private synchronized void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
}
}
-881
View File
@@ -1,881 +0,0 @@
/* WeakHashMap -- a hashtable that keeps only weak references
to its keys, allowing the virtual machine to reclaim them
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
/**
* A weak hash map has only weak references to the key. This means that it
* allows the key to be garbage collected if it is not used otherwise. If
* this happens, the entry will eventually disappear from the map,
* asynchronously.
*
* <p>A weak hash map makes most sense when the keys doesn't override the
* <code>equals</code> method: If there is no other reference to the
* key nobody can ever look up the key in this table and so the entry
* can be removed. This table also works when the <code>equals</code>
* method is overloaded, such as String keys, but you should be prepared
* to deal with some entries disappearing spontaneously.
*
* <p>Other strange behaviors to be aware of: The size of this map may
* spontaneously shrink (even if you use a synchronized map and synchronize
* it); it behaves as if another thread removes entries from this table
* without synchronization. The entry set returned by <code>entrySet</code>
* has similar phenomenons: The size may spontaneously shrink, or an
* entry, that was in the set before, suddenly disappears.
*
* <p>A weak hash map is not meant for caches; use a normal map, with
* soft references as values instead, or try {@link LinkedHashMap}.
*
* <p>The weak hash map supports null values and null keys. The null key
* is never deleted from the map (except explictly of course). The
* performance of the methods are similar to that of a hash map.
*
* <p>The value objects are strongly referenced by this table. So if a
* value object maintains a strong reference to the key (either direct
* or indirect) the key will never be removed from this map. According
* to Sun, this problem may be fixed in a future release. It is not
* possible to do it with the jdk 1.2 reference model, though.
*
* @author Jochen Hoenicke
* @author Eric Blake (ebb9@email.byu.edu)
*
* @see HashMap
* @see WeakReference
* @see LinkedHashMap
* @since 1.2
* @status updated to 1.4
*/
public class WeakHashMap extends AbstractMap implements Map
{
// WARNING: WeakHashMap is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
/**
* The default capacity for an instance of HashMap.
* Sun's documentation mildly suggests that this (11) is the correct
* value.
*/
private static final int DEFAULT_CAPACITY = 11;
/**
* The default load factor of a HashMap.
*/
private static final float DEFAULT_LOAD_FACTOR = 0.75F;
/**
* This is used instead of the key value <i>null</i>. It is needed
* to distinguish between an null key and a removed key.
*/
// Package visible for use by nested classes.
static final Object NULL_KEY = new Object()
{
/**
* Sets the hashCode to 0, since that's what null would map to.
* @return the hash code 0
*/
public int hashCode()
{
return 0;
}
/**
* Compares this key to the given object. Normally, an object should
* NEVER compare equal to null, but since we don't publicize NULL_VALUE,
* it saves bytecode to do so here.
* @return true iff o is this or null
*/
public boolean equals(Object o)
{
return null == o || this == o;
}
};
/**
* The reference queue where our buckets (which are WeakReferences) are
* registered to.
*/
private final ReferenceQueue queue;
/**
* The number of entries in this hash map.
*/
// Package visible for use by nested classes.
int size;
/**
* The load factor of this WeakHashMap. This is the maximum ratio of
* size versus number of buckets. If size grows the number of buckets
* must grow, too.
*/
private float loadFactor;
/**
* The rounded product of the capacity (i.e. number of buckets) and
* the load factor. When the number of elements exceeds the
* threshold, the HashMap calls <code>rehash()</code>.
*/
private int threshold;
/**
* The number of structural modifications. This is used by
* iterators, to see if they should fail. This doesn't count
* the silent key removals, when a weak reference is cleared
* by the garbage collection. Instead the iterators must make
* sure to have strong references to the entries they rely on.
*/
// Package visible for use by nested classes.
int modCount;
/**
* The entry set. There is only one instance per hashmap, namely
* theEntrySet. Note that the entry set may silently shrink, just
* like the WeakHashMap.
*/
private final class WeakEntrySet extends AbstractSet
{
/**
* Non-private constructor to reduce bytecode emitted.
*/
WeakEntrySet()
{
}
/**
* Returns the size of this set.
*
* @return the set size
*/
public int size()
{
return size;
}
/**
* Returns an iterator for all entries.
*
* @return an Entry iterator
*/
public Iterator iterator()
{
return new Iterator()
{
/**
* The entry that was returned by the last
* <code>next()</code> call. This is also the entry whose
* bucket should be removed by the <code>remove</code> call. <br>
*
* It is null, if the <code>next</code> method wasn't
* called yet, or if the entry was already removed. <br>
*
* Remembering this entry here will also prevent it from
* being removed under us, since the entry strongly refers
* to the key.
*/
WeakBucket.WeakEntry lastEntry;
/**
* The entry that will be returned by the next
* <code>next()</code> call. It is <code>null</code> if there
* is no further entry. <br>
*
* Remembering this entry here will also prevent it from
* being removed under us, since the entry strongly refers
* to the key.
*/
WeakBucket.WeakEntry nextEntry = findNext(null);
/**
* The known number of modification to the list, if it differs
* from the real number, we throw an exception.
*/
int knownMod = modCount;
/**
* Check the known number of modification to the number of
* modifications of the table. If it differs from the real
* number, we throw an exception.
* @throws ConcurrentModificationException if the number
* of modifications doesn't match.
*/
private void checkMod()
{
// This method will get inlined.
cleanQueue();
if (knownMod != modCount)
throw new ConcurrentModificationException();
}
/**
* Get a strong reference to the next entry after
* lastBucket.
* @param lastEntry the previous bucket, or null if we should
* get the first entry.
* @return the next entry.
*/
private WeakBucket.WeakEntry findNext(WeakBucket.WeakEntry lastEntry)
{
int slot;
WeakBucket nextBucket;
if (lastEntry != null)
{
nextBucket = lastEntry.getBucket().next;
slot = lastEntry.getBucket().slot;
}
else
{
nextBucket = buckets[0];
slot = 0;
}
while (true)
{
while (nextBucket != null)
{
WeakBucket.WeakEntry entry = nextBucket.getEntry();
if (entry != null)
// This is the next entry.
return entry;
// Entry was cleared, try next.
nextBucket = nextBucket.next;
}
slot++;
if (slot == buckets.length)
// No more buckets, we are through.
return null;
nextBucket = buckets[slot];
}
}
/**
* Checks if there are more entries.
* @return true, iff there are more elements.
* @throws ConcurrentModificationException if the hash map was
* modified.
*/
public boolean hasNext()
{
checkMod();
return nextEntry != null;
}
/**
* Returns the next entry.
* @return the next entry.
* @throws ConcurrentModificationException if the hash map was
* modified.
* @throws NoSuchElementException if there is no entry.
*/
public Object next()
{
checkMod();
if (nextEntry == null)
throw new NoSuchElementException();
lastEntry = nextEntry;
nextEntry = findNext(lastEntry);
return lastEntry;
}
/**
* Removes the last returned entry from this set. This will
* also remove the bucket of the underlying weak hash map.
* @throws ConcurrentModificationException if the hash map was
* modified.
* @throws IllegalStateException if <code>next()</code> was
* never called or the element was already removed.
*/
public void remove()
{
checkMod();
if (lastEntry == null)
throw new IllegalStateException();
modCount++;
internalRemove(lastEntry.getBucket());
lastEntry = null;
knownMod++;
}
};
}
}
/**
* A bucket is a weak reference to the key, that contains a strong
* reference to the value, a pointer to the next bucket and its slot
* number. <br>
*
* It would be cleaner to have a WeakReference as field, instead of
* extending it, but if a weak reference gets cleared, we only get
* the weak reference (by queue.poll) and wouldn't know where to
* look for this reference in the hashtable, to remove that entry.
*
* @author Jochen Hoenicke
*/
private static class WeakBucket extends WeakReference
{
/**
* The value of this entry. The key is stored in the weak
* reference that we extend.
*/
Object value;
/**
* The next bucket describing another entry that uses the same
* slot.
*/
WeakBucket next;
/**
* The slot of this entry. This should be
* <code>Math.abs(key.hashCode() % buckets.length)</code>.
*
* But since the key may be silently removed we have to remember
* the slot number.
*
* If this bucket was removed the slot is -1. This marker will
* prevent the bucket from being removed twice.
*/
int slot;
/**
* Creates a new bucket for the given key/value pair and the specified
* slot.
* @param key the key
* @param queue the queue the weak reference belongs to
* @param value the value
* @param slot the slot. This must match the slot where this bucket
* will be enqueued.
*/
public WeakBucket(Object key, ReferenceQueue queue, Object value,
int slot)
{
super(key, queue);
this.value = value;
this.slot = slot;
}
/**
* This class gives the <code>Entry</code> representation of the
* current bucket. It also keeps a strong reference to the
* key; bad things may happen otherwise.
*/
class WeakEntry implements Map.Entry
{
/**
* The strong ref to the key.
*/
Object key;
/**
* Creates a new entry for the key.
* @param key the key
*/
public WeakEntry(Object key)
{
this.key = key;
}
/**
* Returns the underlying bucket.
* @return the owning bucket
*/
public WeakBucket getBucket()
{
return WeakBucket.this;
}
/**
* Returns the key.
* @return the key
*/
public Object getKey()
{
return key == NULL_KEY ? null : key;
}
/**
* Returns the value.
* @return the value
*/
public Object getValue()
{
return value;
}
/**
* This changes the value. This change takes place in
* the underlying hash map.
* @param newVal the new value
* @return the old value
*/
public Object setValue(Object newVal)
{
Object oldVal = value;
value = newVal;
return oldVal;
}
/**
* The hashCode as specified in the Entry interface.
* @return the hash code
*/
public int hashCode()
{
return key.hashCode() ^ WeakHashMap.hashCode(value);
}
/**
* The equals method as specified in the Entry interface.
* @param o the object to compare to
* @return true iff o represents the same key/value pair
*/
public boolean equals(Object o)
{
if (o instanceof Map.Entry)
{
Map.Entry e = (Map.Entry) o;
return key.equals(e.getKey())
&& WeakHashMap.equals(value, e.getValue());
}
return false;
}
public String toString()
{
return key + "=" + value;
}
}
/**
* This returns the entry stored in this bucket, or null, if the
* bucket got cleared in the mean time.
* @return the Entry for this bucket, if it exists
*/
WeakEntry getEntry()
{
final Object key = this.get();
if (key == null)
return null;
return new WeakEntry(key);
}
}
/**
* The entry set returned by <code>entrySet()</code>.
*/
private final WeakEntrySet theEntrySet;
/**
* The hash buckets. These are linked lists. Package visible for use in
* nested classes.
*/
WeakBucket[] buckets;
/**
* Creates a new weak hash map with default load factor and default
* capacity.
*/
public WeakHashMap()
{
this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
}
/**
* Creates a new weak hash map with default load factor and the given
* capacity.
* @param initialCapacity the initial capacity
* @throws IllegalArgumentException if initialCapacity is negative
*/
public WeakHashMap(int initialCapacity)
{
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
/**
* Creates a new weak hash map with the given initial capacity and
* load factor.
* @param initialCapacity the initial capacity.
* @param loadFactor the load factor (see class description of HashMap).
* @throws IllegalArgumentException if initialCapacity is negative, or
* loadFactor is non-positive
*/
public WeakHashMap(int initialCapacity, float loadFactor)
{
// Check loadFactor for NaN as well.
if (initialCapacity < 0 || ! (loadFactor > 0))
throw new IllegalArgumentException();
if (initialCapacity == 0)
initialCapacity = 1;
this.loadFactor = loadFactor;
threshold = (int) (initialCapacity * loadFactor);
theEntrySet = new WeakEntrySet();
queue = new ReferenceQueue();
buckets = new WeakBucket[initialCapacity];
}
/**
* Construct a new WeakHashMap with the same mappings as the given map.
* The WeakHashMap has a default load factor of 0.75.
*
* @param m the map to copy
* @throws NullPointerException if m is null
* @since 1.3
*/
public WeakHashMap(Map m)
{
this(m.size(), DEFAULT_LOAD_FACTOR);
putAll(m);
}
/**
* Simply hashes a non-null Object to its array index.
* @param key the key to hash
* @return its slot number
*/
private int hash(Object key)
{
return Math.abs(key.hashCode() % buckets.length);
}
/**
* Cleans the reference queue. This will poll all references (which
* are WeakBuckets) from the queue and remove them from this map.
* This will not change modCount, even if it modifies the map. The
* iterators have to make sure that nothing bad happens. <br>
*
* Currently the iterator maintains a strong reference to the key, so
* that is no problem.
*/
// Package visible for use by nested classes.
void cleanQueue()
{
Object bucket = queue.poll();
while (bucket != null)
{
internalRemove((WeakBucket) bucket);
bucket = queue.poll();
}
}
/**
* Rehashes this hashtable. This will be called by the
* <code>add()</code> method if the size grows beyond the threshold.
* It will grow the bucket size at least by factor two and allocates
* new buckets.
*/
private void rehash()
{
WeakBucket[] oldBuckets = buckets;
int newsize = buckets.length * 2 + 1; // XXX should be prime.
threshold = (int) (newsize * loadFactor);
buckets = new WeakBucket[newsize];
// Now we have to insert the buckets again.
for (int i = 0; i < oldBuckets.length; i++)
{
WeakBucket bucket = oldBuckets[i];
WeakBucket nextBucket;
while (bucket != null)
{
nextBucket = bucket.next;
Object key = bucket.get();
if (key == null)
{
// This bucket should be removed; it is probably
// already on the reference queue. We don't insert it
// at all, and mark it as cleared.
bucket.slot = -1;
size--;
}
else
{
// Add this bucket to its new slot.
int slot = hash(key);
bucket.slot = slot;
bucket.next = buckets[slot];
buckets[slot] = bucket;
}
bucket = nextBucket;
}
}
}
/**
* Finds the entry corresponding to key. Since it returns an Entry
* it will also prevent the key from being removed under us.
* @param key the key, may be null
* @return The WeakBucket.WeakEntry or null, if the key wasn't found.
*/
private WeakBucket.WeakEntry internalGet(Object key)
{
if (key == null)
key = NULL_KEY;
int slot = hash(key);
WeakBucket bucket = buckets[slot];
while (bucket != null)
{
WeakBucket.WeakEntry entry = bucket.getEntry();
if (entry != null && key.equals(entry.key))
return entry;
bucket = bucket.next;
}
return null;
}
/**
* Adds a new key/value pair to the hash map.
* @param key the key. This mustn't exists in the map. It may be null.
* @param value the value.
*/
private void internalAdd(Object key, Object value)
{
if (key == null)
key = NULL_KEY;
int slot = hash(key);
WeakBucket bucket = new WeakBucket(key, queue, value, slot);
bucket.next = buckets[slot];
buckets[slot] = bucket;
size++;
}
/**
* 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).
* Package visible for use in nested classes.
*
* @param bucket the bucket to remove.
*/
void internalRemove(WeakBucket bucket)
{
int slot = bucket.slot;
if (slot == -1)
// This bucket was already removed.
return;
// Mark the bucket as removed. This is necessary, since the
// bucket may be enqueued later by the garbage collection, and
// internalRemove will be called a second time.
bucket.slot = -1;
if (buckets[slot] == bucket)
buckets[slot] = bucket.next;
else
{
WeakBucket prev = buckets[slot];
/* This may throw a NullPointerException. It shouldn't but if
* a race condition occurred (two threads removing the same
* bucket at the same time) it may happen. <br>
* But with race condition many much worse things may happen
* anyway.
*/
while (prev.next != bucket)
prev = prev.next;
prev.next = bucket.next;
}
size--;
}
/**
* Returns the size of this hash map. Note that the size() may shrink
* spontaneously, if the some of the keys were only weakly reachable.
* @return the number of entries in this hash map.
*/
public int size()
{
cleanQueue();
return size;
}
/**
* Tells if the map is empty. Note that the result may change
* spontanously, if all of the keys were only weakly reachable.
* @return true, iff the map is empty.
*/
public boolean isEmpty()
{
cleanQueue();
return size == 0;
}
/**
* Tells if the map contains the given key. Note that the result
* may change spontanously, if the key was only weakly
* reachable.
* @param key the key to look for
* @return true, iff the map contains an entry for the given key.
*/
public boolean containsKey(Object key)
{
cleanQueue();
return internalGet(key) != null;
}
/**
* Gets the value the key is mapped to.
* @return the value the key was mapped to. It returns null if
* the key wasn't in this map, or if the mapped value was
* explicitly set to null.
*/
public Object get(Object key)
{
cleanQueue();
WeakBucket.WeakEntry entry = internalGet(key);
return entry == null ? null : entry.getValue();
}
/**
* Adds a new key/value mapping to this map.
* @param key the key, may be null
* @param value the value, may be null
* @return the value the key was mapped to previously. It returns
* null if the key wasn't in this map, or if the mapped value
* was explicitly set to null.
*/
public Object put(Object key, Object value)
{
cleanQueue();
WeakBucket.WeakEntry entry = internalGet(key);
if (entry != null)
return entry.setValue(value);
modCount++;
if (size >= threshold)
rehash();
internalAdd(key, value);
return null;
}
/**
* Removes the key and the corresponding value from this map.
* @param key the key. This may be null.
* @return the value the key was mapped to previously. It returns
* null if the key wasn't in this map, or if the mapped value was
* explicitly set to null.
*/
public Object remove(Object key)
{
cleanQueue();
WeakBucket.WeakEntry entry = internalGet(key);
if (entry == null)
return null;
modCount++;
internalRemove(entry.getBucket());
return entry.getValue();
}
/**
* Returns a set representation of the entries in this map. This
* set will not have strong references to the keys, so they can be
* silently removed. The returned set has therefore the same
* strange behaviour (shrinking size(), disappearing entries) as
* this weak hash map.
* @return a set representation of the entries.
*/
public Set entrySet()
{
cleanQueue();
return theEntrySet;
}
/**
* Clears all entries from this map.
*/
public void clear()
{
super.clear();
}
/**
* Returns true if the map contains at least one key which points to
* the specified object as a value. Note that the result
* may change spontanously, if its key was only weakly reachable.
* @param value the value to search for
* @return true if it is found in the set.
*/
public boolean containsValue(Object value)
{
cleanQueue();
return super.containsValue(value);
}
/**
* Returns a set representation of the keys in this map. This
* set will not have strong references to the keys, so they can be
* silently removed. The returned set has therefore the same
* strange behaviour (shrinking size(), disappearing entries) as
* this weak hash map.
* @return a set representation of the keys.
*/
public Set keySet()
{
cleanQueue();
return super.keySet();
}
/**
* Puts all of the mappings from the given map into this one. If the
* key already exists in this map, its value is replaced.
* @param m the map to copy in
*/
public void putAll(Map m)
{
super.putAll(m);
}
/**
* Returns a collection representation of the values in this map. This
* collection will not have strong references to the keys, so mappings
* can be silently removed. The returned collection has therefore the same
* strange behaviour (shrinking size(), disappearing entries) as
* this weak hash map.
* @return a collection representation of the values.
*/
public Collection values()
{
cleanQueue();
return super.values();
}
} // class WeakHashMap
-630
View File
@@ -1,630 +0,0 @@
/* Attributes.java -- Represents attribute name/value pairs from a Manifest
Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.jar;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
/**
* Represents attribute name/value pairs from a Manifest as a Map.
* The names of an attribute are represented by the
* <code>Attributes.Name</code> class and should confirm to the restrictions
* described in that class. Note that the Map interface that Attributes
* implements allows you to put names and values into the attribute that don't
* follow these restriction (and are not really Atrribute.Names, but if you do
* that it might cause undefined behaviour later).
* <p>
* If you use the constants defined in the inner class Name then you can be
* sure that you always access the right attribute names. This makes
* manipulating the Attributes more or less type safe.
* <p>
* Most of the methods are wrappers to implement the Map interface. The really
* useful and often used methods are <code>getValue(Name)</code> and
* <code>getValue(String)</code>. If you actually want to set attributes you
* may want to use the <code>putValue(String, String)</code> method
* (sorry there is no public type safe <code>putValue(Name, String)</code>
* method).
*
* @see java.util.jar.Attributes.Name
* @author Mark Wielaard (mark@klomp.org)
*/
public class Attributes implements Cloneable, Map
{
// Fields
/**
* The map that holds all the attribute name/value pairs. In this
* implementation it is actually a Hashtable, but that can be different in
* other implementations.
*/
protected Map map;
// Inner class
/**
* Represents a name of a Manifest Attribute. Defines a couple of well
* know names for the general main attributes, stand alone application
* attributes, applet attributes, extension identification attributes,
* package versioning and sealing attributes, file contents attributes,
* bean objects attribute and signing attributes. See the
*
* <p>The characters of a Name must obey the following restrictions:</p>
*
* <ul>
* <li>Must contain at least one character</li>
* <li>The first character must be alphanumeric (a-z, A-Z, 0-9)</li>
* <li>All other characters must be alphanumeric, a '-' or a '_'</li>
* </ul>
*
* <p>When comparing Names (with <code>equals</code>) all characters are
* converted to lowercase. But you can get the original case sensitive
* string with the <code>toString()</code> method.</p>
*
* <p>Most important attributes have a constant defined in this
* class. Some other attributes used in Manifest files are:
* <ul>
* <li> "Created-By" - General main attribute, tool and version
* that created this Manifest file.</li>
* <li> "Java-Bean" - Bean objects attribute, whether the entry is a Bean.
* Value is either "true" or "false".</li>
* <li> "Magic" - Signing attribute, application specific signing attribute.
* Must be understood by the manifest parser when present to validate the
* jar (entry).</li>
* </ul>
*
* @since 1.2
* @author Mark Wielaard (mark@klomp.org)
*/
public static class Name
{
// General Main Attributes
/**
* General main attribute -
* the version of this Manifest file.
*/
public static final Name MANIFEST_VERSION = new Name("Manifest-Version");
/**
* General main attribute -
* the version of the jar file signature.
*/
public static final Name SIGNATURE_VERSION
= new Name("Signature-Version");
/**
* General main attribute -
* (relative) file paths of the libraries/classpaths that the Classes in
* this jar file depend on. Paths are separated by spaces.
*/
public static final Name CLASS_PATH = new Name("Class-Path");
/**
* Stand alone application attribute -
* the entry (without the .class ending) that is the main
* class of this jar file.
*/
public static final Name MAIN_CLASS = new Name("Main-Class");
/**
* Applet attribute -
* a list of extension libraries that the applet in this
* jar file depends on.
* For every named extension there should be some Attributes in the
* Manifest manifest file with the following Names:
* <ul>
* <li> &lt;extension&gt;-Extension-Name:
* unique name of the extension</li>
* <li> &lt;extension&gt;-Specification-Version:
* minimum specification version</li>
* <li> &lt;extension&gt;-Implementation-Version:
* minimum implementation version</li>
* <li> &lt;extension&gt;-Implementation-Vendor-Id:
* unique id of implementation vendor</li>
* <li> &lt;extension&gt;-Implementation-URL:
* where the latest version of the extension library can be found</li>
* </ul>
*/
public static final Name EXTENSION_LIST = new Name("Extension-List");
/**
* Extension identification attribute -
* the name if the extension library contained in the jar.
*/
public static final Name EXTENSION_NAME = new Name("Extension-Name");
/**
* Extension identification attribute -
* synonym for <code>EXTENSTION_NAME</code>.
*/
public static final Name EXTENSION_INSTALLATION = EXTENSION_NAME;
// Package versioning and sealing attributes
/**
* Package versioning -
* name of extension library contained in this jar.
*/
public static final Name IMPLEMENTATION_TITLE
= new Name("Implementation-Title");
/**
* Package versioning -
* version of the extension library contained in this jar.
*/
public static final Name IMPLEMENTATION_VERSION
= new Name("Implementation-Version");
/**
* Package versioning -
* name of extension library creator contained in this jar.
*/
public static final Name IMPLEMENTATION_VENDOR
= new Name("Implementation-Vendor");
/**
* Package versioning -
* unique id of extension library creator.
*/
public static final Name IMPLEMENTATION_VENDOR_ID
= new Name("Implementation-Vendor-Id");
/**
* Package versioning -
* location where this implementation can be downloaded.
*/
public static final Name IMPLEMENTATION_URL
= new Name("Implementation-URL");
/**
* Package versioning -
* title of the specification contained in this jar.
*/
public static final Name SPECIFICATION_TITLE
= new Name("Specification-Title");
/**
* Package versioning -
* version of the specification contained in this jar.
*/
public static final Name SPECIFICATION_VERSION
= new Name("Specification-Version");
/**
* Package versioning -
* organisation that maintains the specification contains in this
* jar.
*/
public static final Name SPECIFICATION_VENDOR
= new Name("Specification-Vendor");
/**
* Package sealing -
* whether (all) package(s) is(/are) sealed. Value is either "true"
* or "false".
*/
public static final Name SEALED = new Name("Sealed");
/**
* File contents attribute -
* Mime type and subtype for the jar entry.
*/
public static final Name CONTENT_TYPE = new Name("Content-Type");
/** The (lowercase) String representation of this Name */
private final String name;
/** The original String given to the constructor */
private final String origName;
// Constructor
/**
* Creates a new Name from the given String.
* Throws an IllegalArgumentException if the given String is empty or
* contains any illegal Name characters.
*
* @param name the name of the new Name
* @exception IllegalArgumentException if name isn't a valid String
* representation of a Name
* @exception NullPointerException if name is null
*/
public Name(String name) throws IllegalArgumentException,
NullPointerException
{
// name must not be null
// this will throw a NullPointerException if it is
char chars[] = name.toCharArray();
// there must be at least one character
if (chars.length == 0)
throw new
IllegalArgumentException
("There must be at least one character in a name");
// first character must be alphanum
char c = chars[0];
if (!((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')))
throw new
IllegalArgumentException("First character must be alphanum");
// all other characters must be alphanums, '-' or '_'
for (int i = 1; i < chars.length; i++)
{
c = chars[i];
if (!((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') || (c == '-') || (c == '_')))
throw new
IllegalArgumentException
("Characters must be alphanums, '-' or '_'");
}
// Still here? Then convert to lower case and be done.
// Store the original name for toString();
this.origName = name;
this.name = name.toLowerCase();
}
/**
* Returns the hash code of the (lowercase) String representation of
* this Name.
*/
public int hashCode()
{
return name.hashCode();
}
/**
* Checks if another object is equal to this Name object.
* Another object is equal to this Name object if it is an instance of
* Name and the (lowercase) string representation of the name is equal.
*/
public boolean equals(Object o)
{
// Quick and dirty check
if (name == o)
return true;
try
{
// Note that the constructor already converts the strings to
// lowercase.
String otherName = ((Name) o).name;
return name.equals(otherName);
}
catch (ClassCastException cce)
{
return false;
}
catch (NullPointerException npe)
{
return false;
}
}
/**
* Returns the string representation of this Name as given to the
* constructor (not neccesarily the lower case representation).
*/
public String toString()
{
return origName;
}
}
// Constructors
/**
* Creates an empty Attributes map.
*/
public Attributes()
{
map = new Hashtable();
}
/**
* Creates an empty Attributes map with the given initial size.
* @param size the initial size of the underlying map
*/
public Attributes(int size)
{
map = new Hashtable(size);
}
/**
* Creates an Attributes map with the initial values taken from another
* Attributes map.
* @param attr Attributes map to take the initial values from
*/
public Attributes(Attributes attr)
{
map = new Hashtable(attr.map);
}
// Methods
/**
* Gets the value of an attribute name given as a String.
*
* @param name a String describing the Name to look for
* @return the value gotten from the map of null when not found
*/
public String getValue(String name)
{
return (String) get(new Name(name));
}
/**
* Gets the value of the given attribute name.
*
* @param name the Name to look for
* @return the value gotten from the map of null when not found
*/
public String getValue(Name name)
{
return (String) get(name);
}
/**
* Stores an attribute name (represented by a String) and value in this
* Attributes map.
* When the (case insensitive string) name already exists the value is
* replaced and the old value is returned.
*
* @param name a (case insensitive) String representation of the attribite
* name to add/replace
* @param value the (new) value of the attribute name
* @returns the old value of the attribute name or null if it didn't exist
* yet
*/
public String putValue(String name, String value)
{
return putValue(new Name(name), value);
}
/**
* Stores an attribute name (represented by a String) and value in this
* Attributes map.
* When the name already exists the value is replaced and the old value
* is returned.
* <p>
* I don't know why there is no public method with this signature. I think
* there should be one.
*
* @param name the attribite name to add/replace
* @param value the (new) value of the attribute name
* @returns the old value of the attribute name or null if it didn't exist
* yet
*/
String putValue(Name name, String value)
{
return (String) put(name, value);
}
// Methods from Cloneable interface
/**
* Return a clone of this attribute map.
*/
public Object clone()
{
return new Attributes(this);
}
// Methods from Map interface
/**
* Removes all attributes.
*/
public void clear()
{
map.clear();
}
/**
* Checks to see if there is an attribute with the specified name.
* XXX - what if the object is a String?
*
* @param attrName the name of the attribute to check
* @return true if there is an attribute with the specified name, false
* otherwise
*/
public boolean containsKey(Object attrName)
{
return map.containsKey(attrName);
}
/**
* Checks to see if there is an attribute name with the specified value.
*
* @param attrValue the value of a attribute to check
* @return true if there is an attribute name with the specified value,
* false otherwise
*/
public boolean containsValue(Object attrValue)
{
return map.containsValue(attrValue);
}
/**
* Gives a Set of attribute name and values pairs as MapEntries.
* @see java.util.Map.Entry
* @see java.util.Map#entrySet()
*
* @return a set of attribute name value pairs
*/
public Set entrySet()
{
return map.entrySet();
}
/**
* Checks to see if two Attributes are equal. The supplied object must be
* a real instance of Attributes and contain the same attribute name/value
* pairs.
*
* @param o another Attribute object which should be checked for equality
* @return true if the object is an instance of Attributes and contains the
* same name/value pairs, false otherwise
*/
public boolean equals(Object o)
{
// quick and dirty check
if (this == o)
return true;
try
{
return map.equals(((Attributes) o).map);
}
catch (ClassCastException cce)
{
return false;
}
catch (NullPointerException npe)
{
return false;
}
}
/**
* Gets the value of a specified attribute name.
* XXX - what if the object is a String?
*
* @param attrName the name of the attribute we want the value of
* @return the value of the specified attribute name or null when there is
* no such attribute name
*/
public Object get(Object attrName)
{
return map.get(attrName);
}
/**
* Returns the hashcode of the attribute name/value map.
*/
public int hashCode()
{
return map.hashCode();
}
/**
* Returns true if there are no attributes set, false otherwise.
*/
public boolean isEmpty()
{
return map.isEmpty();
}
/**
* Gives a Set of all the values of defined attribute names.
*/
public Set keySet()
{
return map.keySet();
}
/**
* Adds or replaces a attribute name/value pair.
* XXX - What if the name is a string? What if the name is neither a Name
* nor a String? What if the value is not a string?
*
* @param name the name of the attribute
* @param value the (new) value of the attribute
* @return the old value of the attribute or null when there was no old
* attribute with this name
*/
public Object put(Object name, Object value)
{
return map.put(name, value);
}
/**
* Adds or replaces all attribute name/value pairs from another
* Attributes object to this one. The supplied Map must be an instance of
* Attributes.
*
* @param attr the Attributes object to merge with this one
* @exception ClassCastException if the supplied map is not an instance of
* Attributes
*/
public void putAll(Map attr)
{
if (!(attr instanceof Attributes))
{
throw new
ClassCastException("Supplied Map is not an instance of Attributes");
}
map.putAll(attr);
}
/**
* Remove a attribute name/value pair.
* XXX - What if the name is a String?
*
* @param name the name of the attribute name/value pair to remove
* @return the old value of the attribute or null if the attribute didn't
* exist
*/
public Object remove(Object name)
{
return map.remove(name);
}
/**
* Returns the number of defined attribute name/value pairs.
*/
public int size()
{
return map.size();
}
/**
* Returns all the values of the defined attribute name/value pairs as a
* Collection.
*/
public Collection values()
{
return map.values();
}
}
-165
View File
@@ -1,165 +0,0 @@
/* JarEntry.java - Represents an entry in a jar file
Copyright (C) 2000 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.jar;
import java.io.IOException;
import java.security.cert.Certificate;
import java.util.zip.ZipEntry;
/**
* Extension to a ZipEntry that contains manifest attributes and certificates.
* Both the Atrributes and the Certificates can be null when not set.
* Note that the <code>getCertificates()</code> method only returns a
* valid value after all of the data of the entry has been read.
* <p>
* There are no public methods to set the attributes or certificate of an
* Entru. Only JarEntries created by the classes in <code>java.util.jar</code>
* will have these properties set.
*
* @since 1.2
* @author Mark Wielaard (mark@klomp.org)
*/
public class JarEntry extends ZipEntry
{
// (Package local) fields
Attributes attr;
Certificate certs[];
// Constructors
/**
* Creates a new JarEntry with the specified name and no attributes or
* or certificates. Calls <code>super(name)</code> so all other (zip)entry
* fields are null or -1.
*
* @param name the name of the new jar entry
* @exception NullPointerException when the supplied name is null
* @exception IllegalArgumentException when the supplied name is longer
* than 65535 bytes
*/
public JarEntry(String name) throws NullPointerException,
IllegalArgumentException
{
super(name);
attr = null;
certs = null;
}
/**
* Creates a new JarEntry with the specified ZipEntry as template for
* all properties of the entry. Both attributes and certificates will be
* null.
*
* @param entry the ZipEntry whose fields should be copied
*/
public JarEntry(ZipEntry entry)
{
super(entry);
attr = null;
certs = null;
}
/**
* Creates a new JarEntry with the specified JarEntry as template for
* all properties of the entry.
*
* @param entry the jarEntry whose fields should be copied
*/
public JarEntry(JarEntry entry)
{
super(entry);
try
{
attr = entry.getAttributes();
}
catch (IOException _)
{
}
certs = entry.getCertificates();
}
// Methods
/**
* Returns a copy of the Attributes set for this entry.
* When no Attributes are set in the manifest null is returned.
*
* @return a copy of the Attributes set for this entry
* @exception IOException This will never be thrown. It is here for
* binary compatibility.
*/
public Attributes getAttributes() throws IOException
{
if (attr != null)
{
return (Attributes) attr.clone();
}
else
{
return null;
}
}
/**
* Returns a copy of the certificates set for this entry.
* When no certificates are set or when not all data of this entry has
* been read null is returned.
* <p>
* To make sure that this call returns a valid value you must read all
* data from the JarInputStream for this entry.
* When you don't need the data for an entry but want to know the
* certificates that are set for the entry then you can skip all data by
* calling <code>skip(entry.getSize())</code> on the JarInputStream for
* the entry.
*
* @return a copy of the certificates set for this entry
*/
public Certificate[] getCertificates()
{
if (certs != null)
{
return (Certificate[])certs.clone();
}
else
{
return null;
}
}
}
-77
View File
@@ -1,77 +0,0 @@
/* JarException.java -- thrown to indicate an problem with a jar file
Copyright (C) 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.jar;
import java.util.zip.ZipException;
/**
* This exception is thrown to indicate an problem with a jar file.
* Note that none of the methods in the java.util.jar package actually declare
* to throw this exception, most just declare that they throw an IOException
* which is super class of JarException.
*
* @author Mark Wielaard (mark@klomp.org)
* @since 1.2
*/
public class JarException extends ZipException
{
/**
* Compatible with JDK 1.2+.
*/
private static final long serialVersionUID = 7159778400963954473L;
/**
* Create a new JarException without a descriptive error message.
*/
public JarException()
{
}
/**
* Create a new JarException with a descriptive error message indicating
* what went wrong. This message can later be retrieved by calling the
* <code>getMessage()</code> method.
*
* @param message The descriptive error message
* @see #getMessage()
*/
public JarException(String message)
{
super(message);
}
}
File diff suppressed because it is too large Load Diff
-200
View File
@@ -1,200 +0,0 @@
/* JarInputStream.java - InputStream for reading jar files
Copyright (C) 2000, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.jar;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* InputStream for reading jar files.
* XXX - verification of the signatures in the Manifest file is not yet
* implemented.
*
* @since 1.2
* @author Mark Wielaard (mark@klomp.org)
*/
public class JarInputStream extends ZipInputStream
{
// Fields
/** The manifest for this file or null when there was no manifest. */
private Manifest manifest;
/** The first real JarEntry for this file. Used by readManifest() to store
an entry that isn't the manifest but that should be returned by
getNextEntry next time it is called. Null when no firstEntry was read
while searching for the manifest entry, or when it has already been
returned by getNextEntry(). */
private JarEntry firstEntry;
// Constructors
/**
* Creates a new JarInputStream and tries to read the manifest.
* If such a manifest is present the JarInputStream tries to verify all
* the entry signatures while reading.
*
* @param in InputStream to read the jar from
* @exception IOException when an error occurs when opening or reading
*/
public JarInputStream(InputStream in) throws IOException
{
this(in, true);
}
/**
* Creates a new JarInputStream and tries to read the manifest.
* If such a manifest is present and verify is true, the JarInputStream
* tries to verify all the entry signatures while reading.
*
* @param in InputStream to read the jar from
* @param verify whether or not to verify the manifest entries
* @exception IOException when an error occurs when opening or reading
*/
public JarInputStream(InputStream in, boolean verify) throws IOException
{
super(in);
readManifest(verify);
}
// Methods
/**
* Set the manifest if found. Skips all entries that start with "META-INF/"
*
* @param verify when true (and a Manifest is found) checks the Manifest,
* when false no check is performed
* @exception IOException if an error occurs while reading
*/
private void readManifest(boolean verify) throws IOException
{
firstEntry = (JarEntry) super.getNextEntry();
while ((firstEntry != null) &&
firstEntry.getName().startsWith("META-INF/"))
{
if (firstEntry.getName().equals(JarFile.MANIFEST_NAME))
{
manifest = new Manifest(this);
}
firstEntry = (JarEntry) super.getNextEntry();
}
if (verify)
{
// XXX
}
}
/**
* Creates a JarEntry for a particular name and consults the manifest
* for the Attributes of the entry.
* Used by <code>ZipEntry.getNextEntry()</code>
*
* @param name the name of the new entry
*/
protected ZipEntry createZipEntry(String name)
{
ZipEntry zipEntry = super.createZipEntry(name);
JarEntry jarEntry = new JarEntry(zipEntry);
if (manifest != null)
{
jarEntry.attr = manifest.getAttributes(name);
}
return jarEntry;
}
/**
* Returns the Manifest for the jar file or null if there was no Manifest.
*/
public Manifest getManifest()
{
return manifest;
}
/**
* Returns the next entry or null when there are no more entries.
* Does actually return a JarEntry, if you don't want to cast it yourself
* use <code>getNextJarEntry()</code>. Does not return any entries found
* at the beginning of the ZipFile that are special
* (those that start with "META-INF/").
*
* @exception IOException if an IO error occurs when reading the entry
*/
public ZipEntry getNextEntry() throws IOException
{
ZipEntry entry;
if (firstEntry != null)
{
entry = firstEntry;
firstEntry = null;
}
else
{
entry = super.getNextEntry();
}
return entry;
}
/**
* Returns the next jar entry or null when there are no more entries.
*
* @exception IOException if an IO error occurs when reading the entry
*/
public JarEntry getNextJarEntry() throws IOException
{
return (JarEntry) getNextEntry();
}
/**
* XXX
*
* @param buf XXX
* @param off XXX
* @param len XXX
* @return XXX
* @exception IOException XXX
*/
public int read(byte[]buf, int off, int len) throws IOException
{
// XXX if (verify) {}
return super.read(buf, off, len);
}
}
-113
View File
@@ -1,113 +0,0 @@
/* JarOutputStream.java - OutputStream for writing jar files
Copyright (C) 2000, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.jar;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* OutputStream for writing jar files.
* A special ZipOutputStream that can take JarEntries and can have a optional
* Manifest as first entry.
*
* @author Mark Wielaard (mark@klomp.org)
*/
public class JarOutputStream extends ZipOutputStream
{
// Constructors
/**
* Creates a new JarOutputStream without a manifest entry.
*
* @param out the stream to create the new jar on
* @exception IOException if something unexpected happend
*/
public JarOutputStream(OutputStream out) throws IOException
{
this(out, null);
}
/**
* Creates a new JarOutputStream with a manifest entry.
* The manifest will be the first entry in the jar.
*
* @param out the stream to create the new jar on
* @param man the manifest that should be put in the jar file or null
* for no manifest entry
* @exception IOException if something unexpected happend
*/
public JarOutputStream(OutputStream out, Manifest man) throws IOException
{
super(out);
if (man != null)
writeManifest(man);
}
// Methods
/**
* Writes the manifest to a new JarEntry in this JarOutputStream with as
* name JarFile.MANIFEST_NAME.
*
* @param manifest the non null manifest to be written
* @exception IOException if something unexpected happend
*/
private void writeManifest(Manifest manifest) throws IOException
{
// Create a new Jar Entry for the Manifest
JarEntry entry = new JarEntry(JarFile.MANIFEST_NAME);
putNextEntry(entry);
manifest.write(this);
closeEntry();
}
/**
* Prepares the JarOutputStream for writing the next entry.
* This implementation just calls <code>super.putNextEntre()</code>.
*
* @param entry The information for the next entry
* @exception IOException when some unexpected I/O exception occurred
*/
public void putNextEntry(ZipEntry entry) throws IOException
{
super.putNextEntry(entry); // XXX
}
}
-472
View File
@@ -1,472 +0,0 @@
/* Manifest.java -- Reads, writes and manipulaties jar manifest files
Copyright (C) 2000, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.jar;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
/**
* Reads, writes and manipulaties jar manifest files.
* XXX
*
* @since 1.2
* @author Mark Wielaard (mark@klomp.org)
*/
public class Manifest implements Cloneable
{
// Fields
/** The main attributes of the manifest (jar file). */
private final Attributes mainAttr;
/** A map of atrributes for all entries described in this Manifest. */
private final Map entries;
// Constructors
/**
* Creates a new empty Manifest.
*/
public Manifest()
{
mainAttr = new Attributes();
entries = new Hashtable();
}
/**
* Creates a Manifest from the supplied input stream.
*
* @see read(Inputstream)
* @see write(OutputStream)
*
* @param InputStream the input stream to read the manifest from
* @exception IOException when an i/o exception occurs or the input stream
* does not describe a valid manifest
*/
public Manifest(InputStream in) throws IOException
{
this();
read(in);
}
/**
* Creates a Manifest from another Manifest.
* Makes a deep copy of the main attributes, but a shallow copy of
* the other entries. This means that you can freely add, change or remove
* the main attributes or the entries of the new manifest without effecting
* the original manifest, but adding, changing or removing attributes from
* a particular entry also changes the attributes of that entry in the
* original manifest.
*
* @see clone()
* @param man the Manifest to copy from
*/
public Manifest(Manifest man)
{
mainAttr = new Attributes(man.getMainAttributes());
entries = new Hashtable(man.getEntries());
}
// Methods
/**
* Gets the main attributes of this Manifest.
*/
public Attributes getMainAttributes()
{
return mainAttr;
}
/**
* Gets a map of entry Strings to Attributes for all the entries described
* in this manifest. Adding, changing or removing from this entries map
* changes the entries of this manifest.
*/
public Map getEntries()
{
return entries;
}
/**
* Returns the Attributes associated with the Entry.
* <p>
* Implemented as:
* <code>return (Attributes)getEntries().get(entryName)</code>
*
* @param entryName the name of the entry to look up
* @return the attributes associated with the entry or null when none
*/
public Attributes getAttributes(String entryName)
{
return (Attributes) getEntries().get(entryName);
}
/**
* Clears the main attributes and removes all the entries from the
* manifest.
*/
public void clear()
{
mainAttr.clear();
entries.clear();
}
/**
* XXX
*/
public void read(InputStream in) throws IOException
{
BufferedReader br =
new BufferedReader(new InputStreamReader(in, "8859_1"));
read_main_section(getMainAttributes(), br);
read_individual_sections(getEntries(), br);
}
// Private Static methods for reading the Manifest file from BufferedReader
private static void read_main_section(Attributes attr,
BufferedReader br) throws IOException
{
// According to the spec we should actually call read_version_info() here.
read_attributes(attr, br);
// Explicitly set Manifest-Version attribute if not set in Main
// attributes of Manifest.
if (attr.getValue(Attributes.Name.MANIFEST_VERSION) == null)
attr.putValue(Attributes.Name.MANIFEST_VERSION, "0.0");
}
/**
* Pedantic method that requires the next attribute in the Manifest to be
* the "Manifest-Version". This follows the Manifest spec closely but
* reject some jar Manifest files out in the wild.
*/
private static void read_version_info(Attributes attr,
BufferedReader br) throws IOException
{
String version_header = Attributes.Name.MANIFEST_VERSION.toString();
try
{
String value = expect_header(version_header, br);
attr.putValue(Attributes.Name.MANIFEST_VERSION, value);
}
catch (IOException ioe)
{
throw new JarException("Manifest should start with a " +
version_header + ": " + ioe.getMessage());
}
}
private static String expect_header(String header, BufferedReader br)
throws IOException
{
String s = br.readLine();
if (s == null)
{
throw new JarException("unexpected end of file");
}
return expect_header(header, br, s);
}
private static String expect_header(String header, BufferedReader br,
String s) throws IOException
{
try
{
String name = s.substring(0, header.length() + 1);
if (name.equalsIgnoreCase(header + ":"))
{
String value_start = s.substring(header.length() + 2);
return read_header_value(value_start, br);
}
}
catch (IndexOutOfBoundsException iobe)
{
}
// If we arrive here, something went wrong
throw new JarException("unexpected '" + s + "'");
}
private static String read_header_value(String s, BufferedReader br)
throws IOException
{
boolean try_next = true;
while (try_next)
{
// Lets see if there is something on the next line
br.mark(1);
if (br.read() == ' ')
{
s += br.readLine();
}
else
{
br.reset();
try_next = false;
}
}
return s;
}
private static void read_attributes(Attributes attr,
BufferedReader br) throws IOException
{
String s = br.readLine();
while (s != null && (!s.equals("")))
{
read_attribute(attr, s, br);
s = br.readLine();
}
}
private static void read_attribute(Attributes attr, String s,
BufferedReader br) throws IOException
{
try
{
int colon = s.indexOf(": ");
String name = s.substring(0, colon);
String value_start = s.substring(colon + 2);
String value = read_header_value(value_start, br);
attr.putValue(name, value);
}
catch (IndexOutOfBoundsException iobe)
{
throw new JarException("Manifest contains a bad header: " + s);
}
}
private static void read_individual_sections(Map entries,
BufferedReader br) throws
IOException
{
String s = br.readLine();
while (s != null && (!s.equals("")))
{
Attributes attr = read_section_name(s, br, entries);
read_attributes(attr, br);
s = br.readLine();
}
}
private static Attributes read_section_name(String s, BufferedReader br,
Map entries) throws JarException
{
try
{
String name = expect_header("Name", br, s);
Attributes attr = new Attributes();
entries.put(name, attr);
return attr;
}
catch (IOException ioe)
{
throw new JarException
("Section should start with a Name header: " + ioe.getMessage());
}
}
/**
* XXX
*/
public void write(OutputStream out) throws IOException
{
PrintWriter pw =
new PrintWriter(new
BufferedWriter(new OutputStreamWriter(out, "8859_1")));
write_main_section(getMainAttributes(), pw);
pw.println();
write_individual_sections(getEntries(), pw);
if (pw.checkError())
{
throw new JarException("Error while writing manifest");
}
}
// Private Static functions for writing the Manifest file to a PrintWriter
private static void write_main_section(Attributes attr,
PrintWriter pw) throws JarException
{
write_version_info(attr, pw);
write_main_attributes(attr, pw);
}
private static void write_version_info(Attributes attr, PrintWriter pw)
{
// First check if there is already a version attribute set
String version = attr.getValue(Attributes.Name.MANIFEST_VERSION);
if (version == null)
{
version = "1.0";
}
write_header(Attributes.Name.MANIFEST_VERSION.toString(), version, pw);
}
private static void write_header(String name, String value, PrintWriter pw)
{
pw.print(name + ": ");
int last = 68 - name.length();
if (last > value.length())
{
pw.println(value);
}
else
{
pw.println(value.substring(0, last));
}
while (last < value.length())
{
pw.print(" ");
int end = (last + 69);
if (end > value.length())
{
pw.println(value.substring(last));
}
else
{
pw.println(value.substring(last, end));
}
last = end;
}
}
private static void write_main_attributes(Attributes attr, PrintWriter pw)
throws JarException
{
Iterator it = attr.entrySet().iterator();
while (it.hasNext())
{
Map.Entry entry = (Map.Entry) it.next();
// Don't print the manifest version again
if (!Attributes.Name.MANIFEST_VERSION.equals(entry.getKey()))
{
write_attribute_entry(entry, pw);
}
}
}
private static void write_attribute_entry(Map.Entry entry, PrintWriter pw)
throws JarException
{
String name = entry.getKey().toString();
String value = entry.getValue().toString();
if (name.equalsIgnoreCase("Name"))
{
throw new JarException("Attributes cannot be called 'Name'");
}
if (name.startsWith("From"))
{
throw new
JarException("Header cannot start with the four letters 'From'" +
name);
}
write_header(name, value, pw);
}
private static void write_individual_sections(Map entries, PrintWriter pw)
throws JarException
{
Iterator it = entries.entrySet().iterator();
while (it.hasNext())
{
Map.Entry entry = (Map.Entry) it.next();
write_header("Name", entry.getKey().toString(), pw);
write_entry_attributes((Attributes) entry.getValue(), pw);
pw.println();
}
}
private static void write_entry_attributes(Attributes attr, PrintWriter pw)
throws JarException
{
Iterator it = attr.entrySet().iterator();
while (it.hasNext())
{
Map.Entry entry = (Map.Entry) it.next();
write_attribute_entry(entry, pw);
}
}
/**
* Makes a deep copy of the main attributes, but a shallow copy of
* the other entries. This means that you can freely add, change or remove
* the main attributes or the entries of the new manifest without effecting
* the original manifest, but adding, changing or removing attributes from
* a particular entry also changes the attributes of that entry in the
* original manifest. Calls <CODE>new Manifest(this)</CODE>.
*/
public Object clone()
{
return new Manifest(this);
}
/**
* Checks if another object is equal to this Manifest object.
* Another Object is equal to this Manifest object if it is an instance of
* Manifest and the main attributes and the entries of the other manifest
* are equal to this one.
*/
public boolean equals(Object o)
{
return (o instanceof Manifest) &&
(mainAttr.equals(((Manifest) o).mainAttr)) &&
(entries.equals(((Manifest) o).entries));
}
/**
* Calculates the hash code of the manifest. Implemented by a xor of the
* hash code of the main attributes with the hash code of the entries map.
*/
public int hashCode()
{
return mainAttr.hashCode() ^ entries.hashCode();
}
}
@@ -1,125 +0,0 @@
/* ConsoleHandler.java -- a class for publishing log messages to System.err
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
/**
* A <code>ConsoleHandler</code> publishes log records to
* <code>System.err</code>.
*
* <p><strong>Configuration:</strong> Values of the subsequent
* <code>LogManager</code> properties are taken into consideration
* when a <code>ConsoleHandler</code> is initialized.
* If a property is not defined, or if it has an invalid
* value, a default is taken without an exception being thrown.
*
* <ul>
*
* <li><code>java.util.logging.ConsoleHandler.level</code> - specifies
* the initial severity level threshold. Default value:
* <code>Level.INFO</code>.</li>
*
* <li><code>java.util.logging.ConsoleHandler.filter</code> - specifies
* the name of a Filter class. Default value: No Filter.</li>
*
* <li><code>java.util.logging.ConsoleHandler.formatter</code> - specifies
* the name of a Formatter class. Default value:
* <code>java.util.logging.SimpleFormatter</code>.</li>
*
* <li><code>java.util.logging.ConsoleHandler.encoding</code> - specifies
* the name of the character encoding. Default value:
* the default platform encoding.</li>
*
* </ul>
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class ConsoleHandler
extends StreamHandler
{
/**
* Constructs a <code>StreamHandler</code> that publishes
* log records to <code>System.err</code>. The initial
* configuration is determined by the <code>LogManager</code>
* properties described above.
*/
public ConsoleHandler()
{
super(System.err, "java.util.logging.ConsoleHandler", Level.INFO,
/* formatter */ null, SimpleFormatter.class);
}
/**
* Forces any data that may have been buffered to the underlying
* output device, but does <i>not</i> close <code>System.err</code>.
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>ConsoleHandler</code> will be informed, but the caller
* of this method will not receive an exception.
*/
public void close()
{
flush();
}
/**
* Publishes a <code>LogRecord</code> to the console, provided the
* record passes all tests for being loggable.
*
* <p>Most applications do not need to call this method directly.
* Instead, they will use use a <code>Logger</code>, which will
* create LogRecords and distribute them to registered handlers.
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>SocketHandler</code> will be informed, but the caller
* of this method will not receive an exception.
*
* <p>The GNU implementation of <code>ConsoleHandler.publish</code>
* calls flush() for every request to publish a record, so
* they appear immediately on the console.
*
* @param record the log event to be published.
*/
public void publish(LogRecord record)
{
super.publish(record);
flush();
}
}
-194
View File
@@ -1,194 +0,0 @@
/* ErrorManager.java --
A class for dealing with errors that a Handler encounters
during logging
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
/**
* An <code>ErrorManager</code> deals with errors that a <code>Handler</code>
* encounters while logging.
*
* @see Handler#setErrorManager(ErrorManager)
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class ErrorManager
{
/* The values have been taken from Sun's public J2SE 1.4 API
* documentation.
* See http://java.sun.com/j2se/1.4/docs/api/constant-values.html
*/
/**
* Indicates that there was a failure that does not readily
* fall into any of the other categories.
*/
public static final int GENERIC_FAILURE = 0;
/**
* Indicates that there was a problem upon writing to
* an output stream.
*/
public static final int WRITE_FAILURE = 1;
/**
* Indicates that there was a problem upon flushing
* an output stream.
*/
public static final int FLUSH_FAILURE = 2;
/**
* Indicates that there was a problem upon closing
* an output stream.
*/
public static final int CLOSE_FAILURE = 3;
/**
* Indicates that there was a problem upon opening
* an output stream.
*/
public static final int OPEN_FAILURE = 4;
/**
* Indicates that there was a problem upon formatting
* the message of a log record.
*/
public static final int FORMAT_FAILURE = 5;
/**
* Indicates whether the {@link #error} method of this ErrorManager
* has ever been used.
*
* Declared volatile in order to correctly support the
* double-checked locking idiom (once the revised Java Memory Model
* gets adopted); see Classpath bug #2944.
*/
private volatile boolean everUsed = false;
public ErrorManager()
{
}
/**
* Reports an error that occured upon logging. The default implementation
* emits the very first error to System.err, ignoring subsequent errors.
*
* @param message a message describing the error, or <code>null</code> if
* there is no suitable description.
*
* @param ex an exception, or <code>null</code> if the error is not
* related to an exception.
*
* @param errorCode one of the defined error codes, for example
* <code>ErrorManager.CLOSE_FAILURE</code>.
*/
public void error(String message, Exception ex, int errorCode)
{
if (everUsed)
return;
synchronized (this)
{
/* The double check is intentional. If the first check was
* omitted, the monitor would have to be entered every time
* error() method was called. If the second check was
* omitted, the code below could be executed by multiple
* threads simultaneously.
*
* This is the 'double-checked locking' idiom, which is broken
* with the current version of the Java memory model. However,
* we assume that JVMs will have adopted a revised version of
* the Java Memory Model by the time GNU Classpath gains
* widespread acceptance. See Classpath bug #2944.
*/
if (everUsed)
return;
everUsed = true;
}
String codeMsg;
switch (errorCode)
{
case GENERIC_FAILURE:
codeMsg = "GENERIC_FAILURE";
break;
case WRITE_FAILURE:
codeMsg = "WRITE_FAILURE";
break;
case FLUSH_FAILURE:
codeMsg = "FLUSH_FAILURE";
break;
case CLOSE_FAILURE:
codeMsg = "CLOSE_FAILURE";
break;
case OPEN_FAILURE:
codeMsg = "OPEN_FAILURE";
break;
case FORMAT_FAILURE:
codeMsg = "FORMAT_FAILURE";
break;
default:
codeMsg = String.valueOf(errorCode);
break;
}
System.err.println("Error upon logging: " + codeMsg);
if ((message != null) && (message.length() > 0))
System.err.println(message);
if (ex != null)
ex.printStackTrace();
}
}
-506
View File
@@ -1,506 +0,0 @@
/* FileHandler.java -- a class for publishing log messages to log files
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* A <code>FileHandler</code> publishes log records to a set of log
* files. A maximum file size can be specified; as soon as a log file
* reaches the size limit, it is closed and the next file in the set
* is taken.
*
* <p><strong>Configuration:</strong> Values of the subsequent
* <code>LogManager</code> properties are taken into consideration
* when a <code>FileHandler</code> is initialized. If a property is
* not defined, or if it has an invalid value, a default is taken
* without an exception being thrown.
*
* <ul>
*
* <li><code>java.util.FileHandler.level</code> - specifies
* the initial severity level threshold. Default value:
* <code>Level.ALL</code>.</li>
*
* <li><code>java.util.FileHandler.filter</code> - specifies
* the name of a Filter class. Default value: No Filter.</li>
*
* <li><code>java.util.FileHandler.formatter</code> - specifies
* the name of a Formatter class. Default value:
* <code>java.util.logging.XMLFormatter</code>.</li>
*
* <li><code>java.util.FileHandler.encoding</code> - specifies
* the name of the character encoding. Default value:
* the default platform encoding.</li>
*
* <li><code>java.util.FileHandler.limit</code> - specifies the number
* of bytes a log file is approximately allowed to reach before it
* is closed and the handler switches to the next file in the
* rotating set. A value of zero means that files can grow
* without limit. Default value: 0 (unlimited growth).</li>
*
* <li><code>java.util.FileHandler.count</code> - specifies the number
* of log files through which this handler cycles. Default value:
* 1.</li>
*
* <li><code>java.util.FileHandler.pattern</code> - specifies a
* pattern for the location and name of the produced log files.
* See the section on <a href="#filePatterns">file name
* patterns</a> for details. Default value:
* <code>"%h/java%u.log"</code>.</li>
*
* <li><code>java.util.FileHandler.append</code> - specifies
* whether the handler will append log records to existing
* files, or whether the handler will clear log files
* upon switching to them. Default value: <code>false</code>,
* indicating that files will be cleared.</li>
*
* </ul>
*
* <p><a name="filePatterns"><strong>File Name Patterns:</strong></a>
* The name and location and log files are specified with pattern
* strings. The handler will replace the following character sequences
* when opening log files:
*
* <p><ul>
* <li><code>/</code> - replaced by the platform-specific path name
* separator. This value is taken from the system property
* <code>file.separator</code>.</li>
*
* <li><code>%t</code> - replaced by the platform-specific location of
* the directory intended for temporary files. This value is
* taken from the system property <code>java.io.tmpdir</code>.</li>
*
* <li><code>%h</code> - replaced by the location of the home
* directory of the current user. This value is taken from the
* system property <code>file.separator</code>.</li>
*
* <li><code>%g</code> - replaced by a generation number for
* distinguisthing the individual items in the rotating set
* of log files. The generation number cycles through the
* sequence 0, 1, ..., <code>count</code> - 1.</li>
*
* <li><code>%u</code> - replaced by a unique number for
* distinguisthing the output files of several concurrently
* running processes. The <code>FileHandler</code> starts
* with 0 when it tries to open a log file. If the file
* cannot be opened because it is currently in use,
* the unique number is incremented by one and opening
* is tried again. These steps are repeated until the
* opening operation succeeds.
*
* <p>FIXME: Is the following correct? Please review. The unique
* number is determined for each log file individually when it is
* opened upon switching to the next file. Therefore, it is not
* correct to assume that all log files in a rotating set bear the
* same unique number.
*
* <p>FIXME: The Javadoc for the Sun reference implementation
* says: "Note that the use of unique ids to avoid conflicts is
* only guaranteed to work reliably when using a local disk file
* system." Why? This needs to be mentioned as well, in case
* the reviewers decide the statement is true. Otherwise,
* file a bug report with Sun.</li>
*
* <li><code>%%</code> - replaced by a single percent sign.</li>
* </ul>
*
* <p>If the pattern string does not contain <code>%g</code> and
* <code>count</code> is greater than one, the handler will append
* the string <code>.%g</code> to the specified pattern.
*
* <p>If the handler attempts to open a log file, this log file
* is being used at the time of the attempt, and the pattern string
* does not contain <code>%u</code>, the handler will append
* the string <code>.%u</code> to the specified pattern. This
* step is performed after any generation number has been
* appended.
*
* <p><em>Examples for the GNU platform:</em>
*
* <p><ul>
*
* <li><code>%h/java%u.log</code> will lead to a single log file
* <code>/home/janet/java0.log</code>, assuming <code>count</code>
* equals 1, the user's home directory is
* <code>/home/janet</code>, and the attempt to open the file
* succeeds.</li>
*
* <li><code>%h/java%u.log</code> will lead to three log files
* <code>/home/janet/java0.log.0</code>,
* <code>/home/janet/java0.log.1</code>, and
* <code>/home/janet/java0.log.2</code>,
* assuming <code>count</code> equals 3, the user's home
* directory is <code>/home/janet</code>, and all attempts
* to open files succeed.</li>
*
* <li><code>%h/java%u.log</code> will lead to three log files
* <code>/home/janet/java0.log.0</code>,
* <code>/home/janet/java1.log.1</code>, and
* <code>/home/janet/java0.log.2</code>,
* assuming <code>count</code> equals 3, the user's home
* directory is <code>/home/janet</code>, and the attempt
* to open <code>/home/janet/java0.log.1</code> fails.</li>
*
* </ul>
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class FileHandler
extends StreamHandler
{
/**
* The number of bytes a log file is approximately allowed to reach
* before it is closed and the handler switches to the next file in
* the rotating set. A value of zero means that files can grow
* without limit.
*/
private final int limit;
/**
* The number of log files through which this handler cycles.
*/
private final int count;
/**
* The pattern for the location and name of the produced log files.
* See the section on <a href="#filePatterns">file name patterns</a>
* for details.
*/
private final String pattern;
/**
* Indicates whether the handler will append log records to existing
* files (<code>true</code>), or whether the handler will clear log files
* upon switching to them (<code>false</code>).
*/
private final boolean append;
/**
* Constructs a <code>FileHandler</code>, taking all property values
* from the current {@link LogManager LogManager} configuration.
*
* @throws java.io.IOException FIXME: The Sun Javadoc says: "if
* there are IO problems opening the files." This conflicts
* with the general principle that configuration errors do
* not prohibit construction. Needs review.
*
* @throws SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*/
public FileHandler()
throws IOException, SecurityException
{
this(/* pattern: use configiguration */ null,
LogManager.getIntProperty("java.util.logging.FileHandler.limit",
/* default */ 0),
LogManager.getIntProperty("java.util.logging.FileHandler.count",
/* default */ 1),
LogManager.getBooleanProperty("java.util.logging.FileHandler.append",
/* default */ false));
}
/* FIXME: Javadoc missing. */
public FileHandler(String pattern)
throws IOException, SecurityException
{
this(pattern,
/* limit */ 0,
/* count */ 1,
/* append */ false);
}
/* FIXME: Javadoc missing. */
public FileHandler(String pattern, boolean append)
throws IOException, SecurityException
{
this(pattern,
/* limit */ 0,
/* count */ 1,
append);
}
/* FIXME: Javadoc missing. */
public FileHandler(String pattern, int limit, int count)
throws IOException, SecurityException
{
this(pattern, limit, count,
LogManager.getBooleanProperty(
"java.util.logging.FileHandler.append",
/* default */ false));
}
/**
* Constructs a <code>FileHandler</code> given the pattern for the
* location and name of the produced log files, the size limit, the
* number of log files thorough which the handler will rotate, and
* the <code>append</code> property. All other property values are
* taken from the current {@link LogManager LogManager}
* configuration.
*
* @param pattern The pattern for the location and name of the
* produced log files. See the section on <a
* href="#filePatterns">file name patterns</a> for details.
* If <code>pattern</code> is <code>null</code>, the value is
* taken from the {@link LogManager LogManager} configuration
* property
* <code>java.util.logging.FileHandler.pattern</code>.
* However, this is a pecularity of the GNU implementation,
* and Sun's API specification does not mention what behavior
* is to be expected for <code>null</code>. Therefore,
* applications should not rely on this feature.
*
* @param limit specifies the number of bytes a log file is
* approximately allowed to reach before it is closed and the
* handler switches to the next file in the rotating set. A
* value of zero means that files can grow without limit.
*
* @param count specifies the number of log files through which this
* handler cycles.
*
* @param append specifies whether the handler will append log
* records to existing files (<code>true</code>), or whether the
* handler will clear log files upon switching to them
* (<code>false</code>).
*
* @throws java.io.IOException FIXME: The Sun Javadoc says: "if
* there are IO problems opening the files." This conflicts
* with the general principle that configuration errors do
* not prohibit construction. Needs review.
*
* @throws SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
* <p>FIXME: This seems in contrast to all other handler
* constructors -- verify this by running tests against
* the Sun reference implementation.
*/
public FileHandler(String pattern,
int limit,
int count,
boolean append)
throws IOException, SecurityException
{
super(createFileStream(pattern, limit, count, append,
/* generation */ 0),
"java.util.logging.FileHandler",
/* default level */ Level.ALL,
/* formatter */ null,
/* default formatter */ XMLFormatter.class);
if ((limit <0) || (count < 1))
throw new IllegalArgumentException();
this.pattern = pattern;
this.limit = limit;
this.count = count;
this.append = append;
}
/* FIXME: Javadoc missing. */
private static java.io.OutputStream createFileStream(String pattern,
int limit,
int count,
boolean append,
int generation)
{
String path;
int unique = 0;
/* Throws a SecurityException if the caller does not have
* LoggingPermission("control").
*/
LogManager.getLogManager().checkAccess();
/* Default value from the java.util.logging.FileHandler.pattern
* LogManager configuration property.
*/
if (pattern == null)
pattern = LogManager.getLogManager().getProperty(
"java.util.logging.FileHandler.pattern");
if (pattern == null)
pattern = "%h/java%u.log";
do
{
path = replaceFileNameEscapes(pattern, generation, unique, count);
try
{
File file = new File(path);
if (file.createNewFile())
return new FileOutputStream(path, append);
}
catch (Exception ex)
{
ex.printStackTrace();
}
unique = unique + 1;
if (pattern.indexOf("%u") < 0)
pattern = pattern + ".%u";
}
while (true);
}
/**
* Replaces the substrings <code>"/"</code> by the value of the
* system property <code>"file.separator"</code>, <code>"%t"</code>
* by the value of the system property
* <code>"java.io.tmpdir"</code>, <code>"%h"</code> by the value of
* the system property <code>"user.home"</code>, <code>"%g"</code>
* by the value of <code>generation</code>, <code>"%u"</code> by the
* value of <code>uniqueNumber</code>, and <code>"%%"</code> by a
* single percent character. If <code>pattern</code> does
* <em>not</em> contain the sequence <code>"%g"</code>,
* the value of <code>generation</code> will be appended to
* the result.
*
* @throws NullPointerException if one of the system properties
* <code>"file.separator"</code>,
* <code>"java.io.tmpdir"</code>, or
* <code>"user.home"</code> has no value and the
* corresponding escape sequence appears in
* <code>pattern</code>.
*/
private static String replaceFileNameEscapes(String pattern,
int generation,
int uniqueNumber,
int count)
{
StringBuffer buf = new StringBuffer(pattern);
String replaceWith;
boolean foundGeneration = false;
int pos = 0;
do
{
// Uncomment the next line for finding bugs.
// System.out.println(buf.substring(0,pos) + '|' + buf.substring(pos));
if (buf.charAt(pos) == '/')
{
/* The same value is also provided by java.io.File.separator. */
replaceWith = System.getProperty("file.separator");
buf.replace(pos, pos + 1, replaceWith);
pos = pos + replaceWith.length() - 1;
continue;
}
if (buf.charAt(pos) == '%')
{
switch (buf.charAt(pos + 1))
{
case 't':
replaceWith = System.getProperty("java.io.tmpdir");
break;
case 'h':
replaceWith = System.getProperty("user.home");
break;
case 'g':
replaceWith = Integer.toString(generation);
foundGeneration = true;
break;
case 'u':
replaceWith = Integer.toString(uniqueNumber);
break;
case '%':
replaceWith = "%";
break;
default:
replaceWith = "??";
break; // FIXME: Throw exception?
}
buf.replace(pos, pos + 2, replaceWith);
pos = pos + replaceWith.length() - 1;
continue;
}
}
while (++pos < buf.length() - 1);
if (!foundGeneration && (count > 1))
{
buf.append('.');
buf.append(generation);
}
return buf.toString();
}
/* FIXME: Javadoc missing, implementation incomplete. */
public void publish(LogRecord record)
{
super.publish(record);
/* FIXME: Decide when to switch over. How do we get to
* the number of bytes published so far? Two possibilities:
* 1. File.length, 2. have metering wrapper around
* output stream counting the number of written bytes.
*/
/* FIXME: Switch over if needed! This implementation always
* writes into a single file, i.e. behaves as if limit
* always was zero. So, the implementation is somewhat
* functional but incomplete.
*/
}
}
-64
View File
@@ -1,64 +0,0 @@
/* Filter.java -- an interface for filters that decide whether a
LogRecord should be published or discarded
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
/**
* By implementing the <code>Filter</code> interface, applications
* can control what is being logged based on arbitrary properties,
* not just the severity level. Both <code>Handler</code> and
* <code>Logger</code> allow to register Filters whose
* <code>isLoggable</code> method will be called when a
* <code>LogRecord</code> has passed the test based on the
* severity level.
*
* @author Sascha Brawer (brawer@acm.org)
*/
public interface Filter
{
/**
* Determines whether a LogRecord should be published or discarded.
*
* @param record the <code>LogRecord</code> to be inspected.
*
* @return <code>true</code> if the record should be published,
* <code>false</code> if it should be discarded.
*/
boolean isLoggable(LogRecord record);
}
-171
View File
@@ -1,171 +0,0 @@
/* Formatter.java --
A class for formatting log messages by localizing message texts
and performing substitution of parameters
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
import java.text.MessageFormat;
import java.util.ResourceBundle;
/**
* A <code>Formatter</code> supports handlers by localizing
* message texts and by subsituting parameter values for their
* placeholders.
*
* @author Sascha Brawer (brawer@acm.org)
*/
public abstract class Formatter
{
/**
* Constructs a new Formatter.
*/
protected Formatter()
{
}
/**
* Formats a LogRecord into a string. Usually called by handlers
* which need a string for a log record, for example to append
* a record to a log file or to transmit a record over the network.
*
* @param record the log record for which a string form is requested.
*/
public abstract String format(LogRecord record);
/**
* Returns a string that handlers are supposed to emit before
* the first log record. The base implementation returns an
* empty string, but subclasses such as {@link XMLFormatter}
* override this method in order to provide a suitable header.
*
* @return a string for the header.
*
* @param handler the handler which will prepend the returned
* string in front of the first log record. This method
* may inspect certain properties of the handler, for
* example its encoding, in order to construct the header.
*/
public String getHead(Handler handler)
{
return "";
}
/**
* Returns a string that handlers are supposed to emit after
* the last log record. The base implementation returns an
* empty string, but subclasses such as {@link XMLFormatter}
* override this method in order to provide a suitable tail.
*
* @return a string for the header.
*
* @param handler the handler which will append the returned
* string after the last log record. This method
* may inspect certain properties of the handler
* in order to construct the tail.
*/
public String getTail(Handler handler)
{
return "";
}
/**
* Formats the message part of a log record.
*
* <p>First, the Formatter localizes the record message to the
* default locale by looking up the message in the record's
* localization resource bundle. If this step fails because there
* is no resource bundle associated with the record, or because the
* record message is not a key in the bundle, the raw message is
* used instead.
*
* <p>Second, the Formatter substitutes appropriate strings for
* the message parameters. If the record returns a non-empty
* array for <code>getParameters()</code> and the localized
* message string contains the character sequence "{0", the
* formatter uses <code>java.text.MessageFormat</code> to format
* the message. Otherwise, no parameter substitution is performed.
*
* @param record the log record to be localized and formatted.
*
* @return the localized message text where parameters have been
* substituted by suitable strings.
*
* @throws NullPointerException if <code>record</code>
* is <code>null</code>.
*/
public String formatMessage(LogRecord record)
{
String msg;
ResourceBundle bundle;
Object[] params;
/* This will throw a NullPointerExceptionif record is null. */
msg = record.getMessage();
if (msg == null)
msg = "";
/* Try to localize the message. */
bundle = record.getResourceBundle();
if (bundle != null)
{
try
{
msg = bundle.getString(msg);
}
catch (java.util.MissingResourceException _)
{
}
}
/* Format the message if there are parameters. */
params = record.getParameters();
if ((params != null)
&& (params.length > 0)
&& (msg.indexOf("{0") >= 0))
{
msg = MessageFormat.format(msg, params);
}
return msg;
}
}
-386
View File
@@ -1,386 +0,0 @@
/* Handler.java -- a class for publishing log messages
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
import java.io.UnsupportedEncodingException;
/**
* A <code>Handler</code> publishes <code>LogRecords</code> to
* a sink, for example a file, the console or a network socket.
* There are different subclasses of <code>Handler</code>
* to deal with different kinds of sinks.
*
* <p>FIXME: Are handlers thread-safe, or is the assumption that only
* loggers are, and a handler can belong only to one single logger? If
* the latter, should we enforce it? (Spec not clear). In any
* case, it needs documentation.
*
* @author Sascha Brawer (brawer@acm.org)
*/
public abstract class Handler
{
Formatter formatter;
Filter filter;
Level level;
ErrorManager errorManager;
String encoding;
/**
* Constructs a Handler with a logging severity level of
* <code>Level.ALL</code>, no formatter, no filter, and
* an instance of <code>ErrorManager</code> managing errors.
*
* <p><strong>Specification Note:</strong> The specification of the
* Java<sup>TM</sup> Logging API does not mention which character
* encoding is to be used by freshly constructed Handlers. The GNU
* implementation uses the default platform encoding, but other
* Java implementations might behave differently.
*
* <p><strong>Specification Note:</strong> While a freshly constructed
* Handler is required to have <em>no filter</em> according to the
* specification, <code>null</code> is not a valid parameter for
* <code>Handler.setFormatter</code>. Therefore, the following
* code will throw a <code>java.lang.NullPointerException</code>:
*
* <p><pre>Handler h = new MyConcreteSubclassOfHandler();
h.setFormatter(h.getFormatter());</pre>
*
* It seems strange that a freshly constructed Handler is not
* supposed to provide a Formatter, but this is what the specification
* says.
*/
protected Handler()
{
level = Level.ALL;
}
/**
* Publishes a <code>LogRecord</code> to an appropriate sink,
* provided the record passes all tests for being loggable. The
* <code>Handler</code> will localize the message of the log
* record and substitute any message parameters.
*
* <p>Most applications do not need to call this method directly.
* Instead, they will use use a {@link Logger}, which will
* create LogRecords and distribute them to registered handlers.
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>Handler</code> will be informed, but the caller
* of this method will not receive an exception.
*
* @param record the log event to be published.
*/
public abstract void publish(LogRecord record);
/**
* Forces any data that may have been buffered to the underlying
* output device.
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>Handler</code> will be informed, but the caller
* of this method will not receive an exception.
*/
public abstract void flush();
/**
* Closes this <code>Handler</code> after having flushed
* the buffers. As soon as <code>close</code> has been called,
* a <code>Handler</code> should not be used anymore. Attempts
* to publish log records, to flush buffers, or to modify the
* <code>Handler</code> in any other way may throw runtime
* exceptions after calling <code>close</code>.
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>Handler</code> will be informed, but the caller
* of this method will not receive an exception.
*
* @throws SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*/
public abstract void close()
throws SecurityException;
/**
* Returns the <code>Formatter</code> which will be used to
* localize the text of log messages and to substitute
* message parameters. A <code>Handler</code> is encouraged,
* but not required to actually use an assigned
* <code>Formatter</code>.
*
* @return the <code>Formatter</code> being used, or
* <code>null</code> if this <code>Handler</code>
* does not use formatters and no formatter has
* ever been set by calling <code>setFormatter</code>.
*/
public Formatter getFormatter()
{
return formatter;
}
/**
* Sets the <code>Formatter</code> which will be used to
* localize the text of log messages and to substitute
* message parameters. A <code>Handler</code> is encouraged,
* but not required to actually use an assigned
* <code>Formatter</code>.
*
* @param formatter the new <code>Formatter</code> to use.
*
* @throws SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*
* @throws NullPointerException if <code>formatter</code> is
* <code>null</code>.
*/
public void setFormatter(Formatter formatter)
throws SecurityException
{
LogManager.getLogManager().checkAccess();
/* Throws a NullPointerException if formatter is null. */
formatter.getClass();
this.formatter = formatter;
}
/**
* Returns the character encoding which this handler uses for publishing
* log records.
*
* @param encoding the name of a character encoding, or <code>null</code>
* for the default platform encoding.
*/
public String getEncoding()
{
return encoding;
}
/**
* Sets the character encoding which this handler uses for publishing
* log records. The encoding of a <code>Handler</code> must be
* set before any log records have been published.
*
* @param encoding the name of a character encoding, or <code>null</code>
* for the default encoding.
*
* @exception SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*
*/
public void setEncoding(String encoding)
throws SecurityException, UnsupportedEncodingException
{
/* Should any developer ever change this implementation, they are
* advised to have a look at StreamHandler.setEncoding(String),
* which overrides this method without calling super.setEncoding.
*/
LogManager.getLogManager().checkAccess();
/* Simple check for supported encodings. This is more expensive
* than it could be, but this method is overwritten by StreamHandler
* anyway.
*/
if (encoding != null)
new String(new byte[0], encoding);
this.encoding = encoding;
}
/**
* Returns the <code>Filter</code> that currently controls which
* log records are being published by this <code>Handler</code>.
*
* @return the currently active <code>Filter</code>, or
* <code>null</code> if no filter has been associated.
* In the latter case, log records are filtered purely
* based on their severity level.
*/
public Filter getFilter()
{
return filter;
}
/**
* Sets the <code>Filter</code> for controlling which
* log records will be published by this <code>Handler</code>.
*
* @return the <code>Filter</code> to use, or
* <code>null</code> to filter log records purely based
* on their severity level.
*/
public void setFilter(Filter filter)
throws SecurityException
{
LogManager.getLogManager().checkAccess();
this.filter = filter;
}
/**
* Returns the <code>ErrorManager</code> that currently deals
* with errors originating from this Handler.
*
* @exception SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*/
public ErrorManager getErrorManager()
{
LogManager.getLogManager().checkAccess();
/* Developers wanting to change the subsequent code should
* have a look at Handler.reportError -- it also can create
* an ErrorManager, but does so without checking permissions
* to control the logging infrastructure.
*/
if (errorManager == null)
errorManager = new ErrorManager();
return errorManager;
}
public void setErrorManager(ErrorManager manager)
{
LogManager.getLogManager().checkAccess();
/* Make sure manager is not null. */
manager.getClass();
this.errorManager = manager;
}
protected void reportError(String message, Exception ex, int code)
{
if (errorManager == null)
errorManager = new ErrorManager();
errorManager.error(message, ex, code);
}
/**
* Returns the severity level threshold for this <code>Handler</code>
* All log records with a lower severity level will be discarded;
* a log record of the same or a higher level will be published
* unless an installed <code>Filter</code> decides to discard it.
*
* @return the severity level below which all log messages
* will be discarded.
*/
public Level getLevel()
{
return level;
}
/**
* Sets the severity level threshold for this <code>Handler</code>.
* All log records with a lower severity level will be discarded;
* a log record of the same or a higher level will be published
* unless an installed <code>Filter</code> decides to discard it.
*
* @param level the severity level below which all log messages
* will be discarded.
*
* @exception SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*
* @exception NullPointerException if <code>level</code> is
* <code>null</code>.
*/
public void setLevel(Level level)
{
LogManager.getLogManager().checkAccess();
/* Throw NullPointerException if level is null. */
level.getClass();
this.level = level;
}
/**
* Checks whether a <code>LogRecord</code> would be logged
* if it was passed to this <code>Handler</code> for publication.
*
* <p>The <code>Handler</code> implementation considers a record as
* loggable if its level is greater than or equal to the severity
* level threshold. In a second step, if a {@link Filter} has
* been installed, its {@link Filter#isLoggable(LogRecord) isLoggable}
* method is invoked. Subclasses of <code>Handler</code> can override
* this method to impose their own constraints.
*
* @param record the <code>LogRecord</code> to be checked.
*
* @return <code>true</code> if <code>record</code> would
* be published by {@link #publish(LogRecord) publish},
* <code>false</code> if it would be discarded.
*
* @see #setLevel(Level)
* @see #setFilter(Filter)
* @see Filter#isLoggable(LogRecord)
*
* @throws NullPointerException if <code>record</code>
* is <code>null</code>.
*/
public boolean isLoggable(LogRecord record)
{
if (record.getLevel().intValue() < level.intValue())
return false;
if (filter != null)
return filter.isLoggable(record);
else
return true;
}
}
-414
View File
@@ -1,414 +0,0 @@
/* Level.java -- a class for indicating logging levels
Copyright (C) 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
import java.io.Serializable;
import java.util.ResourceBundle;
/**
* A class for indicating logging levels. A number of commonly used
* levels is pre-defined (such as <code>java.util.logging.Level.INFO</code>),
* and applications should utilize those whenever possible. For specialized
* purposes, however, applications can sub-class Level in order to define
* custom logging levels.
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class Level implements Serializable
{
/* The integer values are the same as in the Sun J2SE 1.4.
* They have been obtained with a test program. In J2SE 1.4.1,
* Sun has amended the API documentation; these values are now
* publicly documented.
*/
/**
* The <code>OFF</code> level is used as a threshold for filtering
* log records, meaning that no message should be logged.
*
* @see Logger#setLevel(java.util.logging.Level)
*/
public static final Level OFF = new Level ("OFF", Integer.MAX_VALUE);
/**
* Log records whose level is <code>SEVERE</code> indicate a serious
* failure that prevents normal program execution. Messages at this
* level should be understandable to an inexperienced, non-technical
* end user. Ideally, they explain in simple words what actions the
* user can take in order to resolve the problem.
*/
public static final Level SEVERE = new Level ("SEVERE", 1000);
/**
* Log records whose level is <code>WARNING</code> indicate a
* potential problem that does not prevent normal program execution.
* Messages at this level should be understandable to an
* inexperienced, non-technical end user. Ideally, they explain in
* simple words what actions the user can take in order to resolve
* the problem.
*/
public static final Level WARNING = new Level ("WARNING", 900);
/**
* Log records whose level is <code>INFO</code> are used in purely
* informational situations that do not constitute serious errors or
* potential problems. In the default logging configuration, INFO
* messages will be written to the system console. For this reason,
* the INFO level should be used only for messages that are
* important to end users and system administrators. Messages at
* this level should be understandable to an inexperienced,
* non-technical user.
*/
public static final Level INFO = new Level ("INFO", 800);
/**
* Log records whose level is <code>CONFIG</code> are used for
* describing the static configuration, for example the windowing
* environment, the operating system version, etc.
*/
public static final Level CONFIG = new Level ("CONFIG", 700);
/**
* Log records whose level is <code>FINE</code> are typically used
* for messages that are relevant for developers using
* the component generating log messages. Examples include minor,
* recoverable failures, or possible inefficiencies.
*/
public static final Level FINE = new Level ("FINE", 500);
/**
* Log records whose level is <code>FINER</code> are intended for
* rather detailed tracing, for example entering a method, returning
* from a method, or throwing an exception.
*/
public static final Level FINER = new Level ("FINER", 400);
/**
* Log records whose level is <code>FINEST</code> are used for
* highly detailed tracing, for example to indicate that a certain
* point inside the body of a method has been reached.
*/
public static final Level FINEST = new Level ("FINEST", 300);
/**
* The <code>ALL</code> level is used as a threshold for filtering
* log records, meaning that every message should be logged.
*
* @see Logger#setLevel(java.util.logging.Level)
*/
public static final Level ALL = new Level ("ALL", Integer.MIN_VALUE);
private static final Level[] knownLevels = {
ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF
};
/**
* The name of the Level without localizing it, for example
* "WARNING".
*/
private String name;
/**
* The integer value of this <code>Level</code>.
*/
private int value;
/**
* The name of the resource bundle used for localizing the level
* name, or <code>null</code> if the name does not undergo
* localization.
*/
private String resourceBundleName;
/**
* Creates a logging level given a name and an integer value.
* It rarely is necessary to create custom levels,
* as most applications should be well served with one of the
* standard levels such as <code>Level.CONFIG</code>,
* <code>Level.INFO</code>, or <code>Level.FINE</code>.
*
* @param name the name of the level.
*
* @param value the integer value of the level. Please note
* that the Java<small><sup>TM</sup></small>
* Logging API does not specify integer
* values for standard levels (such as
* Level.FINE). Therefore, a custom
* level should pass an integer value that
* is calculated at run-time, e.g.
* <code>(Level.FINE.intValue() + Level.CONFIG.intValue())
* / 2</code> for a level between FINE and CONFIG.
*/
protected Level(String name, int value)
{
this(name, value, null);
}
/**
* Create a logging level given a name, an integer value and a name
* of a resource bundle for localizing the level name. It rarely
* is necessary to create custom levels, as most applications
* should be well served with one of the standard levels such as
* <code>Level.CONFIG</code>, <code>Level.INFO</code>, or
* <code>Level.FINE</code>.
*
* @param name the name of the level.
*
* @param value the integer value of the level. Please note
* that the Java<small><sup>TM</sup></small>
* Logging API does not specify integer
* values for standard levels (such as
* Level.FINE). Therefore, a custom
* level should pass an integer value that
* is calculated at run-time, e.g.
* <code>(Level.FINE.intValue() + Level.CONFIG.intValue())
* / 2</code> for a level between FINE and CONFIG.
*
* @param resourceBundleName the name of a resource bundle
* for localizing the level name, or <code>null</code>
* if the name does not need to be localized.
*/
protected Level(String name, int value, String resourceBundleName)
{
this.name = name;
this.value = value;
this.resourceBundleName = resourceBundleName;
}
static final long serialVersionUID = -8176160795706313070L;
/**
* Checks whether the Level has the same intValue as one of the
* pre-defined levels. If so, the pre-defined level object is
* returned.
*
* <br/>Since the resource bundle name is not taken into
* consideration, it is possible to resolve Level objects that have
* been de-serialized by another implementation, even if the other
* implementation uses a different resource bundle for localizing
* the names of pre-defined levels.
*/
private Object readResolve()
{
for (int i = 0; i < knownLevels.length; i++)
if (value == knownLevels[i].intValue())
return knownLevels[i];
return this;
}
/**
* Returns the name of the resource bundle used for localizing the
* level name.
*
* @return the name of the resource bundle used for localizing the
* level name, or <code>null</code> if the name does not undergo
* localization.
*/
public String getResourceBundleName()
{
return resourceBundleName;
}
/**
* Returns the name of the Level without localizing it, for example
* "WARNING".
*/
public String getName()
{
return name;
}
/**
* Returns the name of the Level after localizing it, for example
* "WARNUNG".
*/
public String getLocalizedName()
{
String localizedName = null;
if (resourceBundleName != null)
{
try
{
ResourceBundle b = ResourceBundle.getBundle(resourceBundleName);
localizedName = b.getString(name);
}
catch (Exception _)
{
}
}
if (localizedName != null)
return localizedName;
else
return name;
}
/**
* Returns the name of the Level without localizing it, for example
* "WARNING".
*/
public final String toString()
{
return getName();
}
/**
* Returns the integer value of the Level.
*/
public final int intValue()
{
return value;
}
/**
* Returns one of the standard Levels given either its name or its
* integer value. Custom subclasses of Level will not be returned
* by this method.
*
* @throws IllegalArgumentException if <code>name</code> is neither
* the name nor the integer value of one of the pre-defined standard
* logging levels.
*
* @throws NullPointerException if <code>name</code> is null.
*
*/
public static Level parse(String name)
throws IllegalArgumentException
{
/* This will throw a NullPointerException if name is null,
* as required by the API specification.
*/
name = name.intern();
for (int i = 0; i < knownLevels.length; i++)
{
if (name == knownLevels[i].name)
return knownLevels[i];
}
try
{
int num = Integer.parseInt(name);
for (int i = 0; i < knownLevels.length; i++)
if (num == knownLevels[i].value)
return knownLevels[i];
}
catch (NumberFormatException _)
{
}
String msg = "Not the name of a standard logging level: \"" + name + "\"";
throw new IllegalArgumentException(msg);
}
/**
* Checks whether this Level's integer value is equal to that of
* another object.
*
* @return <code>true</code> if <code>other</code> is an instance of
* <code>java.util.logging.Level</code> and has the same integer
* value, <code>false</code> otherwise.
*/
public boolean equals(Object other)
{
if (!(other instanceof Level))
return false;
return value == ((Level) other).value;
}
/**
* Returns a hash code for this Level which is based on its numeric
* value.
*/
public int hashCode()
{
return value;
}
/**
* Determines whether or not this Level is one of the standard
* levels specified in the Logging API.
*
* <p>This method is package-private because it is not part
* of the logging API specification. However, an XMLFormatter
* is supposed to emit the numeric value for a custom log
* level, but the name for a pre-defined level. It seems
* cleaner to put this method to Level than to write some
* procedural code for XMLFormatter.
*
* @return <code>true</code> if this Level is a standard level,
* <code>false</code> otherwise.
*/
final boolean isStandardLevel()
{
for (int i = 0; i < knownLevels.length; i++)
if (knownLevels[i] == this)
return true;
return false;
}
}
-672
View File
@@ -1,672 +0,0 @@
/* LogRecord.java --
A class for the state associated with individual logging events
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
import java.util.ResourceBundle;
/**
* A <code>LogRecord</code> contains the state for an individual
* event to be logged.
*
* <p>As soon as a LogRecord instance has been handed over to the
* logging framework, applications should not manipulate it anymore.
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class LogRecord
implements java.io.Serializable
{
/**
* The severity level of this <code>LogRecord</code>.
*/
private Level level;
/**
* The sequence number of this <code>LogRecord</code>.
*/
private long sequenceNumber;
/**
* The name of the class that issued the logging request, or
* <code>null</code> if this information could not be obtained.
*/
private String sourceClassName;
/**
* The name of the method that issued the logging request, or
* <code>null</code> if this information could not be obtained.
*/
private String sourceMethodName;
/**
* The message for this <code>LogRecord</code> before
* any localization or formatting.
*/
private String message;
/**
* An identifier for the thread in which this <code>LogRecord</code>
* was created. The identifier is not necessarily related to any
* thread identifiers used by the operating system.
*/
private int threadID;
/**
* The time when this <code>LogRecord</code> was created,
* in milliseconds since the beginning of January 1, 1970.
*/
private long millis;
/**
* The Throwable associated with this <code>LogRecord</code>, or
* <code>null</code> if the logged event is not related to an
* exception or error.
*/
private Throwable thrown;
/**
* The name of the logger where this <code>LogRecord</code> has
* originated, or <code>null</code> if this <code>LogRecord</code>
* does not originate from a <code>Logger</code>.
*/
private String loggerName;
/**
* The name of the resource bundle used for localizing log messages,
* or <code>null</code> if no bundle has been specified.
*/
private String resourceBundleName;
private transient Object[] parameters;
private transient ResourceBundle bundle;
/**
* Constructs a <code>LogRecord</code> given a severity level and
* an unlocalized message text. In addition, the sequence number,
* creation time (as returned by <code>getMillis()</code>) and
* thread ID are assigned. All other properties are set to
* <code>null</code>.
*
* @param level the severity level, for example <code>Level.WARNING</code>.
*
* @param message the message text (which will be used as key
* for looking up the localized message text
* if a resource bundle has been associated).
*/
public LogRecord(Level level, String message)
{
this.level = level;
this.message = message;
this.millis = System.currentTimeMillis();
/* A subclass of java.lang.Thread could override hashCode(),
* in which case the result would not be guaranteed anymore
* to be unique among all threads. While System.identityHashCode
* is not necessarily unique either, it at least cannot be
* overridden by user code. However, is might be a good idea
* to use something better for generating thread IDs.
*/
this.threadID = System.identityHashCode(Thread.currentThread());
sequenceNumber = allocateSeqNum();
}
/**
* Determined with the serialver tool of the Sun J2SE 1.4.
*/
static final long serialVersionUID = 5372048053134512534L;
private void readObject(java.io.ObjectInputStream in)
throws java.io.IOException, java.lang.ClassNotFoundException
{
in.defaultReadObject();
/* We assume that future versions will be downwards compatible,
* so we can ignore the versions.
*/
byte majorVersion = in.readByte();
byte minorVersion = in.readByte();
int numParams = in.readInt();
if (numParams >= 0)
{
parameters = new Object[numParams];
for (int i = 0; i < numParams; i++)
parameters[i] = in.readObject();
}
}
/**
* @serialData The default fields, followed by a major byte version
* number, followed by a minor byte version number, followed by
* information about the log record parameters. If
* <code>parameters</code> is <code>null</code>, the integer -1 is
* written, otherwise the length of the <code>parameters</code>
* array (which can be zero), followed by the result of calling
* {@link Object#toString() toString()} on the parameter (or
* <code>null</code> if the parameter is <code>null</code>).
*
* <p><strong>Specification Note:</strong> The Javadoc for the
* Sun reference implementation does not specify the version
* number. FIXME: Reverse-engineer the JDK and file a bug
* report with Sun, asking for amendment of the specification.
*/
private void writeObject(java.io.ObjectOutputStream out)
throws java.io.IOException
{
out.defaultWriteObject();
/* Major, minor version number: The Javadoc for J2SE1.4 does not
* specify the values.
*/
out.writeByte(0);
out.writeByte(0);
if (parameters == null)
out.writeInt(-1);
else
{
out.writeInt(parameters.length);
for (int i = 0; i < parameters.length; i++)
{
if (parameters[i] == null)
out.writeObject(null);
else
out.writeObject(parameters[i].toString());
}
}
}
/**
* Returns the name of the logger where this <code>LogRecord</code>
* has originated.
*
* @return the name of the source {@link Logger}, or
* <code>null</code> if this <code>LogRecord</code>
* does not originate from a <code>Logger</code>.
*/
public String getLoggerName()
{
return loggerName;
}
/**
* Sets the name of the logger where this <code>LogRecord</code>
* has originated.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param name the name of the source logger, or <code>null</code> to
* indicate that this <code>LogRecord</code> does not
* originate from a <code>Logger</code>.
*/
public void setLoggerName(String name)
{
loggerName = name;
}
/**
* Returns the resource bundle that is used when the message
* of this <code>LogRecord</code> needs to be localized.
*
* @return the resource bundle used for localization,
* or <code>null</code> if this message does not need
* to be localized.
*/
public ResourceBundle getResourceBundle()
{
return bundle;
}
/**
* Sets the resource bundle that is used when the message
* of this <code>LogRecord</code> needs to be localized.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param bundle the resource bundle to be used, or
* <code>null</code> to indicate that this
* message does not need to be localized.
*/
public void setResourceBundle(ResourceBundle bundle)
{
this.bundle = bundle;
/* FIXME: Is there a way to infer the name
* of a resource bundle from a ResourceBundle object?
*/
this.resourceBundleName = null;
}
/**
* Returns the name of the resource bundle that is used when the
* message of this <code>LogRecord</code> needs to be localized.
*
* @return the name of the resource bundle used for localization,
* or <code>null</code> if this message does not need
* to be localized.
*/
public String getResourceBundleName()
{
return resourceBundleName;
}
/**
* Sets the name of the resource bundle that is used when the
* message of this <code>LogRecord</code> needs to be localized.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param name the name of the resource bundle to be used, or
* <code>null</code> to indicate that this message
* does not need to be localized.
*/
public void setResourceBundleName(String name)
{
resourceBundleName = name;
bundle = null;
try
{
if (resourceBundleName != null)
bundle = ResourceBundle.getBundle(resourceBundleName);
}
catch (java.util.MissingResourceException _)
{
}
}
/**
* Returns the level of the LogRecord.
*
* <p>Applications should be aware of the possibility that the
* result is not necessarily one of the standard logging levels,
* since the logging framework allows to create custom subclasses
* of <code>java.util.logging.Level</code>. Therefore, filters
* should perform checks like <code>theRecord.getLevel().intValue()
* == Level.INFO.intValue()</code> instead of <code>theRecord.getLevel()
* == Level.INFO</code>.
*/
public Level getLevel()
{
return level;
}
/**
* Sets the severity level of this <code>LogRecord</code> to a new
* value.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param level the new severity level, for example
* <code>Level.WARNING</code>.
*/
public void setLevel(Level level)
{
this.level = level;
}
/**
* The last used sequence number for any LogRecord.
*/
private static long lastSeqNum;
/**
* Allocates a sequence number for a new LogRecord. This class
* method is only called by the LogRecord constructor.
*/
private static synchronized long allocateSeqNum()
{
lastSeqNum += 1;
return lastSeqNum;
}
/**
* Returns the sequence number of this <code>LogRecord</code>.
*/
public long getSequenceNumber()
{
return sequenceNumber;
}
/**
* Sets the sequence number of this <code>LogRecord</code> to a new
* value.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param seqNum the new sequence number.
*/
public void setSequenceNumber(long seqNum)
{
this.sequenceNumber = seqNum;
}
/**
* Returns the name of the class where the event being logged
* has had its origin. This information can be passed as
* parameter to some logging calls, and in certain cases, the
* logging framework tries to determine an approximation
* (which may or may not be accurate).
*
* @return the name of the class that issued the logging request,
* or <code>null</code> if this information could not
* be obtained.
*/
public String getSourceClassName()
{
if (sourceClassName != null)
return sourceClassName;
/* FIXME: Should infer this information from the call stack. */
return null;
}
/**
* Sets the name of the class where the event being logged
* has had its origin.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param sourceClassName the name of the class that issued the
* logging request, or <code>null</code> to indicate that
* this information could not be obtained.
*/
public void setSourceClassName(String sourceClassName)
{
this.sourceClassName = sourceClassName;
}
/**
* Returns the name of the method where the event being logged
* has had its origin. This information can be passed as
* parameter to some logging calls, and in certain cases, the
* logging framework tries to determine an approximation
* (which may or may not be accurate).
*
* @return the name of the method that issued the logging request,
* or <code>null</code> if this information could not
* be obtained.
*/
public String getSourceMethodName()
{
if (sourceMethodName != null)
return sourceMethodName;
/* FIXME: Should infer this information from the call stack. */
return null;
}
/**
* Sets the name of the method where the event being logged
* has had its origin.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param sourceMethodName the name of the method that issued the
* logging request, or <code>null</code> to indicate that
* this information could not be obtained.
*/
public void setSourceMethodName(String sourceMethodName)
{
this.sourceMethodName = sourceMethodName;
}
/**
* Returns the message for this <code>LogRecord</code> before
* any localization or parameter substitution.
*
* <p>A {@link Logger} will try to localize the message
* if a resource bundle has been associated with this
* <code>LogRecord</code>. In this case, the logger will call
* <code>getMessage()</code> and use the result as the key
* for looking up the localized message in the bundle.
* If no bundle has been associated, or if the result of
* <code>getMessage()</code> is not a valid key in the
* bundle, the logger will use the raw message text as
* returned by this method.
*
* @return the message text, or <code>null</code> if there
* is no message text.
*/
public String getMessage()
{
return message;
}
/**
* Sets the message for this <code>LogRecord</code>.
*
* <p>A <code>Logger</code> will try to localize the message
* if a resource bundle has been associated with this
* <code>LogRecord</code>. In this case, the logger will call
* <code>getMessage()</code> and use the result as the key
* for looking up the localized message in the bundle.
* If no bundle has been associated, or if the result of
* <code>getMessage()</code> is not a valid key in the
* bundle, the logger will use the raw message text as
* returned by this method.
*
* <p>It is possible to set the message to either an empty String or
* <code>null</code>, although this does not make the the message
* very helpful to human users.
*
* @param message the message text (which will be used as key
* for looking up the localized message text
* if a resource bundle has been associated).
*/
public void setMessage(String message)
{
this.message = message;
}
/**
* Returns the parameters to the log message.
*
* @return the parameters to the message, or <code>null</code> if
* the message has no parameters.
*/
public Object[] getParameters()
{
return parameters;
}
/**
* Sets the parameters to the log message.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param parameters the parameters to the message, or <code>null</code>
* to indicate that the message has no parameters.
*/
public void setParameters(Object[] parameters)
{
this.parameters = parameters;
}
/**
* Returns an identifier for the thread in which this
* <code>LogRecord</code> was created. The identifier is not
* necessarily related to any thread identifiers used by the
* operating system.
*
* @return an identifier for the source thread.
*/
public int getThreadID()
{
return threadID;
}
/**
* Sets the identifier indicating in which thread this
* <code>LogRecord</code> was created. The identifier is not
* necessarily related to any thread identifiers used by the
* operating system.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param threadID the identifier for the source thread.
*/
public void setThreadID(int threadID)
{
this.threadID = threadID;
}
/**
* Returns the time when this <code>LogRecord</code> was created.
*
* @return the time of creation in milliseconds since the beginning
* of January 1, 1970.
*/
public long getMillis()
{
return millis;
}
/**
* Sets the time when this <code>LogRecord</code> was created.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param millis the time of creation in milliseconds since the
* beginning of January 1, 1970.
*/
public void setMillis(long millis)
{
this.millis = millis;
}
/**
* Returns the Throwable associated with this <code>LogRecord</code>,
* or <code>null</code> if the logged event is not related to an exception
* or error.
*/
public Throwable getThrown()
{
return thrown;
}
/**
* Associates this <code>LogRecord</code> with an exception or error.
*
* <p>As soon as a <code>LogRecord</code> has been handed over
* to the logging framework, applications should not modify it
* anymore. Therefore, this method should only be called on
* freshly constructed LogRecords.
*
* @param thrown the exception or error to associate with, or
* <code>null</code> if this <code>LogRecord</code>
* should be made unrelated to an exception or error.
*/
public void setThrown(Throwable thrown)
{
this.thrown = thrown;
}
}
@@ -1,73 +0,0 @@
/* LoggingPermission.java -- a class for logging permissions.
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
public final class LoggingPermission
extends java.security.BasicPermission
{
/**
* Creates a new LoggingPermission.
*
* @param name the name of the permission, which must be "control".
*
* @param actions the list of actions for the permission, which
* must be either <code>null</code> or an empty
* string.
*
* @exception IllegalArgumentException if <code>name</code>
* is not "control", or <code>actions</code> is
* neither <code>null</code> nor empty.
*/
public LoggingPermission(String name, String actions)
{
super("control", "");
if (!"control".equals(name))
{
throw new IllegalArgumentException(
"name of LoggingPermission must be \"control\"");
}
if ((actions != null) && (actions.length() != 0))
{
throw new IllegalArgumentException(
"actions of LoggingPermissions must be null or empty");
}
}
}
@@ -1,345 +0,0 @@
/* MemoryHandler.java -- a class for buffering log messages in a memory buffer
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
/**
* A <code>MemoryHandler</code> maintains a circular buffer of
* log records.
*
* <p><strong>Configuration:</strong> Values of the subsequent
* <code>LogManager</code> properties are taken into consideration
* when a <code>MemoryHandler</code> is initialized.
* If a property is not defined, or if it has an invalid
* value, a default is taken without an exception being thrown.
*
* <ul>
* <li><code>java.util.MemoryHandler.level</code> - specifies
* the initial severity level threshold. Default value:
* <code>Level.ALL</code>.</li>
* <li><code>java.util.MemoryHandler.filter</code> - specifies
* the name of a Filter class. Default value: No Filter.</li>
* <li><code>java.util.MemoryHandler.size</code> - specifies the
* maximum number of log records that are kept in the circular
* buffer. Default value: 1000.</li>
* <li><code>java.util.MemoryHandler.push</code> - specifies the
* <code>pushLevel</code>. Default value:
* <code>Level.SEVERE</code>.</li>
* <li><code>java.util.MemoryHandler.target</code> - specifies the
* name of a subclass of {@link Handler} that will be used as the
* target handler. There is no default value for this property;
* if it is not set, the no-argument MemoryHandler constructor
* will throw an exception.</li>
* </ul>
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class MemoryHandler
extends Handler
{
/**
* The storage area used for buffering the unpushed log records in
* memory.
*/
private final LogRecord[] buffer;
/**
* The current position in the circular buffer. For a new
* MemoryHandler, or immediately after {@link #push()} was called,
* the value of this variable is zero. Each call to {@link
* #publish(LogRecord)} will store the published LogRecord into
* <code>buffer[position]</code> before position is incremented by
* one. If position becomes greater than the size of the buffer, it
* is reset to zero.
*/
private int position;
/**
* The number of log records which have been published, but not
* pushed yet to the target handler.
*/
private int numPublished;
/**
* The push level threshold for this <code>Handler</code>. When a
* record is published whose severity level is greater than or equal
* to the <code>pushLevel</code> of this <code>MemoryHandler</code>,
* the {@link #push()} method will be invoked for pushing the buffer
* contents to the target <code>Handler</code>.
*/
private Level pushLevel;
/**
* The Handler to which log records are forwarded for actual
* publication.
*/
private final Handler target;
/**
* Constructs a <code>MemoryHandler</code> for keeping a circular
* buffer of LogRecords; the initial configuration is determined by
* the <code>LogManager</code> properties described above.
*/
public MemoryHandler()
{
this((Handler) LogManager.getInstanceProperty(
"java.util.logging.MemoryHandler.target",
Handler.class, /* default */ null),
LogManager.getIntPropertyClamped(
"java.util.logging.MemoryHandler.size",
/* default */ 1000,
/* minimum value */ 1,
/* maximum value */ Integer.MAX_VALUE),
LogManager.getLevelProperty(
"java.util.logging.MemoryHandler.push",
/* default push level */ Level.SEVERE));
}
/**
* Constructs a <code>MemoryHandler</code> for keeping a circular
* buffer of LogRecords, given some parameters. The values of the
* other parameters are taken from LogManager properties, as
* described above.
*
* @param target the target handler that will receive those
* log records that are passed on for publication.
*
* @param size the number of log records that are kept in the buffer.
* The value must be a at least one.
*
* @param pushLevel the push level threshold for this
* <code>MemoryHandler</code>. When a record is published whose
* severity level is greater than or equal to
* <code>pushLevel</code>, the {@link #push()} method will be
* invoked in order to push the bufffer contents to
* <code>target</code>.
*
* @throws java.lang.IllegalArgumentException if <code>size</code>
* is negative or zero. The GNU implementation also throws
* an IllegalArgumentException if <code>target</code> or
* <code>pushLevel</code> are <code>null</code>, but the
* API specification does not prescribe what should happen
* in those cases.
*/
public MemoryHandler(Handler target, int size, Level pushLevel)
{
if ((target == null) || (size <= 0) || (pushLevel == null))
throw new IllegalArgumentException();
buffer = new LogRecord[size];
this.pushLevel = pushLevel;
this.target = target;
setLevel(LogManager.getLevelProperty(
"java.util.logging.MemoryHandler.level",
/* default value */ Level.ALL));
setFilter((Filter) LogManager.getInstanceProperty(
"java.util.logging.MemoryHandler.filter",
/* must be instance of */ Filter.class,
/* default value */ null));
}
/**
* Stores a <code>LogRecord</code> in a fixed-size circular buffer,
* provided the record passes all tests for being loggable. If the
* buffer is full, the oldest record will be discarded.
*
* <p>If the record has a severity level which is greater than or
* equal to the <code>pushLevel</code> of this
* <code>MemoryHandler</code>, the {@link #push()} method will be
* invoked for pushing the buffer contents to the target
* <code>Handler</code>.
*
* <p>Most applications do not need to call this method directly.
* Instead, they will use use a {@link Logger}, which will create
* LogRecords and distribute them to registered handlers.
*
* @param record the log event to be published.
*/
public void publish(LogRecord record)
{
if (!isLoggable(record))
return;
buffer[position] = record;
position = (position + 1) % buffer.length;
numPublished = numPublished + 1;
if (record.getLevel().intValue() >= pushLevel.intValue())
push();
}
/**
* Pushes the contents of the memory buffer to the target
* <code>Handler</code> and clears the buffer. Note that
* the target handler will discard those records that do
* not satisfy its own severity level threshold, or that are
* not considered loggable by an installed {@link Filter}.
*
* <p>In case of an I/O failure, the {@link ErrorManager} of the
* target <code>Handler</code> will be notified, but the caller of
* this method will not receive an exception.
*/
public void push()
{
int i;
if (numPublished < buffer.length)
{
for (i = 0; i < position; i++)
target.publish(buffer[i]);
}
else
{
for (i = position; i < buffer.length; i++)
target.publish(buffer[i]);
for (i = 0; i < position; i++)
target.publish(buffer[i]);
}
numPublished = 0;
position = 0;
}
/**
* Forces any data that may have been buffered by the target
* <code>Handler</code> to the underlying output device, but
* does <em>not</em> push the contents of the circular memory
* buffer to the target handler.
*
* <p>In case of an I/O failure, the {@link ErrorManager} of the
* target <code>Handler</code> will be notified, but the caller of
* this method will not receive an exception.
*
* @see #push()
*/
public void flush()
{
target.flush();
}
/**
* Closes this <code>MemoryHandler</code> and its associated target
* handler, discarding the contents of the memory buffer. However,
* any data that may have been buffered by the target
* <code>Handler</code> is forced to the underlying output device.
*
* <p>As soon as <code>close</code> has been called,
* a <code>Handler</code> should not be used anymore. Attempts
* to publish log records, to flush buffers, or to modify the
* <code>Handler</code> in any other way may throw runtime
* exceptions after calling <code>close</code>.</p>
*
* <p>In case of an I/O failure, the <code>ErrorManager</code> of
* the associated target <code>Handler</code> will be informed, but
* the caller of this method will not receive an exception.</p>
*
* @throws SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*
* @see #push()
*/
public void close()
throws SecurityException
{
push();
/* This will check for LoggingPermission("control"). If the
* current security context does not grant this permission,
* push() has been executed, but this does not impose a
* security risk.
*/
target.close();
}
/**
* Returns the push level threshold for this <code>Handler</code>.
* When a record is published whose severity level is greater
* than or equal to the <code>pushLevel</code> of this
* <code>MemoryHandler</code>, the {@link #push()} method will be
* invoked for pushing the buffer contents to the target
* <code>Handler</code>.
*
* @return the push level threshold for automatic pushing.
*/
public Level getPushLevel()
{
return pushLevel;
}
/**
* Sets the push level threshold for this <code>Handler</code>.
* When a record is published whose severity level is greater
* than or equal to the <code>pushLevel</code> of this
* <code>MemoryHandler</code>, the {@link #push()} method will be
* invoked for pushing the buffer contents to the target
* <code>Handler</code>.
*
* @param pushLevel the push level threshold for automatic pushing.
*
* @exception SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*
* @exception NullPointerException if <code>pushLevel</code> is
* <code>null</code>.
*/
public void setPushLevel(Level pushLevel)
{
LogManager.getLogManager().checkAccess();
/* Throws a NullPointerException if pushLevel is null. */
pushLevel.getClass();
this.pushLevel = pushLevel;
}
}
@@ -1,119 +0,0 @@
/* SimpleFormatter.java --
A class for formatting log records into short human-readable messages
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
import java.text.DateFormat;
import java.util.Date;
/**
* A <code>SimpleFormatter</code> formats log records into
* short human-readable messages, typically one or two lines.
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class SimpleFormatter
extends Formatter
{
/**
* Constructs a SimpleFormatter.
*/
public SimpleFormatter()
{
}
/**
* An instance of a DateFormatter that is used for formatting
* the time of a log record into a human-readable string,
* according to the rules of the current locale. The value
* is set after the first invocation of format, since it is
* common that a JVM will instantiate a SimpleFormatter without
* ever using it.
*/
private DateFormat dateFormat;
/**
* The character sequence that is used to separate lines in the
* generated stream. Somewhat surprisingly, the Sun J2SE 1.4
* reference implementation always uses UNIX line endings, even on
* platforms that have different line ending conventions (i.e.,
* DOS). The GNU implementation does not replicate this bug.
*
* @see Sun bug parade, bug #4462871,
* "java.util.logging.SimpleFormatter uses hard-coded line separator".
*/
static final String lineSep = System.getProperty("line.separator");
/**
* Formats a log record into a String.
*
* @param the log record to be formatted.
*
* @return a short human-readable message, typically one or two
* lines. Lines are separated using the default platform line
* separator.
*
* @throws NullPointerException if <code>record</code>
* is <code>null</code>.
*/
public String format(LogRecord record)
{
StringBuffer buf = new StringBuffer(180);
if (dateFormat == null)
dateFormat = DateFormat.getDateTimeInstance();
buf.append(dateFormat.format(new Date(record.getMillis())));
buf.append(' ');
buf.append(record.getSourceClassName());
buf.append(' ');
buf.append(record.getSourceMethodName());
buf.append(lineSep);
buf.append(record.getLevel());
buf.append(": ");
buf.append(formatMessage(record));
buf.append(lineSep);
return buf.toString();
}
}
@@ -1,221 +0,0 @@
/* SocketHandler.java -- a class for publishing log messages to network sockets
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
/**
* A <code>SocketHandler</code> publishes log records to
* a TCP/IP socket.
*
* <p><strong>Configuration:</strong> Values of the subsequent
* <code>LogManager</code> properties are taken into consideration
* when a <code>SocketHandler</code> is initialized.
* If a property is not defined, or if it has an invalid
* value, a default is taken without an exception being thrown.
*
* <ul>
*
* <li><code>java.util.SocketHandler.level</code> - specifies
* the initial severity level threshold. Default value:
* <code>Level.ALL</code>.</li>
*
* <li><code>java.util.SocketHandler.filter</code> - specifies
* the name of a Filter class. Default value: No Filter.</li>
*
* <li><code>java.util.SocketHandler.formatter</code> - specifies
* the name of a Formatter class. Default value:
* <code>java.util.logging.XMLFormatter</code>.</li>
*
* <li><code>java.util.SocketHandler.encoding</code> - specifies
* the name of the character encoding. Default value:
* the default platform encoding.</li>
*
* <li><code>java.util.SocketHandler.host</code> - specifies
* the name of the host to which records are published.
* There is no default value for this property; if it is
* not set, the SocketHandler constructor will throw
* an exception.</li>
*
* <li><code>java.util.SocketHandler.port</code> - specifies
* the TCP/IP port to which records are published.
* There is no default value for this property; if it is
* not set, the SocketHandler constructor will throw
* an exception.</li>
*
* </ul>
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class SocketHandler
extends StreamHandler
{
/**
* Constructs a <code>SocketHandler</code> that publishes log
* records to a TCP/IP socket. Tthe initial configuration is
* determined by the <code>LogManager</code> properties described
* above.
*
* @throws java.io.IOException if the connection to the specified
* network host and port cannot be established.
*
* @throws java.lang.IllegalArgumentException if either the
* <code>java.util.logging.SocketHandler.host</code>
* or <code>java.util.logging.SocketHandler.port</code>
* LogManager properties is not defined, or specifies
* an invalid value.
*/
public SocketHandler()
throws java.io.IOException
{
this(LogManager.getLogManager().getProperty("java.util.logging.SocketHandler.host"),
getPortNumber());
}
/**
* Constructs a <code>SocketHandler</code> that publishes log
* records to a TCP/IP socket. With the exception of the internet
* host and port, the initial configuration is determined by the
* <code>LogManager</code> properties described above.
*
* @param host the Internet host to which log records will be
* forwarded.
*
* @param port the port at the host which will accept a request
* for a TCP/IP connection.
*
* @throws java.io.IOException if the connection to the specified
* network host and port cannot be established.
*
* @throws java.lang.IllegalArgumentException if either
* <code>host</code> or <code>port</code> specify
* an invalid value.
*/
public SocketHandler(String host, int port)
throws java.io.IOException
{
super(createSocket(host, port),
"java.util.logging.SocketHandler",
/* default level */ Level.ALL,
/* formatter */ null,
/* default formatter */ XMLFormatter.class);
}
/**
* Retrieves the port number from the java.util.logging.SocketHandler.port
* LogManager property.
*
* @throws IllegalArgumentException if the property is not defined or
* does not specify an integer value.
*/
private static int getPortNumber()
{
try {
return Integer.parseInt(LogManager.getLogManager().getProperty("java.util.logging.SocketHandler.port"));
} catch (Exception ex) {
throw new IllegalArgumentException();
}
}
/**
* Creates an OutputStream for publishing log records to an Internet
* host and port. This private method is a helper for use by the
* constructor of SocketHandler.
*
* @param host the Internet host to which log records will be
* forwarded.
*
* @param port the port at the host which will accept a request
* for a TCP/IP connection.
*
* @throws java.io.IOException if the connection to the specified
* network host and port cannot be established.
*
* @throws java.lang.IllegalArgumentException if either
* <code>host</code> or <code>port</code> specify
* an invalid value.
*/
private static java.io.OutputStream createSocket(String host, int port)
throws java.io.IOException, java.lang.IllegalArgumentException
{
java.net.Socket socket;
if ((host == null) || (port < 1))
throw new IllegalArgumentException();
socket = new java.net.Socket(host, port);
socket.shutdownInput();
/* The architecture of the logging framework provides replaceable
* formatters. Because these formatters perform their task by
* returning one single String for each LogRecord to be formatted,
* there is no need to buffer.
*/
socket.setTcpNoDelay(true);
return socket.getOutputStream();
}
/**
* Publishes a <code>LogRecord</code> to the network socket,
* provided the record passes all tests for being loggable.
* In addition, all data that may have been buffered will
* be forced to the network stream.
*
* <p>Most applications do not need to call this method directly.
* Instead, they will use a {@link Logger} instance, which will
* create LogRecords and distribute them to registered handlers.
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>SocketHandler</code> will be informed, but the caller
* of this method will not receive an exception.
*
* @param record the log event to be published.
*/
public void publish(LogRecord record)
{
super.publish(record);
flush();
}
}
@@ -1,521 +0,0 @@
/* StreamHandler.java --
A class for publishing log messages to instances of java.io.OutputStream
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
/**
* A <code>StreamHandler</code> publishes <code>LogRecords</code> to
* a instances of <code>java.io.OutputStream</code>.
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class StreamHandler
extends Handler
{
private OutputStream out;
private Writer writer;
/**
* Indicates the current state of this StreamHandler. The value
* should be one of STATE_FRESH, STATE_PUBLISHED, or STATE_CLOSED.
*/
private int streamState = STATE_FRESH;
/**
* streamState having this value indicates that the StreamHandler
* has been created, but the publish(LogRecord) method has not been
* called yet. If the StreamHandler has been constructed without an
* OutputStream, writer will be null, otherwise it is set to a
* freshly created OutputStreamWriter.
*/
private static final int STATE_FRESH = 0;
/**
* streamState having this value indicates that the publish(LocRecord)
* method has been called at least once.
*/
private static final int STATE_PUBLISHED = 1;
/**
* streamState having this value indicates that the close() method
* has been called.
*/
private static final int STATE_CLOSED = 2;
/**
* Creates a <code>StreamHandler</code> without an output stream.
* Subclasses can later use {@link
* #setOutputStream(java.io.OutputStream)} to associate an output
* stream with this StreamHandler.
*/
public StreamHandler()
{
this(null, null);
}
/**
* Creates a <code>StreamHandler</code> that formats log messages
* with the specified Formatter and publishes them to the specified
* output stream.
*
* @param out the output stream to which the formatted log messages
* are published.
*
* @param formatter the <code>Formatter</code> that will be used
* to format log messages.
*/
public StreamHandler(OutputStream out, Formatter formatter)
{
this(out, "java.util.logging.StreamHandler", Level.INFO,
formatter, SimpleFormatter.class);
}
StreamHandler(
OutputStream out,
String propertyPrefix,
Level defaultLevel,
Formatter formatter, Class defaultFormatterClass)
{
this.level = LogManager.getLevelProperty(propertyPrefix + ".level",
defaultLevel);
this.filter = (Filter) LogManager.getInstanceProperty(
propertyPrefix + ".filter",
/* must be instance of */ Filter.class,
/* default: new instance of */ null);
if (formatter != null)
this.formatter = formatter;
else
this.formatter = (Formatter) LogManager.getInstanceProperty(
propertyPrefix + ".formatter",
/* must be instance of */ Formatter.class,
/* default: new instance of */ defaultFormatterClass);
try
{
String enc = LogManager.getLogManager().getProperty(propertyPrefix
+ ".encoding");
/* make sure enc actually is a valid encoding */
if ((enc != null) && (enc.length() > 0))
new String(new byte[0], enc);
this.encoding = enc;
}
catch (Exception _)
{
}
if (out != null)
{
try
{
changeWriter(out, getEncoding());
}
catch (UnsupportedEncodingException uex)
{
/* This should never happen, since the validity of the encoding
* name has been checked above.
*/
throw new RuntimeException(uex.getMessage());
}
}
}
private void checkOpen()
{
if (streamState == STATE_CLOSED)
throw new IllegalStateException(this.toString() + " has been closed");
}
private void checkFresh()
{
checkOpen();
if (streamState != STATE_FRESH)
throw new IllegalStateException("some log records have been published to " + this);
}
private void changeWriter(OutputStream out, String encoding)
throws UnsupportedEncodingException
{
OutputStreamWriter writer;
/* The logging API says that a null encoding means the default
* platform encoding. However, java.io.OutputStreamWriter needs
* another constructor for the default platform encoding,
* passing null would throw an exception.
*/
if (encoding == null)
writer = new OutputStreamWriter(out);
else
writer = new OutputStreamWriter(out, encoding);
/* Closing the stream has side effects -- do this only after
* creating a new writer has been successful.
*/
if ((streamState != STATE_FRESH) || (this.writer != null))
close();
this.writer = writer;
this.out = out;
this.encoding = encoding;
streamState = STATE_FRESH;
}
/**
* Sets the character encoding which this handler uses for publishing
* log records. The encoding of a <code>StreamHandler</code> must be
* set before any log records have been published.
*
* @param encoding the name of a character encoding, or <code>null</code>
* for the default encoding.
*
* @throws SecurityException if a security manager exists and
* the caller is not granted the permission to control the
* the logging infrastructure.
*
* @exception IllegalStateException if any log records have been
* published to this <code>StreamHandler</code> before. Please
* be aware that this is a pecularity of the GNU implementation.
* While the API specification indicates that it is an error
* if the encoding is set after records have been published,
* it does not mandate any specific behavior for that case.
*/
public void setEncoding(String encoding)
throws SecurityException, UnsupportedEncodingException
{
/* The inherited implementation first checks whether the invoking
* code indeed has the permission to control the logging infra-
* structure, and throws a SecurityException if this was not the
* case.
*
* Next, it verifies that the encoding is supported and throws
* an UnsupportedEncodingExcpetion otherwise. Finally, it remembers
* the name of the encoding.
*/
super.setEncoding(encoding);
checkFresh();
/* If out is null, setEncoding is being called before an output
* stream has been set. In that case, we need to check that the
* encoding is valid, and remember it if this is the case. Since
* this is exactly what the inherited implementation of
* Handler.setEncoding does, we can delegate.
*/
if (out != null)
{
/* The logging API says that a null encoding means the default
* platform encoding. However, java.io.OutputStreamWriter needs
* another constructor for the default platform encoding, passing
* null would throw an exception.
*/
if (encoding == null)
writer = new OutputStreamWriter(out);
else
writer = new OutputStreamWriter(out, encoding);
}
}
/**
* Changes the output stream to which this handler publishes
* logging records.
*
* @throws SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*
* @throws NullPointerException if <code>out</code>
* is <code>null</code>.
*/
protected void setOutputStream(OutputStream out)
throws SecurityException
{
LogManager.getLogManager().checkAccess();
/* Throw a NullPointerException if out is null. */
out.getClass();
try
{
changeWriter(out, getEncoding());
}
catch (UnsupportedEncodingException ex)
{
/* This seems quite unlikely to happen, unless the underlying
* implementation of java.io.OutputStreamWriter changes its
* mind (at runtime) about the set of supported character
* encodings.
*/
throw new RuntimeException(ex.getMessage());
}
}
/**
* Publishes a <code>LogRecord</code> to the associated output
* stream, provided the record passes all tests for being loggable.
* The <code>StreamHandler</code> will localize the message of the
* log record and substitute any message parameters.
*
* <p>Most applications do not need to call this method directly.
* Instead, they will use use a {@link Logger}, which will create
* LogRecords and distribute them to registered handlers.
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>Handler</code> will be informed, but the caller
* of this method will not receive an exception.
*
* <p>If a log record is being published to a
* <code>StreamHandler</code> that has been closed earlier, the Sun
* J2SE 1.4 reference can be observed to silently ignore the
* call. The GNU implementation, however, intentionally behaves
* differently by informing the <code>ErrorManager</code> associated
* with this <code>StreamHandler</code>. Since the condition
* indicates a programming error, the programmer should be
* informed. It also seems extremely unlikely that any application
* would depend on the exact behavior in this rather obscure,
* erroneous case -- especially since the API specification does not
* prescribe what is supposed to happen.
*
* @param record the log event to be published.
*/
public void publish(LogRecord record)
{
String formattedMessage;
if (!isLoggable(record))
return;
if (streamState == STATE_FRESH)
{
try
{
writer.write(formatter.getHead(this));
}
catch (java.io.IOException ex)
{
reportError(null, ex, ErrorManager.WRITE_FAILURE);
return;
}
catch (Exception ex)
{
reportError(null, ex, ErrorManager.GENERIC_FAILURE);
return;
}
streamState = STATE_PUBLISHED;
}
try
{
formattedMessage = formatter.format(record);
}
catch (Exception ex)
{
reportError(null, ex, ErrorManager.FORMAT_FAILURE);
return;
}
try
{
writer.write(formattedMessage);
}
catch (Exception ex)
{
reportError(null, ex, ErrorManager.WRITE_FAILURE);
}
}
/**
* Checks whether or not a <code>LogRecord</code> would be logged
* if it was passed to this <code>StreamHandler</code> for publication.
*
* <p>The <code>StreamHandler</code> implementation first checks
* whether a writer is present and the handler's level is greater
* than or equal to the severity level threshold. In a second step,
* if a {@link Filter} has been installed, its {@link
* Filter#isLoggable(LogRecord) isLoggable} method is
* invoked. Subclasses of <code>StreamHandler</code> can override
* this method to impose their own constraints.
*
* @param record the <code>LogRecord</code> to be checked.
*
* @return <code>true</code> if <code>record</code> would
* be published by {@link #publish(LogRecord) publish},
* <code>false</code> if it would be discarded.
*
* @see #setLevel(Level)
* @see #setFilter(Filter)
* @see Filter#isLoggable(LogRecord)
*
* @throws NullPointerException if <code>record</code> is
* <code>null</code>. */
public boolean isLoggable(LogRecord record)
{
return (writer != null) && super.isLoggable(record);
}
/**
* Forces any data that may have been buffered to the underlying
* output device.
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>Handler</code> will be informed, but the caller
* of this method will not receive an exception.
*
* <p>If a <code>StreamHandler</code> that has been closed earlier
* is closed a second time, the Sun J2SE 1.4 reference can be
* observed to silently ignore the call. The GNU implementation,
* however, intentionally behaves differently by informing the
* <code>ErrorManager</code> associated with this
* <code>StreamHandler</code>. Since the condition indicates a
* programming error, the programmer should be informed. It also
* seems extremely unlikely that any application would depend on the
* exact behavior in this rather obscure, erroneous case --
* especially since the API specification does not prescribe what is
* supposed to happen.
*/
public void flush()
{
try
{
checkOpen();
if (writer != null)
writer.flush();
}
catch (Exception ex)
{
reportError(null, ex, ErrorManager.FLUSH_FAILURE);
}
}
/**
* Closes this <code>StreamHandler</code> after having forced any
* data that may have been buffered to the underlying output
* device.
*
* <p>As soon as <code>close</code> has been called,
* a <code>Handler</code> should not be used anymore. Attempts
* to publish log records, to flush buffers, or to modify the
* <code>Handler</code> in any other way may throw runtime
* exceptions after calling <code>close</code>.</p>
*
* <p>In case of an I/O failure, the <code>ErrorManager</code>
* of this <code>Handler</code> will be informed, but the caller
* of this method will not receive an exception.</p>
*
* <p>If a <code>StreamHandler</code> that has been closed earlier
* is closed a second time, the Sun J2SE 1.4 reference can be
* observed to silently ignore the call. The GNU implementation,
* however, intentionally behaves differently by informing the
* <code>ErrorManager</code> associated with this
* <code>StreamHandler</code>. Since the condition indicates a
* programming error, the programmer should be informed. It also
* seems extremely unlikely that any application would depend on the
* exact behavior in this rather obscure, erroneous case --
* especially since the API specification does not prescribe what is
* supposed to happen.
*
* @throws SecurityException if a security manager exists and
* the caller is not granted the permission to control
* the logging infrastructure.
*/
public void close()
throws SecurityException
{
LogManager.getLogManager().checkAccess();
try
{
/* Although flush also calls checkOpen, it catches
* any exceptions and reports them to the ErrorManager
* as flush failures. However, we want to report
* a closed stream as a close failure, not as a
* flush failure here. Therefore, we call checkOpen()
* before flush().
*/
checkOpen();
flush();
if (writer != null)
{
if (formatter != null)
{
/* Even if the StreamHandler has never published a record,
* it emits head and tail upon closing. An earlier version
* of the GNU Classpath implementation did not emitted
* anything. However, this had caused XML log files to be
* entirely empty instead of containing no log records.
*/
if (streamState == STATE_FRESH)
writer.write(formatter.getHead(this));
if (streamState != STATE_CLOSED)
writer.write(formatter.getTail(this));
}
streamState = STATE_CLOSED;
writer.close();
}
}
catch (Exception ex)
{
reportError(null, ex, ErrorManager.CLOSE_FAILURE);
}
}
}
-387
View File
@@ -1,387 +0,0 @@
/* XMLFormatter.java --
A class for formatting log messages into a standard XML format
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.logging;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.ResourceBundle;
/**
* An <code>XMLFormatter</code> formats LogRecords into
* a standard XML format.
*
* @author Sascha Brawer (brawer@acm.org)
*/
public class XMLFormatter
extends Formatter
{
/**
* Constructs a new XMLFormatter.
*/
public XMLFormatter()
{
}
/**
* The character sequence that is used to separate lines in the
* generated XML stream. Somewhat surprisingly, the Sun J2SE 1.4
* reference implementation always uses UNIX line endings, even on
* platforms that have different line ending conventions (i.e.,
* DOS). The GNU Classpath implementation does not replicates this
* bug.
*
* See also the Sun bug parade, bug #4462871,
* "java.util.logging.SimpleFormatter uses hard-coded line separator".
*/
private static final String lineSep = SimpleFormatter.lineSep;
/**
* A DateFormat for emitting time in the ISO 8601 format.
* Since the API specification of SimpleDateFormat does not talk
* about its thread-safety, we cannot share a singleton instance.
*/
private final SimpleDateFormat iso8601
= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
/**
* Appends a line consisting of indentation, opening element tag,
* element content, closing element tag and line separator to
* a StringBuffer, provided that the element content is
* actually existing.
*
* @param buf the StringBuffer to which the line will be appended.
*
* @param indent the indentation level.
*
* @param tag the element tag name, for instance <code>method</code>.
*
* @param content the element content, or <code>null</code> to
* have no output whatsoever appended to <code>buf</code>.
*/
private static void appendTag(StringBuffer buf, int indent,
String tag, String content)
{
int i;
if (content == null)
return;
for (i = 0; i < indent * 2; i++)
buf.append(' ');
buf.append("<");
buf.append(tag);
buf.append('>');
/* Append the content, but escape for XML by replacing
* '&', '<', '>' and all non-ASCII characters with
* appropriate escape sequences.
* The Sun J2SE 1.4 reference implementation does not
* escape non-ASCII characters. This is a bug in their
* implementation which has been reported in the Java
* bug parade as bug number (FIXME: Insert number here).
*/
for (i = 0; i < content.length(); i++)
{
char c = content.charAt(i);
switch (c)
{
case '&':
buf.append("&amp;");
break;
case '<':
buf.append("&lt;");
break;
case '>':
buf.append("&gt;");
break;
default:
if (((c >= 0x20) && (c <= 0x7e))
|| (c == /* line feed */ 10)
|| (c == /* carriage return */ 13))
buf.append(c);
else
{
buf.append("&#");
buf.append((int) c);
buf.append(';');
}
break;
} /* switch (c) */
} /* for i */
buf.append("</");
buf.append(tag);
buf.append(">");
buf.append(lineSep);
}
/**
* Appends a line consisting of indentation, opening element tag,
* numeric element content, closing element tag and line separator
* to a StringBuffer.
*
* @param buf the StringBuffer to which the line will be appended.
*
* @param indent the indentation level.
*
* @param tag the element tag name, for instance <code>method</code>.
*
* @param content the element content.
*/
private static void appendTag(StringBuffer buf, int indent,
String tag, long content)
{
appendTag(buf, indent, tag, Long.toString(content));
}
public String format(LogRecord record)
{
StringBuffer buf = new StringBuffer(400);
Level level = record.getLevel();
long millis = record.getMillis();
Object[] params = record.getParameters();
ResourceBundle bundle = record.getResourceBundle();
String message;
buf.append("<record>");
buf.append(lineSep);
appendTag(buf, 1, "date", iso8601.format(new Date(millis)));
appendTag(buf, 1, "millis", record.getMillis());
appendTag(buf, 1, "sequence", record.getSequenceNumber());
appendTag(buf, 1, "logger", record.getLoggerName());
if (level.isStandardLevel())
appendTag(buf, 1, "level", level.toString());
else
appendTag(buf, 1, "level", level.intValue());
appendTag(buf, 1, "class", record.getSourceClassName());
appendTag(buf, 1, "method", record.getSourceMethodName());
appendTag(buf, 1, "thread", record.getThreadID());
/* The Sun J2SE 1.4 reference implementation does not emit the
* message in localized form. This is in violation of the API
* specification. The GNU Classpath implementation intentionally
* replicates the buggy behavior of the Sun implementation, as
* different log files might be a big nuisance to users.
*/
try
{
record.setResourceBundle(null);
message = formatMessage(record);
}
finally
{
record.setResourceBundle(bundle);
}
appendTag(buf, 1, "message", message);
/* The Sun J2SE 1.4 reference implementation does not
* emit key, catalog and param tags. This is in violation
* of the API specification. The Classpath implementation
* intentionally replicates the buggy behavior of the
* Sun implementation, as different log files might be
* a big nuisance to users.
*
* FIXME: File a bug report with Sun. Insert bug number here.
*
*
* key = record.getMessage();
* if (key == null)
* key = "";
*
* if ((bundle != null) && !key.equals(message))
* {
* appendTag(buf, 1, "key", key);
* appendTag(buf, 1, "catalog", record.getResourceBundleName());
* }
*
* if (params != null)
* {
* for (int i = 0; i < params.length; i++)
* appendTag(buf, 1, "param", params[i].toString());
* }
*/
/* FIXME: We have no way to obtain the stacktrace before free JVMs
* support the corresponding method in java.lang.Throwable. Well,
* it would be possible to parse the output of printStackTrace,
* but this would be pretty kludgy. Instead, we postpose the
* implementation until Throwable has made progress.
*/
Throwable thrown = record.getThrown();
if (thrown != null)
{
buf.append(" <exception>");
buf.append(lineSep);
/* The API specification is not clear about what exactly
* goes into the XML record for a thrown exception: It
* could be the result of getMessage(), getLocalizedMessage(),
* or toString(). Therefore, it was necessary to write a
* Mauve testlet and run it with the Sun J2SE 1.4 reference
* implementation. It turned out that the we need to call
* toString().
*
* FIXME: File a bug report with Sun, asking for clearer
* specs.
*/
appendTag(buf, 2, "message", thrown.toString());
/* FIXME: The Logging DTD specifies:
*
* <!ELEMENT exception (message?, frame+)>
*
* However, java.lang.Throwable.getStackTrace() is
* allowed to return an empty array. So, what frame should
* be emitted for an empty stack trace? We probably
* should file a bug report with Sun, asking for the DTD
* to be changed.
*/
buf.append(" </exception>");
buf.append(lineSep);
}
buf.append("</record>");
buf.append(lineSep);
return buf.toString();
}
/**
* Returns a string that handlers are supposed to emit before
* the first log record. The base implementation returns an
* empty string, but subclasses such as {@link XMLFormatter}
* override this method in order to provide a suitable header.
*
* @return a string for the header.
*
* @param handler the handler which will prepend the returned
* string in front of the first log record. This method
* will inspect certain properties of the handler, for
* example its encoding, in order to construct the header.
*/
public String getHead(Handler h)
{
StringBuffer buf;
String encoding;
buf = new StringBuffer(80);
buf.append("<?xml version=\"1.0\" encoding=\"");
encoding = h.getEncoding();
/* file.encoding is a system property with the Sun JVM, indicating
* the platform-default file encoding. Unfortunately, the API
* specification for java.lang.System.getProperties() does not
* list this property.
*/
if (encoding == null)
encoding = System.getProperty("file.encoding");
/* Since file.encoding is not listed with the API specification of
* java.lang.System.getProperties(), there might be some VMs that
* do not define this system property. Therefore, we use UTF-8 as
* a reasonable default. Please note that if the platform encoding
* uses the same codepoints as US-ASCII for the US-ASCII character
* set (e.g, 65 for A), it does not matter whether we emit the
* wrong encoding into the XML header -- the GNU Classpath will
* emit XML escape sequences like &#1234; for any non-ASCII
* character. Virtually all character encodings use the same code
* points as US-ASCII for ASCII characters. Probably, EBCDIC is
* the only exception.
*/
if (encoding == null)
encoding = "UTF-8";
/* On Windows XP localized for Swiss German (this is one of
* my [Sascha Brawer's] test machines), the default encoding
* has the canonical name "windows-1252". The "historical" name
* of this encoding is "Cp1252" (see the Javadoc for the class
* java.nio.charset.Charset for the distinction). Now, that class
* does have a method for mapping historical to canonical encoding
* names. However, if we used it here, we would be come dependent
* on java.nio.*, which was only introduced with J2SE 1.4.
* Thus, we do this little hack here. As soon as Classpath supports
* java.nio.charset.CharSet, this hack should be replaced by
* code that correctly canonicalizes the encoding name.
*/
if ((encoding.length() > 2) && encoding.startsWith("Cp"))
encoding = "windows-" + encoding.substring(2);
buf.append(encoding);
buf.append("\" standalone=\"no\"?>");
buf.append(lineSep);
/* SYSTEM is not a fully qualified URL so that validating
* XML parsers do not need to connect to the Internet in
* order to read in a log file. See also the Sun Bug Parade,
* bug #4372790, "Logging APIs: need to use relative URL for XML
* doctype".
*/
buf.append("<!DOCTYPE log SYSTEM \"logger.dtd\">");
buf.append(lineSep);
buf.append("<log>");
buf.append(lineSep);
return buf.toString();
}
public String getTail(Handler h)
{
return "</log>" + lineSep;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,104 +0,0 @@
/* BackingStoreException.java - chained exception thrown when backing store
fails
Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.prefs;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* Chained exception thrown when backing store fails. This exception is
* only thrown from methods that actually have to access the backing store,
* such as <code>clear(), keys(), childrenNames(), nodeExists(), removeNode(),
* flush(), sync(), exportNode(), exportSubTree()</code>; normal operations
* do not throw BackingStoreExceptions.
*
* <p>Note that although this class inherits the Serializable interface, an
* attempt to serialize will fail with a <code>NotSerializableException</code>.
*
* @author Mark Wielaard (mark@klomp.org)
* @since 1.4
* @status updated to 1.4
*/
public class BackingStoreException extends Exception
{
static final long serialVersionUID = 859796500401108469L;
/**
* Creates a new exception with a descriptive message.
*
* @param message the message
*/
public BackingStoreException(String message)
{
super(message);
}
/**
* Create a new exception with the given cause.
*
* @param cause the cause
*/
public BackingStoreException(Throwable cause)
{
super(cause);
}
/**
* This class should not be serialized.
*
* @param o the output stream
*/
private void writeObject(ObjectOutputStream o) throws NotSerializableException
{
throw new NotSerializableException
("java.util.prefs.BackingStoreException");
}
/**
* This class should not be serialized.
*
* @param i the input stream
*/
private void readObject(ObjectInputStream i) throws NotSerializableException
{
throw new NotSerializableException
("java.util.prefs.BackingStoreException");
}
}
@@ -1,116 +0,0 @@
/* InvalidPreferencesFormatException - indicates reading prefs from stream
failed
Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.prefs;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* Indicates reading prefs from stream failed. Thrown by the
* <code>importPreferences()</code> method when the supplied input stream
* could not be read because it was not in the correct XML format.
*
* <p>Note that although this class inherits the Serializable interface, an
* attempt to serialize will fail with a <code>NotSerializableException</code>.
* </p>
*
* @author Mark Wielaard (mark@klomp.org)
* @see Preferences
* @since 1.4
* @status updated to 1.4
*/
public class InvalidPreferencesFormatException extends Exception
{
static final long serialVersionUID = -791715184232119669L;
/**
* Creates a new exception with a descriptive message. The cause remains
* uninitialized.
*
* @param message the message
*/
public InvalidPreferencesFormatException(String message)
{
super(message);
}
/**
* Creates a new exception with the given cause.
*
* @param cause the cause
*/
public InvalidPreferencesFormatException(Throwable cause)
{
super(cause);
}
/**
* Creates a new exception with a descriptive message and a cause.
*
* @param message the message
* @param cause the cause
*/
public InvalidPreferencesFormatException(String message, Throwable cause)
{
super(message, cause);
}
/**
* This class should not be serialized.
*
* @param o the output stream
*/
private void writeObject(ObjectOutputStream o) throws NotSerializableException
{
throw new NotSerializableException
("java.util.prefs.InvalidPreferencesFormatException");
}
/**
* This class should not be serialized.
*
* @param i the input stream
*/
private void readObject(ObjectInputStream i) throws NotSerializableException
{
throw new NotSerializableException
("java.util.prefs.InvalidPreferencesFormatException");
}
}
@@ -1,91 +0,0 @@
/* NodeChangeEvent - ObjectEvent fired when a Preference node is added/removed
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.prefs;
import java.util.EventObject;
/**
* ObjectEvent fired when a Preference node is added/removed.
* This event is only generated when a new subnode is added or a subnode is
* removed from a preference node. Changes in the entries of a preference node
* are indicated with a <code>PreferenceChangeEvent</code>.
*
* @since 1.4
* @author Mark Wielaard (mark@klomp.org)
*/
public class NodeChangeEvent extends EventObject {
private static final long serialVersionUID =8068949086596572957L;
/**
* The sub node that was added or removed.
* Defined transient just like <code>EventObject.source</code> since
* this object should be serializable, but Preferences is in general not
* serializable.
*/
private final transient Preferences child;
/**
* Creates a new NodeChangeEvent.
*
* @param parentNode The source preference node from which a subnode was
* added or removed
* @param childNode The preference node that was added or removed
*/
public NodeChangeEvent(Preferences parentNode, Preferences childNode) {
super(parentNode);
child = childNode;
}
/**
* Returns the source parent preference node from which a subnode was
* added or removed.
*/
public Preferences getParent() {
return (Preferences) source;
}
/**
* Returns the child preference subnode that was added or removed.
* To see wether it is still a valid preference node one has to call
* <code>event.getChild().nodeExists("")</code>.
*/
public Preferences getChild() {
return child;
}
}
@@ -1,64 +0,0 @@
/* NodeChangeListener - EventListener for Preferences node addition/removal
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.prefs;
import java.util.EventListener;
/**
* EventListener for Preferences node addition/removal.
* <p>
* Note that these events are only generated for the addition and removal
* of sub nodes from the preference node. Entry changes in the preference
* node can be monitored with a <code>PreferenceChangeListener</code>.
*
* @since 1.4
* @author Mark Wielaard (mark@klomp.org)
*/
public interface NodeChangeListener extends EventListener {
/**
* Fired when a sub node is added to the preference node.
*/
void childAdded(NodeChangeEvent event);
/**
* Fired when a sub node is removed from the preference node.
*/
void childRemoved(NodeChangeEvent event);
}
@@ -1,105 +0,0 @@
/* PreferenceChangeEvent - ObjectEvent fired when a Preferences entry changes
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.prefs;
import java.util.EventObject;
/**
* ObjectEvent fired when a Preferences entry changes.
* This event is generated when a entry is added, changed or removed.
* When an entry is removed then <code>getNewValue</code> will return null.
* <p>
* Preference change events are only generated for entries in one particular
* preference node. Notification of subnode addition/removal is given by a
* <code>NodeChangeEvent</code>.
*
* @since 1.4
* @author Mark Wielaard (mark@klomp.org)
*/
public class PreferenceChangeEvent extends EventObject {
private static final long serialVersionUID = 793724513368024975L;
/**
* The key of the changed entry.
*/
private final String key;
/**
* The new value of the changed entry, or null when the entry was removed.
*/
private final String newValue;
/**
* Creates a new PreferenceChangeEvent.
*
* @param node The source preference node for which an entry was added,
* changed or removed
* @param key The key of the entry that was added, changed or removed
* @param value The new value of the entry that was added or changed, or
* null when the entry was removed
*/
public PreferenceChangeEvent(Preferences node, String key, String value) {
super(node);
this.key = key;
this.newValue = value;
}
/**
* Returns the source Preference node from which an entry was added,
* changed or removed.
*/
public Preferences getNode() {
return (Preferences) source;
}
/**
* Returns the key of the entry that was added, changed or removed.
*/
public String getKey() {
return key;
}
/**
* Returns the new value of the entry that was added or changed, or
* returns null when the entry was removed.
*/
public String getNewValue() {
return newValue;
}
}
@@ -1,60 +0,0 @@
/* PreferenceChangeListener - EventListener for Preferences entry changes
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.prefs;
import java.util.EventListener;
/**
* EventListener for Preferences entry addition, change or removal.
* <p>
* Preference change events are only generated for entries in one particular
* preference node. Notification of subnode addition/removal can be monitored
* with a <code>NodeChangeListener</code>.
*
* @since 1.4
* @author Mark Wielaard (mark@klomp.org)
*/
public interface PreferenceChangeListener extends EventListener {
/**
* Fired when a entry has been added, changed or removed from the
* preference node.
*/
void preferenceChange(PreferenceChangeEvent event);
}
-668
View File
@@ -1,668 +0,0 @@
/* Preferences -- Preference node containing key value entries and subnodes
Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.prefs;
import gnu.java.util.prefs.NodeReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
/**
* Preference node containing key value entries and subnodes.
* <p>
* There are two preference node trees, a system tree which can be accessed
* by calling <code>systemRoot()</code> containing system preferences usefull
* for all users, and a user tree that can be accessed by calling
* <code>userRoot()</code> containing preferences that can differ between
* different users. How different users are identified is implementation
* depended. It can be determined by Thread, Access Control Context or Subject.
* <p>
* This implementation uses the "java.util.prefs.PreferencesFactory" system
* property to find a class that implement <code>PreferencesFactory</code>
* and initialized that class (if it has a public no arguments contructor)
* to get at the actual system or user root. If the system property is not set,
* or the class cannot be initialized it uses the default implementation
* <code>gnu.java.util.prefs.FileBasedFactory</code>.
* <p>
* Besides the two static method above to get the roots of the system and user
* preference node trees there are also two convenience methods to access the
* default preference node for a particular package an object is in. These are
* <code>userNodeForPackage()</code> and <code>systemNodeForPackage()</code>.
* Both methods take an Object as an argument so accessing preferences values
* can be as easy as calling <code>Preferences.userNodeForPackage(this)</code>.
* <p>
* Note that if a security manager is installed all static methods check for
* <code>RuntimePermission("preferences")</code>. But if this permission is
* given to the code then it can access and change all (user) preference nodes
* and entries. So you should be carefull not to store to sensitive information
* or make security decissions based on preference values since there is no
* more fine grained control over what preference values can be changed once
* code has been given the correct runtime permission.
* <p>
* XXX
*
* @since 1.4
* @author Mark Wielaard (mark@klomp.org)
*/
public abstract class Preferences {
// Static Fields
/**
* Default PreferencesFactory class used when the system property
* "java.util.prefs.PreferencesFactory" is not set.
* <p>
* XXX - Currently set to MemoryBasedFactory, should be changed
* when FileBasedPreferences backend works.
*/
private static final String defaultFactoryClass
= "gnu.java.util.prefs.MemoryBasedFactory";
/** Permission needed to access system or user root. */
private static final Permission prefsPermission
= new RuntimePermission("preferences");
/**
* The preferences factory object that supplies the system and user root.
* Set and returned by the getFactory() method.
*/
private static PreferencesFactory factory;
/** Maximum node name length. 80 characters. */
public static final int MAX_NAME_LENGTH = 80;
/** Maximum entry key length. 80 characters. */
public static final int MAX_KEY_LENGTH = 80;
/** Maximum entry value length. 8192 characters. */
public static final int MAX_VALUE_LENGTH = 8192;
// Constructors
/**
* Creates a new Preferences node. Can only be used by subclasses.
* Empty implementation.
*/
protected Preferences() {}
// Static methods
/**
* Returns the system preferences root node containing usefull preferences
* for all users. It is save to cache this value since it should always
* return the same preference node.
*
* @return the root system preference node
* @exception SecurityException when a security manager is installed and
* the caller does not have <code>RuntimePermission("preferences")</code>.
*/
public static Preferences systemRoot() throws SecurityException {
// Get the preferences factory and check for permission
PreferencesFactory factory = getFactory();
return factory.systemRoot();
}
/**
* Returns the user preferences root node containing preferences for the
* the current user. How different users are identified is implementation
* depended. It can be determined by Thread, Access Control Context or
* Subject.
*
* @return the root user preference node
* @exception SecurityException when a security manager is installed and
* the caller does not have <code>RuntimePermission("preferences")</code>.
*/
public static Preferences userRoot() throws SecurityException {
// Get the preferences factory and check for permission
PreferencesFactory factory = getFactory();
return factory.userRoot();
}
/**
* Private helper method for <code>systemRoot()</code> and
* <code>userRoot()</code>. Checks security permission and instantiates the
* correct factory if it has not yet been set.
* <p>
* When the preferences factory has not yet been set this method first
* tries to get the system propery "java.util.prefs.PreferencesFactory"
* and tries to initializes that class. If the system property is not set
* or initialization fails it returns an instance of the default factory
* <code>gnu.java.util.prefs.FileBasedPreferencesFactory</code>.
*
* @return the preferences factory to use
* @exception SecurityException when a security manager is installed and
* the caller does not have <code>RuntimePermission("preferences")</code>.
*/
private static PreferencesFactory getFactory() throws SecurityException {
// First check for permission
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(prefsPermission);
}
// Get the factory
if (factory == null) {
// Caller might not have enough permissions
factory = (PreferencesFactory) AccessController.doPrivileged(
new PrivilegedAction() {
public Object run() {
PreferencesFactory pf = null;
String className = System.getProperty
("java.util.prefs.PreferencesFactory");
if (className != null) {
try {
Class fc = Class.forName(className);
Object o = fc.newInstance();
pf = (PreferencesFactory) o;
} catch (ClassNotFoundException cnfe)
{/*ignore*/}
catch (InstantiationException ie)
{/*ignore*/}
catch (IllegalAccessException iae)
{/*ignore*/}
catch (ClassCastException cce)
{/*ignore*/}
}
return pf;
}
});
// Still no factory? Use our default.
if (factory == null)
{
try
{
Class cls = Class.forName (defaultFactoryClass);
factory = (PreferencesFactory) cls.newInstance();
}
catch (Exception e)
{
throw new RuntimeException ("Couldn't load default factory"
+ " '"+ defaultFactoryClass +"'");
// XXX - when using 1.4 compatible throwables add cause
}
}
}
return factory;
}
/**
* Returns the system preferences node for the package of an object.
* The package node name of the object is determined by dropping the
* class name of the object of the fully quallified class name and
* replacing all '.' to '/' in the package name. If the class of the
* object has no package then the package node name is "&lt;unnamed&gt;".
* The returened node is <code>systemRoot().node(packageNodeName)</code>.
*
* @param o Object whose default system preference node is requested
* @returns system preferences node that should be used by object o
* @exception SecurityException when a security manager is installed and
* the caller does not have <code>RuntimePermission("preferences")</code>.
*/
public static Preferences systemNodeForPackage(Class c)
throws SecurityException
{
return nodeForPackage(c, systemRoot());
}
/**
* Returns the user preferences node for the package of an object.
* The package node name of the object is determined by dropping the
* class name of the object of the fully quallified class name and
* replacing all '.' to '/' in the package name. If the class of the
* object has no package then the package node name is "&lt;unnamed&gt;".
* The returened node is <code>userRoot().node(packageNodeName)</code>.
*
* @param o Object whose default user preference node is requested
* @returns user preferences node that should be used by object o
* @exception SecurityException when a security manager is installed and
* the caller does not have <code>RuntimePermission("preferences")</code>.
*/
public static Preferences userNodeForPackage(Class c)
throws SecurityException
{
return nodeForPackage(c, userRoot());
}
/**
* Private helper method for <code>systemNodeForPackage()</code> and
* <code>userNodeForPackage()</code>. Given the correct system or user
* root it returns the correct Preference node for the package node name
* of the given object.
*/
private static Preferences nodeForPackage(Class c, Preferences root) {
// Get the package path
String className = c.getName();
String packagePath;
int index = className.lastIndexOf('.');
if(index == -1) {
packagePath = "<unnamed>";
} else {
packagePath = className.substring(0,index).replace('.','/');
}
return root.node(packagePath);
}
/**
* XXX
*/
public static void importPreferences(InputStream is)
throws InvalidPreferencesFormatException,
IOException
{
PreferencesFactory factory = getFactory();
NodeReader reader = new NodeReader(is, factory);
reader.importPreferences();
}
// abstract methods (identification)
/**
* Returns the absolute path name of this preference node.
* The absolute path name of a node is the path name of its parent node
* plus a '/' plus its own name. If the node is the root node and has no
* parent then its name is "" and its absolute path name is "/".
*/
public abstract String absolutePath();
/**
* Returns true if this node comes from the user preferences tree, false
* if it comes from the system preferences tree.
*/
public abstract boolean isUserNode();
/**
* Returns the name of this preferences node. The name of the node cannot
* be null, can be mostly 80 characters and cannot contain any '/'
* characters. The root node has as name "".
*/
public abstract String name();
/**
* Returns the String given by
* <code>
* (isUserNode() ? "User":"System") + " Preference Node: " + absolutePath()
* </code>
*/
public abstract String toString();
// abstract methods (navigation)
/**
* Returns all the direct sub nodes of this preferences node.
* Needs access to the backing store to give a meaningfull answer.
*
* @exception BackingStoreException when the backing store cannot be
* reached
* @exception IllegalStateException when this node has been removed
*/
public abstract String[] childrenNames() throws BackingStoreException;
/**
* Returns a sub node of this preferences node if the given path is
* relative (does not start with a '/') or a sub node of the root
* if the path is absolute (does start with a '/').
*
* @exception IllegalStateException if this node has been removed
* @exception IllegalArgumentException if the path contains two or more
* consecutive '/' characters, ends with a '/' charactor and is not the
* string "/" (indicating the root node) or any name on the path is more
* then 80 characters long
*/
public abstract Preferences node(String path);
/**
* Returns true if the node that the path points to exists in memory or
* in the backing store. Otherwise it returns false or an exception is
* thrown. When this node is removed the only valid parameter is the
* empty string (indicating this node), the return value in that case
* will be false.
*
* @exception BackingStoreException when the backing store cannot be
* reached
* @exception IllegalStateException if this node has been removed
* and the path is not the empty string (indicating this node)
* @exception IllegalArgumentException if the path contains two or more
* consecutive '/' characters, ends with a '/' charactor and is not the
* string "/" (indicating the root node) or any name on the path is more
* then 80 characters long
*/
public abstract boolean nodeExists(String path)
throws BackingStoreException;
/**
* Returns the parent preferences node of this node or null if this is
* the root of the preferences tree.
*
* @exception IllegalStateException if this node has been removed
*/
public abstract Preferences parent();
// abstract methods (export)
/**
* XXX
*/
public abstract void exportNode(OutputStream os)
throws BackingStoreException,
IOException;
/**
* XXX
*/
public abstract void exportSubtree(OutputStream os)
throws BackingStoreException,
IOException;
// abstract methods (preference entry manipulation)
/**
* Returns an (possibly empty) array with all the keys of the preference
* entries of this node.
*
* @exception BackingStoreException when the backing store cannot be
* reached
* @exception IllegalStateException if this node has been removed
*/
public abstract String[] keys() throws BackingStoreException;
/**
* Returns the value associated with the key in this preferences node. If
* the default value of the key cannot be found in the preferences node
* entries or something goes wrong with the backing store the supplied
* default value is returned.
*
* @exception IllegalArgumentException if key is larger then 80 characters
* @exception IllegalStateException if this node has been removed
* @exception NullPointerException if key is null
*/
public abstract String get(String key, String defaultVal);
/**
* Convenience method for getting the given entry as a boolean.
* When the string representation of the requested entry is either
* "true" or "false" (ignoring case) then that value is returned,
* otherwise the given default boolean value is returned.
*
* @exception IllegalArgumentException if key is larger then 80 characters
* @exception IllegalStateException if this node has been removed
* @exception NullPointerException if key is null
*/
public abstract boolean getBoolean(String key, boolean defaultVal);
/**
* Convenience method for getting the given entry as a byte array.
* When the string representation of the requested entry is a valid
* Base64 encoded string (without any other characters, such as newlines)
* then the decoded Base64 string is returned as byte array,
* otherwise the given default byte array value is returned.
*
* @exception IllegalArgumentException if key is larger then 80 characters
* @exception IllegalStateException if this node has been removed
* @exception NullPointerException if key is null
*/
public abstract byte[] getByteArray(String key, byte[] defaultVal);
/**
* Convenience method for getting the given entry as a double.
* When the string representation of the requested entry can be decoded
* with <code>Double.parseDouble()</code> then that double is returned,
* otherwise the given default double value is returned.
*
* @exception IllegalArgumentException if key is larger then 80 characters
* @exception IllegalStateException if this node has been removed
* @exception NullPointerException if key is null
*/
public abstract double getDouble(String key, double defaultVal);
/**
* Convenience method for getting the given entry as a float.
* When the string representation of the requested entry can be decoded
* with <code>Float.parseFloat()</code> then that float is returned,
* otherwise the given default float value is returned.
*
* @exception IllegalArgumentException if key is larger then 80 characters
* @exception IllegalStateException if this node has been removed
* @exception NullPointerException if key is null
*/
public abstract float getFloat(String key, float defaultVal);
/**
* Convenience method for getting the given entry as an integer.
* When the string representation of the requested entry can be decoded
* with <code>Integer.parseInt()</code> then that integer is returned,
* otherwise the given default integer value is returned.
*
* @exception IllegalArgumentException if key is larger then 80 characters
* @exception IllegalStateException if this node has been removed
* @exception NullPointerException if key is null
*/
public abstract int getInt(String key, int defaultVal);
/**
* Convenience method for getting the given entry as a long.
* When the string representation of the requested entry can be decoded
* with <code>Long.parseLong()</code> then that long is returned,
* otherwise the given default long value is returned.
*
* @exception IllegalArgumentException if key is larger then 80 characters
* @exception IllegalStateException if this node has been removed
* @exception NullPointerException if key is null
*/
public abstract long getLong(String key, long defaultVal);
/**
* Sets the value of the given preferences entry for this node.
* Key and value cannot be null, the key cannot exceed 80 characters
* and the value cannot exceed 8192 characters.
* <p>
* The result will be immediatly visible in this VM, but may not be
* immediatly written to the backing store.
*
* @exception NullPointerException if either key or value are null
* @exception IllegalArgumentException if either key or value are to large
* @exception IllegalStateException when this node has been removed
*/
public abstract void put(String key, String value);
/**
* Convenience method for setting the given entry as a boolean.
* The boolean is converted with <code>Boolean.toString(value)</code>
* and then stored in the preference entry as that string.
*
* @exception NullPointerException if key is null
* @exception IllegalArgumentException if the key length is to large
* @exception IllegalStateException when this node has been removed
*/
public abstract void putBoolean(String key, boolean value);
/**
* Convenience method for setting the given entry as an array of bytes.
* The byte array is converted to a Base64 encoded string
* and then stored in the preference entry as that string.
* <p>
* Note that a byte array encoded as a Base64 string will be about 1.3
* times larger then the original length of the byte array, which means
* that the byte array may not be larger about 6 KB.
*
* @exception NullPointerException if either key or value are null
* @exception IllegalArgumentException if either key or value are to large
* @exception IllegalStateException when this node has been removed
*/
public abstract void putByteArray(String key, byte[] value);
/**
* Convenience method for setting the given entry as a double.
* The double is converted with <code>Double.toString(double)</code>
* and then stored in the preference entry as that string.
*
* @exception NullPointerException if the key is null
* @exception IllegalArgumentException if the key length is to large
* @exception IllegalStateException when this node has been removed
*/
public abstract void putDouble(String key, double value);
/**
* Convenience method for setting the given entry as a float.
* The float is converted with <code>Float.toString(float)</code>
* and then stored in the preference entry as that string.
*
* @exception NullPointerException if the key is null
* @exception IllegalArgumentException if the key length is to large
* @exception IllegalStateException when this node has been removed
*/
public abstract void putFloat(String key, float value);
/**
* Convenience method for setting the given entry as an integer.
* The integer is converted with <code>Integer.toString(int)</code>
* and then stored in the preference entry as that string.
*
* @exception NullPointerException if the key is null
* @exception IllegalArgumentException if the key length is to large
* @exception IllegalStateException when this node has been removed
*/
public abstract void putInt(String key, int value);
/**
* Convenience method for setting the given entry as a long.
* The long is converted with <code>Long.toString(long)</code>
* and then stored in the preference entry as that string.
*
* @exception NullPointerException if the key is null
* @exception IllegalArgumentException if the key length is to large
* @exception IllegalStateException when this node has been removed
*/
public abstract void putLong(String key, long value);
/**
* Removes the preferences entry from this preferences node.
* <p>
* The result will be immediatly visible in this VM, but may not be
* immediatly written to the backing store.
*
* @exception NullPointerException if the key is null
* @exception IllegalArgumentException if the key length is to large
* @exception IllegalStateException when this node has been removed
*/
public abstract void remove(String key);
// abstract methods (preference node manipulation)
/**
* Removes all entries from this preferences node. May need access to the
* backing store to get and clear all entries.
* <p>
* The result will be immediatly visible in this VM, but may not be
* immediatly written to the backing store.
*
* @exception BackingStoreException when the backing store cannot be
* reached
* @exception IllegalStateException if this node has been removed
*/
public abstract void clear() throws BackingStoreException;
/**
* Writes all preference changes on this and any subnode that have not
* yet been written to the backing store. This has no effect on the
* preference entries in this VM, but it makes sure that all changes
* are visible to other programs (other VMs might need to call the
* <code>sync()</code> method to actually see the changes to the backing
* store.
*
* @exception BackingStoreException when the backing store cannot be
* reached
* @exception IllegalStateException if this node has been removed
*/
public abstract void flush() throws BackingStoreException;
/**
* Writes and reads all preference changes to and from this and any
* subnodes. This makes sure that all local changes are written to the
* backing store and that all changes to the backing store are visible
* in this preference node (and all subnodes).
*
* @exception BackingStoreException when the backing store cannot be
* reached
* @exception IllegalStateException if this node has been removed
*/
public abstract void sync() throws BackingStoreException;
/**
* Removes this and all subnodes from the backing store and clears all
* entries. After removal this instance will not be useable (except for
* a few methods that don't throw a <code>InvalidStateException</code>),
* even when a new node with the same path name is created this instance
* will not be usable again. The root (system or user) may never be removed.
* <p>
* Note that according to the specification an implementation may delay
* removal of the node from the backing store till the <code>flush()</code>
* method is called. But the <code>flush()</code> method may throw a
* <code>IllegalStateException</code> when the node has been removed.
* So most implementations will actually remove the node and any subnodes
* from the backing store immediatly.
*
* @exception BackingStoreException when the backing store cannot be
* reached
* @exception IllegalStateException if this node has already been removed
* @exception UnsupportedOperationException if this is a root node
*/
public abstract void removeNode() throws BackingStoreException;
// abstract methods (listeners)
public abstract void addNodeChangeListener(NodeChangeListener listener);
public abstract void addPreferenceChangeListener
(PreferenceChangeListener listener);
public abstract void removeNodeChangeListener(NodeChangeListener listener);
public abstract void removePreferenceChangeListener
(PreferenceChangeListener listener);
}
@@ -1,65 +0,0 @@
/* PreferencesFactory - Preferences system and user root factory interface
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.prefs;
/**
* Preferences system and user root factory interface. Defines how to get
* to the system and user root preferences objects. Should be implemented by
* new preferences backends.
*
* @since 1.4
* @author Mark Wielaard (mark@klomp.org)
*/
public interface PreferencesFactory {
/**
* Returns the system root preferences node. Should always return the
* same object.
*/
Preferences systemRoot();
/**
* Returns the user root preferences node. May return different objects
* depending on the user that called this method. The user may for example
* be determined by the current Thread or the Subject associated with the
* current AccessControllContext.
*/
Preferences userRoot();
}
-301
View File
@@ -1,301 +0,0 @@
/* Matcher.java -- Instance of a regular expression applied to a char sequence.
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.regex;
import gnu.regexp.REMatch;
/**
* Instance of a regular expression applied to a char sequence.
*
* @since 1.4
*/
public final class Matcher
{
private Pattern pattern;
private CharSequence input;
private int position;
private int appendPosition;
private REMatch match;
Matcher(Pattern pattern, CharSequence input)
{
this.pattern = pattern;
this.input = input;
}
/**
* @param sb The target string buffer
* @param replacement The replacement string
*
* @exception IllegalStateException If no match has yet been attempted,
* or if the previous match operation failed
* @exception IndexOutOfBoundsException If the replacement string refers
* to a capturing group that does not exist in the pattern
*/
public Matcher appendReplacement (StringBuffer sb, String replacement)
throws IllegalStateException
{
assertMatchOp();
sb.append(input.subSequence(appendPosition,
match.getStartIndex()).toString());
sb.append(match.substituteInto(replacement));
appendPosition = match.getEndIndex();
return this;
}
/**
* @param sb The target string buffer
*/
public StringBuffer appendTail (StringBuffer sb)
{
sb.append(input.subSequence(appendPosition, input.length()).toString());
return sb;
}
/**
* @exception IllegalStateException If no match has yet been attempted,
* or if the previous match operation failed
*/
public int end ()
throws IllegalStateException
{
assertMatchOp();
return match.getEndIndex();
}
/**
* @param group The index of a capturing group in this matcher's pattern
*
* @exception IllegalStateException If no match has yet been attempted,
* or if the previous match operation failed
* @exception IndexOutOfBoundsException If the replacement string refers
* to a capturing group that does not exist in the pattern
*/
public int end (int group)
throws IllegalStateException
{
assertMatchOp();
return match.getEndIndex(group);
}
public boolean find ()
{
boolean first = (match == null);
match = pattern.getRE().getMatch(input, position);
if (match != null)
{
int endIndex = match.getEndIndex();
// Are we stuck at the same position?
if (!first && endIndex == position)
{
match = null;
// Not at the end of the input yet?
if (position < input.length() - 1)
{
position++;
return find(position);
}
else
return false;
}
position = endIndex;
return true;
}
return false;
}
/**
* @param start The index to start the new pattern matching
*
* @exception IndexOutOfBoundsException If the replacement string refers
* to a capturing group that does not exist in the pattern
*/
public boolean find (int start)
{
match = pattern.getRE().getMatch(input, start);
if (match != null)
{
position = match.getEndIndex();
return true;
}
return false;
}
/**
* @exception IllegalStateException If no match has yet been attempted,
* or if the previous match operation failed
*/
public String group ()
{
assertMatchOp();
return match.toString();
}
/**
* @param group The index of a capturing group in this matcher's pattern
*
* @exception IllegalStateException If no match has yet been attempted,
* or if the previous match operation failed
* @exception IndexOutOfBoundsException If the replacement string refers
* to a capturing group that does not exist in the pattern
*/
public String group (int group)
throws IllegalStateException
{
assertMatchOp();
return match.toString(group);
}
/**
* @param replacement The replacement string
*/
public String replaceFirst (String replacement)
{
reset();
// Semantics might not quite match
return pattern.getRE().substitute(input, replacement, position);
}
/**
* @param replacement The replacement string
*/
public String replaceAll (String replacement)
{
reset();
return pattern.getRE().substituteAll(input, replacement, position);
}
public int groupCount ()
{
return pattern.getRE().getNumSubs();
}
public boolean lookingAt ()
{
match = pattern.getRE().getMatch(input, 0);
if (match != null)
{
if (match.getStartIndex() == 0)
{
position = match.getEndIndex();
return true;
}
match = null;
}
return false;
}
/**
* Attempts to match the entire input sequence against the pattern.
*
* If the match succeeds then more information can be obtained via the
* start, end, and group methods.
*
* @see #start
* @see #end
* @see #group
*/
public boolean matches ()
{
if (lookingAt())
{
if (position == input.length())
return true;
match = null;
}
return false;
}
/**
* Returns the Pattern that is interpreted by this Matcher
*/
public Pattern pattern ()
{
return pattern;
}
public Matcher reset ()
{
position = 0;
match = null;
return this;
}
/**
* @param input The new input character sequence
*/
public Matcher reset (CharSequence input)
{
this.input = input;
return reset();
}
/**
* @param group The index of a capturing group in this matcher's pattern
*
* @exception IllegalStateException If no match has yet been attempted,
* or if the previous match operation failed
*/
public int start ()
throws IllegalStateException
{
assertMatchOp();
return match.getStartIndex();
}
/**
* @param group The index of a capturing group in this matcher's pattern
*
* @exception IllegalStateException If no match has yet been attempted,
* or if the previous match operation failed
* @exception IndexOutOfBoundsException If the replacement string refers
* to a capturing group that does not exist in the pattern
*/
public int start (int group)
throws IllegalStateException
{
assertMatchOp();
return match.getStartIndex(group);
}
private void assertMatchOp()
{
if (match == null) throw new IllegalStateException();
}
}
-253
View File
@@ -1,253 +0,0 @@
/* Pattern.java -- Compiled regular expression ready to be applied.
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.regex;
import gnu.regexp.RE;
import gnu.regexp.REException;
import gnu.regexp.RESyntax;
import java.io.Serializable;
import java.util.ArrayList;
/**
* Compiled regular expression ready to be applied.
*
* @since 1.4
*/
public final class Pattern implements Serializable
{
private static final long serialVersionUID = 5073258162644648461L;
public static final int CANON_EQ = 128;
public static final int CASE_INSENSITIVE = 2;
public static final int COMMENTS = 4;
public static final int DOTALL = 32;
public static final int MULTILINE = 8;
public static final int UNICODE_CASE = 64;
public static final int UNIX_LINES = 1;
private final String regex;
private final int flags;
private final RE re;
private Pattern (String regex, int flags)
throws PatternSyntaxException
{
this.regex = regex;
this.flags = flags;
int gnuFlags = 0;
if ((flags & CASE_INSENSITIVE) != 0)
gnuFlags |= RE.REG_ICASE;
if ((flags & MULTILINE) != 0)
gnuFlags |= RE.REG_MULTILINE;
if ((flags & DOTALL) != 0)
gnuFlags |= RE.REG_DOT_NEWLINE;
// not yet supported:
// if ((flags & UNICODE_CASE) != 0) gnuFlags =
// if ((flags & CANON_EQ) != 0) gnuFlags =
RESyntax syntax = RESyntax.RE_SYNTAX_JAVA_1_4;
if ((flags & UNIX_LINES) != 0)
{
// Use a syntax set with \n for linefeeds?
syntax = new RESyntax(syntax);
syntax.setLineSeparator("\n");
}
if ((flags & COMMENTS) != 0)
{
// Use a syntax with support for comments?
}
try
{
this.re = new RE(regex, gnuFlags, syntax);
}
catch (REException e)
{
throw new PatternSyntaxException(e.getMessage(),
regex, e.getPosition());
}
}
// package private accessor method
RE getRE()
{
return re;
}
/**
* @param regex The regular expression
*
* @exception PatternSyntaxException If the expression's syntax is invalid
*/
public static Pattern compile (String regex)
throws PatternSyntaxException
{
return compile(regex, 0);
}
/**
* @param regex The regular expression
* @param flags The match flags, a bit mask
*
* @exception PatternSyntaxException If the expression's syntax is invalid
* @exception IllegalArgumentException If bit values other than those
* corresponding to the defined match flags are set in flags
*/
public static Pattern compile (String regex, int flags)
throws PatternSyntaxException
{
// FIXME: check which flags are really accepted
if ((flags & ~0xEF) != 0)
throw new IllegalArgumentException ();
return new Pattern (regex, flags);
}
public int flags ()
{
return this.flags;
}
/**
* @param regex The regular expression
* @param input The character sequence to be matched
*
* @exception PatternSyntaxException If the expression's syntax is invalid
*/
public static boolean matches (String regex, CharSequence input)
{
return compile(regex).matcher(input).matches();
}
/**
* @param input The character sequence to be matched
*/
public Matcher matcher (CharSequence input)
{
return new Matcher(this, input);
}
/**
* @param input The character sequence to be matched
*/
public String[] split (CharSequence input)
{
return split(input, 0);
}
/**
* @param input The character sequence to be matched
* @param limit The result threshold
*/
public String[] split (CharSequence input, int limit)
{
Matcher matcher = new Matcher(this, input);
ArrayList list = new ArrayList();
int empties = 0;
int count = 0;
int start = 0;
int end;
boolean matched;
while (matched = matcher.find() && (limit <= 0 || count < limit - 1))
{
++count;
end = matcher.start();
if (start == end)
empties++;
else
{
while (empties > 0)
{
list.add("");
empties--;
}
String text = input.subSequence(start, end).toString();
list.add(text);
}
start = matcher.end();
}
// We matched nothing.
if (!matched && count == 0)
return new String[] { input.toString() };
// Is the last token empty?
boolean emptyLast = (start == input.length());
// Can/Must we add empties or an extra last token at the end?
if (list.size() < limit || limit < 0 || (limit == 0 && !emptyLast))
{
if (limit > list.size())
{
int max = limit - list.size();
empties = (empties > max) ? max : empties;
}
while (empties > 0)
{
list.add("");
empties--;
}
}
// last token at end
if (limit != 0 || (limit == 0 && !emptyLast))
{
String t = input.subSequence(start, input.length()).toString();
if ("".equals(t) && limit == 0)
; // Don't add.
else
list.add(t);
}
String[] output = new String [list.size()];
list.toArray(output);
return output;
}
public String pattern ()
{
return regex;
}
}
@@ -1,132 +0,0 @@
/* PatternSyntaxException - Indicates illegal pattern for regular expression.
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.regex;
/**
* Indicates illegal pattern for regular expression.
* Includes state to inspect the pattern and what and where the expression
* was not valid regular expression.
*/
public class PatternSyntaxException extends IllegalArgumentException
{
private static final long serialVersionUID = -3864639126226059218L;
/**
* Human readable escription of the syntax error.
*/
private final String desc;
/**
* The original pattern that contained the syntax error.
*/
private final String pattern;
/**
* Index of the first character in the String that was probably invalid,
* or -1 when unknown.
*/
private final int index;
/**
* Creates a new PatternSyntaxException.
*
* @param description Human readable escription of the syntax error.
* @param pattern The original pattern that contained the syntax error.
* @param index Index of the first character in the String that was
* probably invalid, or -1 when unknown.
*/
public PatternSyntaxException(String description,
String pattern,
int index)
{
super(description);
this.desc = description;
this.pattern = pattern;
this.index = index;
}
/**
* Returns a human readable escription of the syntax error.
*/
public String getDescription()
{
return desc;
}
/**
* Returns the original pattern that contained the syntax error.
*/
public String getPattern()
{
return pattern;
}
/**
* Returns the index of the first character in the String that was probably
* invalid, or -1 when unknown.
*/
public int getIndex()
{
return index;
}
/**
* Returns a string containing a line with the description, a line with
* the original pattern and a line indicating with a ^ which character is
* probably the first invalid character in the pattern if the index is not
* negative.
*/
public String getMessage()
{
String lineSep = System.getProperty("line.separator");
StringBuffer sb = new StringBuffer(desc);
sb.append(lineSep);
sb.append('\t');
sb.append(pattern);
if (index != -1)
{
sb.append(lineSep);
sb.append('\t');
for (int i=0; i<index; i++)
sb.append(' ');
sb.append('^');
}
return sb.toString();
}
}
-205
View File
@@ -1,205 +0,0 @@
/* Adler32.java - Computes Adler32 data checksum of a data stream
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
/*
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* The actual Adler32 algorithm is taken from RFC 1950.
* Status: Believed complete and correct.
*/
/**
* Computes Adler32 checksum for a stream of data. An Adler32
* checksum is not as reliable as a CRC32 checksum, but a lot faster to
* compute.
*<p>
* The specification for Adler32 may be found in RFC 1950.
* (ZLIB Compressed Data Format Specification version 3.3)
*<p>
*<p>
* From that document:
*<p>
* "ADLER32 (Adler-32 checksum)
* This contains a checksum value of the uncompressed data
* (excluding any dictionary data) computed according to Adler-32
* algorithm. This algorithm is a 32-bit extension and improvement
* of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
* standard.
*<p>
* Adler-32 is composed of two sums accumulated per byte: s1 is
* the sum of all bytes, s2 is the sum of all s1 values. Both sums
* are done modulo 65521. s1 is initialized to 1, s2 to zero. The
* Adler-32 checksum is stored as s2*65536 + s1 in most-
* significant-byte first (network) order."
*<p>
* "8.2. The Adler-32 algorithm
*<p>
* The Adler-32 algorithm is much faster than the CRC32 algorithm yet
* still provides an extremely low probability of undetected errors.
*<p>
* The modulo on unsigned long accumulators can be delayed for 5552
* bytes, so the modulo operation time is negligible. If the bytes
* are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
* and order sensitive, unlike the first sum, which is just a
* checksum. That 65521 is prime is important to avoid a possible
* large class of two-byte errors that leave the check unchanged.
* (The Fletcher checksum uses 255, which is not prime and which also
* makes the Fletcher check insensitive to single byte changes 0 <->
* 255.)
*<p>
* The sum s1 is initialized to 1 instead of zero to make the length
* of the sequence part of s2, so that the length does not have to be
* checked separately. (Any sequence of zeroes has a Fletcher
* checksum of zero.)"
*
* @author John Leuner, Per Bothner
* @since JDK 1.1
*
* @see InflaterInputStream
* @see DeflaterOutputStream
*/
public class Adler32 implements Checksum
{
/** largest prime smaller than 65536 */
private static final int BASE = 65521;
private int checksum; //we do all in int.
//Note that java doesn't have unsigned integers,
//so we have to be careful with what arithmetic
//we do. We return the checksum as a long to
//avoid sign confusion.
/**
* Creates a new instance of the <code>Adler32</code> class.
* The checksum starts off with a value of 1.
*/
public Adler32 ()
{
reset();
}
/**
* Resets the Adler32 checksum to the initial value.
*/
public void reset ()
{
checksum = 1; //Initialize to 1
}
/**
* Updates the checksum with the byte b.
*
* @param bval the data value to add. The high byte of the int is ignored.
*/
public void update (int bval)
{
//We could make a length 1 byte array and call update again, but I
//would rather not have that overhead
int s1 = checksum & 0xffff;
int s2 = checksum >>> 16;
s1 = (s1 + (bval & 0xFF)) % BASE;
s2 = (s1 + s2) % BASE;
checksum = (s2 << 16) + s1;
}
/**
* Updates the checksum with the bytes taken from the array.
*
* @param buffer an array of bytes
*/
public void update (byte[] buffer)
{
update(buffer, 0, buffer.length);
}
/**
* Updates the checksum with the bytes taken from the array.
*
* @param buf an array of bytes
* @param off the start of the data used for this update
* @param len the number of bytes to use for this update
*/
public void update (byte[] buf, int off, int len)
{
//(By Per Bothner)
int s1 = checksum & 0xffff;
int s2 = checksum >>> 16;
while (len > 0)
{
// We can defer the modulo operation:
// s1 maximally grows from 65521 to 65521 + 255 * 3800
// s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
int n = 3800;
if (n > len)
n = len;
len -= n;
while (--n >= 0)
{
s1 = s1 + (buf[off++] & 0xFF);
s2 = s2 + s1;
}
s1 %= BASE;
s2 %= BASE;
}
/*Old implementation, borrowed from somewhere:
int n;
while (len-- > 0) {
s1 = (s1 + (bs[offset++] & 0xff)) % BASE;
s2 = (s2 + s1) % BASE;
}*/
checksum = (s2 << 16) | s1;
}
/**
* Returns the Adler32 data checksum computed so far.
*/
public long getValue()
{
return (long) checksum & 0xffffffffL;
}
}
-132
View File
@@ -1,132 +0,0 @@
/* CRC32.java - Computes CRC32 data checksum of a data stream
Copyright (C) 1999. 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
/*
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* The actual CRC32 algorithm is taken from RFC 1952.
* Status: Believed complete and correct.
*/
/**
* Computes CRC32 data checksum of a data stream.
* The actual CRC32 algorithm is described in RFC 1952
* (GZIP file format specification version 4.3).
* Can be used to get the CRC32 over a stream if used with checked input/output
* streams.
*
* @see InflaterInputStream
* @see DeflaterOutputStream
*
* @author Per Bothner
* @date April 1, 1999.
*/
public class CRC32 implements Checksum
{
/** The crc data checksum so far. */
private int crc = 0;
/** The fast CRC table. Computed once when the CRC32 class is loaded. */
private static int[] crc_table = make_crc_table();
/** Make the table for a fast CRC. */
private static int[] make_crc_table ()
{
int[] crc_table = new int[256];
for (int n = 0; n < 256; n++)
{
int c = n;
for (int k = 8; --k >= 0; )
{
if ((c & 1) != 0)
c = 0xedb88320 ^ (c >>> 1);
else
c = c >>> 1;
}
crc_table[n] = c;
}
return crc_table;
}
/**
* Returns the CRC32 data checksum computed so far.
*/
public long getValue ()
{
return (long) crc & 0xffffffffL;
}
/**
* Resets the CRC32 data checksum as if no update was ever called.
*/
public void reset () { crc = 0; }
/**
* Updates the checksum with the int bval.
*
* @param bval (the byte is taken as the lower 8 bits of bval)
*/
public void update (int bval)
{
int c = ~crc;
c = crc_table[(c ^ bval) & 0xff] ^ (c >>> 8);
crc = ~c;
}
/**
* Adds the byte array to the data checksum.
*
* @param buf the buffer which contains the data
* @param off the offset in the buffer where the data starts
* @param len the length of the data
*/
public void update (byte[] buf, int off, int len)
{
int c = ~crc;
while (--len >= 0)
c = crc_table[(c ^ buf[off++]) & 0xff] ^ (c >>> 8);
crc = ~c;
}
/**
* Adds the complete byte array to the data checksum.
*/
public void update (byte[] buf) { update(buf, 0, buf.length); }
}
@@ -1,135 +0,0 @@
/* CheckedInputStream.java - Compute checksum of data being read
Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
/**
* InputStream that computes a checksum of the data being read using a
* supplied Checksum object.
*
* @see Checksum
*
* @author Tom Tromey
* @date May 17, 1999
*/
public class CheckedInputStream extends FilterInputStream
{
/**
* Creates a new CheckInputStream on top of the supplied OutputStream
* using the supplied Checksum.
*/
public CheckedInputStream (InputStream in, Checksum sum)
{
super (in);
this.sum = sum;
}
/**
* Returns the Checksum object used. To get the data checksum computed so
* far call <code>getChecksum.getValue()</code>.
*/
public Checksum getChecksum ()
{
return sum;
}
/**
* Reads one byte, updates the checksum and returns the read byte
* (or -1 when the end of file was reached).
*/
public int read () throws IOException
{
int x = in.read();
if (x != -1)
sum.update(x);
return x;
}
/**
* Reads at most len bytes in the supplied buffer and updates the checksum
* with it. Returns the number of bytes actually read or -1 when the end
* of file was reached.
*/
public int read (byte[] buf, int off, int len) throws IOException
{
int r = in.read(buf, off, len);
if (r != -1)
sum.update(buf, off, r);
return r;
}
/**
* Skips n bytes by reading them in a temporary buffer and updating the
* the checksum with that buffer. Returns the actual number of bytes skiped
* which can be less then requested when the end of file is reached.
*/
public long skip (long n) throws IOException
{
if (n == 0)
return 0;
int min = (int) Math.min(n, 1024);
byte[] buf = new byte[min];
long s = 0;
while (n > 0)
{
int r = in.read(buf, 0, min);
if (r == -1)
break;
n -= r;
s += r;
min = (int) Math.min(n, 1024);
sum.update(buf, 0, r);
}
return s;
}
/** The checksum object. */
private Checksum sum;
}
@@ -1,100 +0,0 @@
/* CheckedOutputStream.java - Compute checksum of data being written.
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/* Written using on-line Java Platform 1.2 API Specification
* and JCL book.
* Believed complete and correct.
*/
/**
* OutputStream that computes a checksum of data being written using a
* supplied Checksum object.
*
* @see Checksum
*
* @author Tom Tromey
* @date May 17, 1999
*/
public class CheckedOutputStream extends FilterOutputStream
{
/**
* Creates a new CheckInputStream on top of the supplied OutputStream
* using the supplied Checksum.
*/
public CheckedOutputStream (OutputStream out, Checksum cksum)
{
super (out);
this.sum = cksum;
}
/**
* Returns the Checksum object used. To get the data checksum computed so
* far call <code>getChecksum.getValue()</code>.
*/
public Checksum getChecksum ()
{
return sum;
}
/**
* Writes one byte to the OutputStream and updates the Checksum.
*/
public void write (int bval) throws IOException
{
out.write(bval);
sum.update(bval);
}
/**
* Writes the byte array to the OutputStream and updates the Checksum.
*/
public void write (byte[] buf, int off, int len) throws IOException
{
out.write(buf, off, len);
sum.update(buf, off, len);
}
/** The checksum object. */
private Checksum sum;
}
-86
View File
@@ -1,86 +0,0 @@
/* Checksum.java - Interface to compute a data checksum
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
/*
* Written using on-line Java Platform 1.2 API Specification, as well
* as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
* Status: Believed complete and correct.
*/
/**
* Interface to compute a data checksum used by checked input/output streams.
* A data checksum can be updated by one byte or with a byte array. After each
* update the value of the current checksum can be returned by calling
* <code>getValue</code>. The complete checksum object can also be reset
* so it can be used again with new data.
*
* @see CheckedInputStream
* @see CheckedOutputStream
*
* @author Per Bothner
* @author Jochen Hoenicke
*/
public interface Checksum
{
/**
* Returns the data checksum computed so far.
*/
long getValue();
/**
* Resets the data checksum as if no update was ever called.
*/
void reset();
/**
* Adds one byte to the data checksum.
*
* @param bval the data value to add. The high byte of the int is ignored.
*/
void update (int bval);
/**
* Adds the byte array to the data checksum.
*
* @param buf the buffer which contains the data
* @param off the offset in the buffer where the data starts
* @param len the length of the data
*/
void update (byte[] buf, int off, int len);
}
@@ -1,71 +0,0 @@
/* DataformatException.java -- thrown when compressed data is corrupt
Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
/**
* Exception thrown when compressed data is corrupt.
*
* @author Tom Tromey
* @author John Leuner
* @since 1.1
* @status updated to 1.4
*/
public class DataFormatException extends Exception
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = 2219632870893641452L;
/**
* Create an exception without a message.
*/
public DataFormatException()
{
}
/**
* Create an exception with a message.
*
* @param msg the message
*/
public DataFormatException(String msg)
{
super(msg);
}
}
-97
View File
@@ -1,97 +0,0 @@
/* java.util.zip.ZipConstants
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
interface ZipConstants
{
/* The local file header */
int LOCHDR = 30;
int LOCSIG = 'P'|('K'<<8)|(3<<16)|(4<<24);
int LOCVER = 4;
int LOCFLG = 6;
int LOCHOW = 8;
int LOCTIM = 10;
int LOCCRC = 14;
int LOCSIZ = 18;
int LOCLEN = 22;
int LOCNAM = 26;
int LOCEXT = 28;
/* The Data descriptor */
int EXTSIG = 'P'|('K'<<8)|(7<<16)|(8<<24);
int EXTHDR = 16;
int EXTCRC = 4;
int EXTSIZ = 8;
int EXTLEN = 12;
/* The central directory file header */
int CENSIG = 'P'|('K'<<8)|(1<<16)|(2<<24);
int CENHDR = 46;
int CENVEM = 4;
int CENVER = 6;
int CENFLG = 8;
int CENHOW = 10;
int CENTIM = 12;
int CENCRC = 16;
int CENSIZ = 20;
int CENLEN = 24;
int CENNAM = 28;
int CENEXT = 30;
int CENCOM = 32;
int CENDSK = 34;
int CENATT = 36;
int CENATX = 38;
int CENOFF = 42;
/* The entries in the end of central directory */
int ENDSIG = 'P'|('K'<<8)|(5<<16)|(6<<24);
int ENDHDR = 22;
/* The following two fields are missing in SUN JDK */
int ENDNRD = 4;
int ENDDCD = 6;
int ENDSUB = 8;
int ENDTOT = 10;
int ENDSIZ = 12;
int ENDOFF = 16;
int ENDCOM = 20;
}
-72
View File
@@ -1,72 +0,0 @@
/* ZipException.java - exception representing a zip related error
Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
import java.io.IOException;
/**
* Thrown during the creation or input of a zip file.
*
* @author Jochen Hoenicke
* @author Per Bothner
* @status updated to 1.4
*/
public class ZipException extends IOException
{
/**
* Compatible with JDK 1.0+.
*/
private static final long serialVersionUID = 8000196834066748623L;
/**
* Create an exception without a message.
*/
public ZipException()
{
}
/**
* Create an exception with a message.
*
* @param msg the message
*/
public ZipException (String msg)
{
super(msg);
}
}
-371
View File
@@ -1,371 +0,0 @@
/* ZipInputStream.java --
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
/**
* This is a FilterInputStream that reads the files in an zip archive
* one after another. It has a special method to get the zip entry of
* the next file. The zip entry contains information about the file name
* size, compressed size, CRC, etc.
*
* It includes support for STORED and DEFLATED entries.
*
* @author Jochen Hoenicke
*/
public class ZipInputStream extends InflaterInputStream implements ZipConstants
{
private CRC32 crc = new CRC32();
private ZipEntry entry = null;
private int csize;
private int size;
private int method;
private int flags;
private int avail;
private boolean entryAtEOF;
/**
* Creates a new Zip input stream, reading a zip archive.
*/
public ZipInputStream(InputStream in)
{
super(in, new Inflater(true));
}
private void fillBuf() throws IOException
{
avail = len = in.read(buf, 0, buf.length);
}
private int readBuf(byte[] out, int offset, int length) throws IOException
{
if (avail <= 0)
{
fillBuf();
if (avail <= 0)
return -1;
}
if (length > avail)
length = avail;
System.arraycopy(buf, len - avail, out, offset, length);
avail -= length;
return length;
}
private void readFully(byte[] out) throws IOException
{
int off = 0;
int len = out.length;
while (len > 0)
{
int count = readBuf(out, off, len);
if (count == -1)
throw new EOFException();
off += count;
len -= count;
}
}
private int readLeByte() throws IOException
{
if (avail <= 0)
{
fillBuf();
if (avail <= 0)
throw new ZipException("EOF in header");
}
return buf[len - avail--] & 0xff;
}
/**
* Read an unsigned short in little endian byte order.
*/
private int readLeShort() throws IOException
{
return readLeByte() | (readLeByte() << 8);
}
/**
* Read an int in little endian byte order.
*/
private int readLeInt() throws IOException
{
return readLeShort() | (readLeShort() << 16);
}
/**
* Open the next entry from the zip archive, and return its description.
* If the previous entry wasn't closed, this method will close it.
*/
public ZipEntry getNextEntry() throws IOException
{
if (crc == null)
throw new IOException("Stream closed.");
if (entry != null)
closeEntry();
int header = readLeInt();
if (header == CENSIG)
{
/* Central Header reached. */
close();
return null;
}
if (header != LOCSIG)
throw new ZipException("Wrong Local header signature: "
+ Integer.toHexString(header));
/* skip version */
readLeShort();
flags = readLeShort();
method = readLeShort();
int dostime = readLeInt();
int crc = readLeInt();
csize = readLeInt();
size = readLeInt();
int nameLen = readLeShort();
int extraLen = readLeShort();
if (method == ZipOutputStream.STORED && csize != size)
throw new ZipException("Stored, but compressed != uncompressed");
byte[] buffer = new byte[nameLen];
readFully(buffer);
String name = new String(buffer);
entry = createZipEntry(name);
entryAtEOF = false;
entry.setMethod(method);
if ((flags & 8) == 0)
{
entry.setCrc(crc & 0xffffffffL);
entry.setSize(size & 0xffffffffL);
entry.setCompressedSize(csize & 0xffffffffL);
}
entry.setDOSTime(dostime);
if (extraLen > 0)
{
byte[] extra = new byte[extraLen];
readFully(extra);
entry.setExtra(extra);
}
if (method == ZipOutputStream.DEFLATED && avail > 0)
{
System.arraycopy(buf, len - avail, buf, 0, avail);
len = avail;
avail = 0;
inf.setInput(buf, 0, len);
}
return entry;
}
private void readDataDescr() throws IOException
{
if (readLeInt() != EXTSIG)
throw new ZipException("Data descriptor signature not found");
entry.setCrc(readLeInt() & 0xffffffffL);
csize = readLeInt();
size = readLeInt();
entry.setSize(size & 0xffffffffL);
entry.setCompressedSize(csize & 0xffffffffL);
}
/**
* Closes the current zip entry and moves to the next one.
*/
public void closeEntry() throws IOException
{
if (crc == null)
throw new IOException("Stream closed.");
if (entry == null)
return;
if (method == ZipOutputStream.DEFLATED)
{
if ((flags & 8) != 0)
{
/* We don't know how much we must skip, read until end. */
byte[] tmp = new byte[2048];
while (read(tmp) > 0)
;
/* read will close this entry */
return;
}
csize -= inf.getTotalIn();
avail = inf.getRemaining();
}
if (avail > csize && csize >= 0)
avail -= csize;
else
{
csize -= avail;
avail = 0;
while (csize != 0)
{
long skipped = in.skip(csize & 0xffffffffL);
if (skipped <= 0)
throw new ZipException("zip archive ends early.");
csize -= skipped;
}
}
size = 0;
crc.reset();
if (method == ZipOutputStream.DEFLATED)
inf.reset();
entry = null;
entryAtEOF = true;
}
public int available() throws IOException
{
return entryAtEOF ? 0 : 1;
}
/**
* Reads a byte from the current zip entry.
* @return the byte or -1 on EOF.
* @exception IOException if a i/o error occured.
* @exception ZipException if the deflated stream is corrupted.
*/
public int read() throws IOException
{
byte[] b = new byte[1];
if (read(b, 0, 1) <= 0)
return -1;
return b[0] & 0xff;
}
/**
* Reads a block of bytes from the current zip entry.
* @return the number of bytes read (may be smaller, even before
* EOF), or -1 on EOF.
* @exception IOException if a i/o error occured.
* @exception ZipException if the deflated stream is corrupted.
*/
public int read(byte[] b, int off, int len) throws IOException
{
if (len == 0)
return 0;
if (crc == null)
throw new IOException("Stream closed.");
if (entry == null)
return -1;
boolean finished = false;
switch (method)
{
case ZipOutputStream.DEFLATED:
len = super.read(b, off, len);
if (len < 0)
{
if (!inf.finished())
throw new ZipException("Inflater not finished!?");
avail = inf.getRemaining();
if ((flags & 8) != 0)
readDataDescr();
if (inf.getTotalIn() != csize
|| inf.getTotalOut() != size)
throw new ZipException("size mismatch: "+csize+";"+size+" <-> "+inf.getTotalIn()+";"+inf.getTotalOut());
inf.reset();
finished = true;
}
break;
case ZipOutputStream.STORED:
if (len > csize && csize >= 0)
len = csize;
len = readBuf(b, off, len);
if (len > 0)
{
csize -= len;
size -= len;
}
if (csize == 0)
finished = true;
else if (len < 0)
throw new ZipException("EOF in stored block");
break;
}
if (len > 0)
crc.update(b, off, len);
if (finished)
{
if ((crc.getValue() & 0xffffffffL) != entry.getCrc())
throw new ZipException("CRC mismatch");
crc.reset();
entry = null;
entryAtEOF = true;
}
return len;
}
/**
* Closes the zip file.
* @exception IOException if a i/o error occured.
*/
public void close() throws IOException
{
super.close();
crc = null;
entry = null;
entryAtEOF = true;
}
/**
* Creates a new zip entry for the given name. This is equivalent
* to new ZipEntry(name).
* @param name the name of the zip entry.
*/
protected ZipEntry createZipEntry(String name)
{
return new ZipEntry(name);
}
}
-399
View File
@@ -1,399 +0,0 @@
/* ZipOutputStream.java --
Copyright (C) 2001, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.util.zip;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
/**
* This is a FilterOutputStream that writes the files into a zip
* archive one after another. It has a special method to start a new
* zip entry. The zip entries contains information about the file name
* size, compressed size, CRC, etc.
*
* It includes support for STORED and DEFLATED entries.
*
* This class is not thread safe.
*
* @author Jochen Hoenicke
*/
public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants
{
private Vector entries = new Vector();
private CRC32 crc = new CRC32();
private ZipEntry curEntry = null;
private int curMethod;
private int size;
private int offset = 0;
private byte[] zipComment = new byte[0];
private int defaultMethod = DEFLATED;
/**
* Our Zip version is hard coded to 1.0 resp. 2.0
*/
private static final int ZIP_STORED_VERSION = 10;
private static final int ZIP_DEFLATED_VERSION = 20;
/**
* Compression method. This method doesn't compress at all.
*/
public static final int STORED = 0;
/**
* Compression method. This method uses the Deflater.
*/
public static final int DEFLATED = 8;
/**
* Creates a new Zip output stream, writing a zip archive.
* @param out the output stream to which the zip archive is written.
*/
public ZipOutputStream(OutputStream out)
{
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
}
/**
* Set the zip file comment.
* @param comment the comment.
* @exception IllegalArgumentException if encoding of comment is
* longer than 0xffff bytes.
*/
public void setComment(String comment)
{
byte[] commentBytes;
commentBytes = comment.getBytes();
if (commentBytes.length > 0xffff)
throw new IllegalArgumentException("Comment too long.");
zipComment = commentBytes;
}
/**
* Sets default compression method. If the Zip entry specifies
* another method its method takes precedence.
* @param method the method.
* @exception IllegalArgumentException if method is not supported.
* @see #STORED
* @see #DEFLATED
*/
public void setMethod(int method)
{
if (method != STORED && method != DEFLATED)
throw new IllegalArgumentException("Method not supported.");
defaultMethod = method;
}
/**
* Sets default compression level. The new level will be activated
* immediately.
* @exception IllegalArgumentException if level is not supported.
* @see Deflater
*/
public void setLevel(int level)
{
def.setLevel(level);
}
/**
* Write an unsigned short in little endian byte order.
*/
private void writeLeShort(int value) throws IOException
{
out.write(value & 0xff);
out.write((value >> 8) & 0xff);
}
/**
* Write an int in little endian byte order.
*/
private void writeLeInt(int value) throws IOException
{
writeLeShort(value);
writeLeShort(value >> 16);
}
/**
* Starts a new Zip entry. It automatically closes the previous
* entry if present. If the compression method is stored, the entry
* must have a valid size and crc, otherwise all elements (except
* name) are optional, but must be correct if present. If the time
* is not set in the entry, the current time is used.
* @param entry the entry.
* @exception IOException if an I/O error occured.
* @exception ZipException if stream was finished.
*/
public void putNextEntry(ZipEntry entry) throws IOException
{
if (entries == null)
throw new ZipException("ZipOutputStream was finished");
int method = entry.getMethod();
int flags = 0;
if (method == -1)
method = defaultMethod;
if (method == STORED)
{
if (entry.getCompressedSize() >= 0)
{
if (entry.getSize() < 0)
entry.setSize(entry.getCompressedSize());
else if (entry.getSize() != entry.getCompressedSize())
throw new ZipException
("Method STORED, but compressed size != size");
}
else
entry.setCompressedSize(entry.getSize());
if (entry.getSize() < 0)
throw new ZipException("Method STORED, but size not set");
if (entry.getCrc() < 0)
throw new ZipException("Method STORED, but crc not set");
}
else if (method == DEFLATED)
{
if (entry.getCompressedSize() < 0
|| entry.getSize() < 0 || entry.getCrc() < 0)
flags |= 8;
}
if (curEntry != null)
closeEntry();
if (entry.getTime() < 0)
entry.setTime(System.currentTimeMillis());
entry.flags = flags;
entry.offset = offset;
entry.setMethod(method);
curMethod = method;
/* Write the local file header */
writeLeInt(LOCSIG);
writeLeShort(method == STORED
? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
writeLeShort(flags);
writeLeShort(method);
writeLeInt(entry.getDOSTime());
if ((flags & 8) == 0)
{
writeLeInt((int)entry.getCrc());
writeLeInt((int)entry.getCompressedSize());
writeLeInt((int)entry.getSize());
}
else
{
writeLeInt(0);
writeLeInt(0);
writeLeInt(0);
}
byte[] name = entry.getName().getBytes();
if (name.length > 0xffff)
throw new ZipException("Name too long.");
byte[] extra = entry.getExtra();
if (extra == null)
extra = new byte[0];
writeLeShort(name.length);
writeLeShort(extra.length);
out.write(name);
out.write(extra);
offset += LOCHDR + name.length + extra.length;
/* Activate the entry. */
curEntry = entry;
crc.reset();
if (method == DEFLATED)
def.reset();
size = 0;
}
/**
* Closes the current entry.
* @exception IOException if an I/O error occured.
* @exception ZipException if no entry is active.
*/
public void closeEntry() throws IOException
{
if (curEntry == null)
throw new ZipException("No open entry");
/* First finish the deflater, if appropriate */
if (curMethod == DEFLATED)
super.finish();
int csize = curMethod == DEFLATED ? def.getTotalOut() : size;
if (curEntry.getSize() < 0)
curEntry.setSize(size);
else if (curEntry.getSize() != size)
throw new ZipException("size was "+size
+", but I expected "+curEntry.getSize());
if (curEntry.getCompressedSize() < 0)
curEntry.setCompressedSize(csize);
else if (curEntry.getCompressedSize() != csize)
throw new ZipException("compressed size was "+csize
+", but I expected "+curEntry.getSize());
if (curEntry.getCrc() < 0)
curEntry.setCrc(crc.getValue());
else if (curEntry.getCrc() != crc.getValue())
throw new ZipException("crc was " + Long.toHexString(crc.getValue())
+ ", but I expected "
+ Long.toHexString(curEntry.getCrc()));
offset += csize;
/* Now write the data descriptor entry if needed. */
if (curMethod == DEFLATED && (curEntry.flags & 8) != 0)
{
writeLeInt(EXTSIG);
writeLeInt((int)curEntry.getCrc());
writeLeInt((int)curEntry.getCompressedSize());
writeLeInt((int)curEntry.getSize());
offset += EXTHDR;
}
entries.addElement(curEntry);
curEntry = null;
}
/**
* Writes the given buffer to the current entry.
* @exception IOException if an I/O error occured.
* @exception ZipException if no entry is active.
*/
public void write(byte[] b, int off, int len) throws IOException
{
if (curEntry == null)
throw new ZipException("No open entry.");
switch (curMethod)
{
case DEFLATED:
super.write(b, off, len);
break;
case STORED:
out.write(b, off, len);
break;
}
crc.update(b, off, len);
size += len;
}
/**
* Finishes the stream. This will write the central directory at the
* end of the zip file and flush the stream.
* @exception IOException if an I/O error occured.
*/
public void finish() throws IOException
{
if (entries == null)
return;
if (curEntry != null)
closeEntry();
int numEntries = 0;
int sizeEntries = 0;
Enumeration e = entries.elements();
while (e.hasMoreElements())
{
ZipEntry entry = (ZipEntry) e.nextElement();
int method = entry.getMethod();
writeLeInt(CENSIG);
writeLeShort(method == STORED
? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
writeLeShort(method == STORED
? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
writeLeShort(entry.flags);
writeLeShort(method);
writeLeInt(entry.getDOSTime());
writeLeInt((int)entry.getCrc());
writeLeInt((int)entry.getCompressedSize());
writeLeInt((int)entry.getSize());
byte[] name = entry.getName().getBytes();
if (name.length > 0xffff)
throw new ZipException("Name too long.");
byte[] extra = entry.getExtra();
if (extra == null)
extra = new byte[0];
String strComment = entry.getComment();
byte[] comment = strComment != null
? strComment.getBytes() : new byte[0];
if (comment.length > 0xffff)
throw new ZipException("Comment too long.");
writeLeShort(name.length);
writeLeShort(extra.length);
writeLeShort(comment.length);
writeLeShort(0); /* disk number */
writeLeShort(0); /* internal file attr */
writeLeInt(0); /* external file attr */
writeLeInt(entry.offset);
out.write(name);
out.write(extra);
out.write(comment);
numEntries++;
sizeEntries += CENHDR + name.length + extra.length + comment.length;
}
writeLeInt(ENDSIG);
writeLeShort(0); /* disk number */
writeLeShort(0); /* disk with start of central dir */
writeLeShort(numEntries);
writeLeShort(numEntries);
writeLeInt(sizeEntries);
writeLeInt(offset);
writeLeShort(zipComment.length);
out.write(zipComment);
out.flush();
entries = null;
}
}