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:
@@ -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
@@ -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 < 0 || index > 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 < 0 || index > size()
|
||||
* @throws ClassCastException if o cannot be added to this list due to its
|
||||
* type
|
||||
* @throws IllegalArgumentException if o cannot be added to this list for
|
||||
* some other reason.
|
||||
* @throws NullPointerException if o is null and 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 < 0 || index > size()
|
||||
* @throws ClassCastException if some element of c cannot be added to this
|
||||
* list due to its type
|
||||
* @throws IllegalArgumentException if some element of c cannot be added
|
||||
* to this list for some other reason
|
||||
* @throws NullPointerException if 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index >= size()
|
||||
* @throws ClassCastException if o cannot be added to this list due to its
|
||||
* type
|
||||
* @throws IllegalArgumentException if o cannot be added to this list for
|
||||
* some other reason
|
||||
* @throws NullPointerException if o is null and 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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 > 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index > 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 < 0 || index >= 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 < 0 || index > 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 > 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 > 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 >= 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
@@ -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 < 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 < 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 < 0 || to < 0 ||
|
||||
* from > 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 > to || from < 0 ||
|
||||
* to < 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 > to || from < 0 ||
|
||||
* to < 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) < bits.length)
|
||||
* && ((bits[k/64] & (1L << (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 >= 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 >= 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 < 0 || from > to ||
|
||||
* to < 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 < 0 || from > to ||
|
||||
* to < 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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) < 0 then compare(b, a) > 0</li>
|
||||
* <li>if compare(a, b) throws an exception, so does compare(b, a)</li>
|
||||
* <li>if compare(a, b) < 0 and compare(b, c) < 0 then compare(a, c)
|
||||
* < 0</li>
|
||||
* <li>if compare(a, b) == 0 then compare(a, c) and compare(b, c) must
|
||||
* have the same sign</li>
|
||||
* </ul>
|
||||
* To be consistent with equals, the following additional constraint is
|
||||
* in place:
|
||||
* <ul>
|
||||
* <li>if a.equals(b) or both a and b are null, then
|
||||
* compare(a, b) == 0.</li>
|
||||
* </ul><p>
|
||||
*
|
||||
* Although it is permissible for a comparator to provide an order
|
||||
* inconsistent with equals, that should be documented.
|
||||
*
|
||||
* @param o1 the first object
|
||||
* @param o2 the second object
|
||||
* @return the comparison
|
||||
* @throws ClassCastException if the elements are not of types that can be
|
||||
* compared by this ordering.
|
||||
*/
|
||||
int compare(Object o1, Object o2);
|
||||
|
||||
/**
|
||||
* Return true if the object is equal to this object. To be
|
||||
* considered equal, the argument object must satisfy the constraints
|
||||
* of <code>Object.equals()</code>, be a Comparator, and impose the
|
||||
* same ordering as this Comparator. The default implementation
|
||||
* inherited from Object is usually adequate.
|
||||
*
|
||||
* @param obj The object
|
||||
* @return true if it is a Comparator that imposes the same order
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
boolean equals(Object obj);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 (>=0)
|
||||
* @throws IllegalArgumentException if (initialCapacity < 0)
|
||||
*/
|
||||
public HashMap(int initialCapacity)
|
||||
{
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new HashMap with a specific inital capacity and load factor.
|
||||
*
|
||||
* @param initialCapacity the initial capacity (>=0)
|
||||
* @param loadFactor the load factor (> 0, not NaN)
|
||||
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
||||
* ! (loadFactor > 0.0)
|
||||
*/
|
||||
public HashMap(int initialCapacity, float loadFactor)
|
||||
{
|
||||
if (initialCapacity < 0)
|
||||
throw new IllegalArgumentException("Illegal Capacity: "
|
||||
+ initialCapacity);
|
||||
if (! (loadFactor > 0)) // check for NaN too
|
||||
throw new IllegalArgumentException("Illegal Load: " + loadFactor);
|
||||
|
||||
if (initialCapacity == 0)
|
||||
initialCapacity = 1;
|
||||
buckets = new HashEntry[initialCapacity];
|
||||
this.loadFactor = loadFactor;
|
||||
threshold = (int) (initialCapacity * loadFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of kay-value mappings currently in this Map.
|
||||
*
|
||||
* @return the size
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are no key-value mappings currently in this Map.
|
||||
*
|
||||
* @return <code>size() == 0</code>
|
||||
*/
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value in this HashMap associated with the supplied key,
|
||||
* or <code>null</code> if the key maps to nothing. NOTE: Since the value
|
||||
* could also be null, you must use containsKey to see if this key
|
||||
* actually maps to something.
|
||||
*
|
||||
* @param key the key for which to fetch an associated value
|
||||
* @return what the key maps to, if present
|
||||
* @see #put(Object, Object)
|
||||
* @see #containsKey(Object)
|
||||
*/
|
||||
public Object get(Object key)
|
||||
{
|
||||
int idx = hash(key);
|
||||
HashEntry e = buckets[idx];
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(key, e.key))
|
||||
return e.value;
|
||||
e = e.next;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the supplied object <code>equals()</code> a key
|
||||
* in this HashMap.
|
||||
*
|
||||
* @param key the key to search for in this HashMap
|
||||
* @return true if the key is in the table
|
||||
* @see #containsValue(Object)
|
||||
*/
|
||||
public boolean containsKey(Object key)
|
||||
{
|
||||
int idx = hash(key);
|
||||
HashEntry e = buckets[idx];
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(key, e.key))
|
||||
return true;
|
||||
e = e.next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the supplied value into the Map, mapped by the supplied key.
|
||||
* The value may be retrieved by any object which <code>equals()</code>
|
||||
* this key. NOTE: Since the prior value could also be null, you must
|
||||
* first use containsKey if you want to see if you are replacing the
|
||||
* key's mapping.
|
||||
*
|
||||
* @param key the key used to locate the value
|
||||
* @param value the value to be stored in the HashMap
|
||||
* @return the prior mapping of the key, or null if there was none
|
||||
* @see #get(Object)
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
public Object put(Object key, Object value)
|
||||
{
|
||||
int idx = hash(key);
|
||||
HashEntry e = buckets[idx];
|
||||
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(key, e.key))
|
||||
{
|
||||
e.access(); // Must call this for bookkeeping in LinkedHashMap.
|
||||
Object r = e.value;
|
||||
e.value = value;
|
||||
return r;
|
||||
}
|
||||
else
|
||||
e = e.next;
|
||||
}
|
||||
|
||||
// At this point, we know we need to add a new entry.
|
||||
modCount++;
|
||||
if (++size > threshold)
|
||||
{
|
||||
rehash();
|
||||
// Need a new hash value to suit the bigger table.
|
||||
idx = hash(key);
|
||||
}
|
||||
|
||||
// LinkedHashMap cannot override put(), hence this call.
|
||||
addEntry(key, value, idx, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all elements of the given map into this hashtable. If this table
|
||||
* already has a mapping for a key, the new mapping replaces the current
|
||||
* one.
|
||||
*
|
||||
* @param m the map to be hashed into this
|
||||
*/
|
||||
public void putAll(Map m)
|
||||
{
|
||||
Iterator itr = m.entrySet().iterator();
|
||||
while (itr.hasNext())
|
||||
{
|
||||
Map.Entry e = (Map.Entry) itr.next();
|
||||
// Optimize in case the Entry is one of our own.
|
||||
if (e instanceof AbstractMap.BasicMapEntry)
|
||||
{
|
||||
AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
|
||||
put(entry.key, entry.value);
|
||||
}
|
||||
else
|
||||
put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes from the HashMap and returns the value which is mapped by the
|
||||
* supplied key. If the key maps to nothing, then the HashMap remains
|
||||
* unchanged, and <code>null</code> is returned. NOTE: Since the value
|
||||
* could also be null, you must use containsKey to see if you are
|
||||
* actually removing a mapping.
|
||||
*
|
||||
* @param key the key used to locate the value to remove
|
||||
* @return whatever the key mapped to, if present
|
||||
*/
|
||||
public Object remove(Object key)
|
||||
{
|
||||
int idx = hash(key);
|
||||
HashEntry e = buckets[idx];
|
||||
HashEntry last = null;
|
||||
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(key, e.key))
|
||||
{
|
||||
modCount++;
|
||||
if (last == null)
|
||||
buckets[idx] = e.next;
|
||||
else
|
||||
last.next = e.next;
|
||||
size--;
|
||||
// Method call necessary for LinkedHashMap to work correctly.
|
||||
return e.cleanup();
|
||||
}
|
||||
last = e;
|
||||
e = e.next;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the Map so it has no keys. This is O(1).
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
modCount++;
|
||||
Arrays.fill(buckets, null);
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this HashMap contains a value <code>o</code>, such that
|
||||
* <code>o.equals(value)</code>.
|
||||
*
|
||||
* @param value the value to search for in this HashMap
|
||||
* @return true if at least one key maps to the value
|
||||
* @see containsKey(Object)
|
||||
*/
|
||||
public boolean containsValue(Object value)
|
||||
{
|
||||
for (int i = buckets.length - 1; i >= 0; i--)
|
||||
{
|
||||
HashEntry e = buckets[i];
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(value, e.value))
|
||||
return true;
|
||||
e = e.next;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shallow clone of this HashMap. The Map itself is cloned,
|
||||
* but its contents are not. This is O(n).
|
||||
*
|
||||
* @return the clone
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
HashMap copy = null;
|
||||
try
|
||||
{
|
||||
copy = (HashMap) super.clone();
|
||||
}
|
||||
catch (CloneNotSupportedException x)
|
||||
{
|
||||
// This is impossible.
|
||||
}
|
||||
copy.buckets = new HashEntry[buckets.length];
|
||||
copy.putAllInternal(this);
|
||||
// Clear the entry cache. AbstractMap.clone() does the others.
|
||||
copy.entries = null;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "set view" of this HashMap's keys. The set is backed by the
|
||||
* HashMap, so changes in one show up in the other. The set supports
|
||||
* element removal, but not element addition.
|
||||
*
|
||||
* @return a set view of the keys
|
||||
* @see #values()
|
||||
* @see #entrySet()
|
||||
*/
|
||||
public Set keySet()
|
||||
{
|
||||
if (keys == null)
|
||||
// Create an AbstractSet with custom implementations of those methods
|
||||
// that can be overridden easily and efficiently.
|
||||
keys = new AbstractSet()
|
||||
{
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
public Iterator iterator()
|
||||
{
|
||||
// Cannot create the iterator directly, because of LinkedHashMap.
|
||||
return HashMap.this.iterator(KEYS);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
HashMap.this.clear();
|
||||
}
|
||||
|
||||
public boolean contains(Object o)
|
||||
{
|
||||
return containsKey(o);
|
||||
}
|
||||
|
||||
public boolean remove(Object o)
|
||||
{
|
||||
// Test against the size of the HashMap to determine if anything
|
||||
// really got removed. This is necessary because the return value
|
||||
// of HashMap.remove() is ambiguous in the null case.
|
||||
int oldsize = size;
|
||||
HashMap.this.remove(o);
|
||||
return oldsize != size;
|
||||
}
|
||||
};
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "collection view" (or "bag view") of this HashMap's values.
|
||||
* The collection is backed by the HashMap, so changes in one show up
|
||||
* in the other. The collection supports element removal, but not element
|
||||
* addition.
|
||||
*
|
||||
* @return a bag view of the values
|
||||
* @see #keySet()
|
||||
* @see #entrySet()
|
||||
*/
|
||||
public Collection values()
|
||||
{
|
||||
if (values == null)
|
||||
// We don't bother overriding many of the optional methods, as doing so
|
||||
// wouldn't provide any significant performance advantage.
|
||||
values = new AbstractCollection()
|
||||
{
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
public Iterator iterator()
|
||||
{
|
||||
// Cannot create the iterator directly, because of LinkedHashMap.
|
||||
return HashMap.this.iterator(VALUES);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
HashMap.this.clear();
|
||||
}
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "set view" of this HashMap's entries. The set is backed by
|
||||
* the HashMap, so changes in one show up in the other. The set supports
|
||||
* element removal, but not element addition.<p>
|
||||
*
|
||||
* Note that the iterators for all three views, from keySet(), entrySet(),
|
||||
* and values(), traverse the HashMap in the same sequence.
|
||||
*
|
||||
* @return a set view of the entries
|
||||
* @see #keySet()
|
||||
* @see #values()
|
||||
* @see Map.Entry
|
||||
*/
|
||||
public Set entrySet()
|
||||
{
|
||||
if (entries == null)
|
||||
// Create an AbstractSet with custom implementations of those methods
|
||||
// that can be overridden easily and efficiently.
|
||||
entries = new AbstractSet()
|
||||
{
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
public Iterator iterator()
|
||||
{
|
||||
// Cannot create the iterator directly, because of LinkedHashMap.
|
||||
return HashMap.this.iterator(ENTRIES);
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
HashMap.this.clear();
|
||||
}
|
||||
|
||||
public boolean contains(Object o)
|
||||
{
|
||||
return getEntry(o) != null;
|
||||
}
|
||||
|
||||
public boolean remove(Object o)
|
||||
{
|
||||
HashEntry e = getEntry(o);
|
||||
if (e != null)
|
||||
{
|
||||
HashMap.this.remove(e.key);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for put, that creates and adds a new Entry. This is
|
||||
* overridden in LinkedHashMap for bookkeeping purposes.
|
||||
*
|
||||
* @param key the key of the new Entry
|
||||
* @param value the value
|
||||
* @param idx the index in buckets where the new Entry belongs
|
||||
* @param callRemove whether to call the removeEldestEntry method
|
||||
* @see #put(Object, Object)
|
||||
*/
|
||||
void addEntry(Object key, Object value, int idx, boolean callRemove)
|
||||
{
|
||||
HashEntry e = new HashEntry(key, value);
|
||||
e.next = buckets[idx];
|
||||
buckets[idx] = e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for entrySet(), which matches both key and value
|
||||
* simultaneously.
|
||||
*
|
||||
* @param o the entry to match
|
||||
* @return the matching entry, if found, or null
|
||||
* @see #entrySet()
|
||||
*/
|
||||
// Package visible, for use in nested classes.
|
||||
final HashEntry getEntry(Object o)
|
||||
{
|
||||
if (! (o instanceof Map.Entry))
|
||||
return null;
|
||||
Map.Entry me = (Map.Entry) o;
|
||||
Object key = me.getKey();
|
||||
int idx = hash(key);
|
||||
HashEntry e = buckets[idx];
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(e.key, key))
|
||||
return equals(e.value, me.getValue()) ? e : null;
|
||||
e = e.next;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that returns an index in the buckets array for `key'
|
||||
* based on its hashCode(). Package visible for use by subclasses.
|
||||
*
|
||||
* @param key the key
|
||||
* @return the bucket number
|
||||
*/
|
||||
final int hash(Object key)
|
||||
{
|
||||
return key == null ? 0 : Math.abs(key.hashCode() % buckets.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a parameterized iterator. Must be overrideable, since
|
||||
* LinkedHashMap iterates in a different order.
|
||||
*
|
||||
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
|
||||
* @return the appropriate iterator
|
||||
*/
|
||||
Iterator iterator(int type)
|
||||
{
|
||||
return new HashIterator(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simplified, more efficient internal implementation of putAll(). clone()
|
||||
* should not call putAll or put, in order to be compatible with the JDK
|
||||
* implementation with respect to subclasses.
|
||||
*
|
||||
* @param m the map to initialize this from
|
||||
*/
|
||||
void putAllInternal(Map m)
|
||||
{
|
||||
Iterator itr = m.entrySet().iterator();
|
||||
size = 0;
|
||||
while (itr.hasNext())
|
||||
{
|
||||
size++;
|
||||
Map.Entry e = (Map.Entry) itr.next();
|
||||
Object key = e.getKey();
|
||||
int idx = hash(key);
|
||||
addEntry(key, e.getValue(), idx, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the size of the HashMap and rehashes all keys to new
|
||||
* array indices; this is called when the addition of a new value
|
||||
* would cause size() > threshold. Note that the existing Entry
|
||||
* objects are reused in the new hash table.
|
||||
*
|
||||
* <p>This is not specified, but the new size is twice the current size
|
||||
* plus one; this number is not always prime, unfortunately.
|
||||
*/
|
||||
private void rehash()
|
||||
{
|
||||
HashEntry[] oldBuckets = buckets;
|
||||
|
||||
int newcapacity = (buckets.length * 2) + 1;
|
||||
threshold = (int) (newcapacity * loadFactor);
|
||||
buckets = new HashEntry[newcapacity];
|
||||
|
||||
for (int i = oldBuckets.length - 1; i >= 0; i--)
|
||||
{
|
||||
HashEntry e = oldBuckets[i];
|
||||
while (e != null)
|
||||
{
|
||||
int idx = hash(e.key);
|
||||
HashEntry dest = buckets[idx];
|
||||
HashEntry next = e.next;
|
||||
e.next = buckets[idx];
|
||||
buckets[idx] = e;
|
||||
e = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes this object to the given stream.
|
||||
*
|
||||
* @param s the stream to write to
|
||||
* @throws IOException if the underlying stream fails
|
||||
* @serialData the <i>capacity</i>(int) that is the length of the
|
||||
* bucket array, the <i>size</i>(int) of the hash map
|
||||
* are emitted first. They are followed by size entries,
|
||||
* each consisting of a key (Object) and a value (Object).
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream s) throws IOException
|
||||
{
|
||||
// Write the threshold and loadFactor fields.
|
||||
s.defaultWriteObject();
|
||||
|
||||
s.writeInt(buckets.length);
|
||||
s.writeInt(size);
|
||||
// Avoid creating a wasted Set by creating the iterator directly.
|
||||
Iterator it = iterator(ENTRIES);
|
||||
while (it.hasNext())
|
||||
{
|
||||
HashEntry entry = (HashEntry) it.next();
|
||||
s.writeObject(entry.key);
|
||||
s.writeObject(entry.value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes this object from the given stream.
|
||||
*
|
||||
* @param s the stream to read from
|
||||
* @throws ClassNotFoundException if the underlying stream fails
|
||||
* @throws IOException if the underlying stream fails
|
||||
* @serialData the <i>capacity</i>(int) that is the length of the
|
||||
* bucket array, the <i>size</i>(int) of the hash map
|
||||
* are emitted first. They are followed by size entries,
|
||||
* each consisting of a key (Object) and a value (Object).
|
||||
*/
|
||||
private void readObject(ObjectInputStream s)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
// Read the threshold and loadFactor fields.
|
||||
s.defaultReadObject();
|
||||
|
||||
// Read and use capacity, followed by key/value pairs.
|
||||
buckets = new HashEntry[s.readInt()];
|
||||
int len = s.readInt();
|
||||
size = len;
|
||||
while (len-- > 0)
|
||||
{
|
||||
Object key = s.readObject();
|
||||
addEntry(key, s.readObject(), hash(key), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over HashMap's entries.
|
||||
* This implementation is parameterized to give a sequential view of
|
||||
* keys, values, or entries.
|
||||
*
|
||||
* @author Jon Zeppieri
|
||||
*/
|
||||
private final class HashIterator implements Iterator
|
||||
{
|
||||
/**
|
||||
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
|
||||
* or {@link #ENTRIES}.
|
||||
*/
|
||||
private final int type;
|
||||
/**
|
||||
* The number of modifications to the backing HashMap that we know about.
|
||||
*/
|
||||
private int knownMod = modCount;
|
||||
/** The number of elements remaining to be returned by next(). */
|
||||
private int count = size;
|
||||
/** Current index in the physical hash table. */
|
||||
private int idx = buckets.length;
|
||||
/** The last Entry returned by a next() call. */
|
||||
private HashEntry last;
|
||||
/**
|
||||
* The next entry that should be returned by next(). It is set to something
|
||||
* if we're iterating through a bucket that contains multiple linked
|
||||
* entries. It is null if next() needs to find a new bucket.
|
||||
*/
|
||||
private HashEntry next;
|
||||
|
||||
/**
|
||||
* Construct a new HashIterator with the supplied type.
|
||||
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
|
||||
*/
|
||||
HashIterator(int type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Iterator has more elements.
|
||||
* @return true if there are more elements
|
||||
* @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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 (>= 0)
|
||||
* @throws IllegalArgumentException if (initialCapacity < 0)
|
||||
*/
|
||||
public LinkedHashMap(int initialCapacity)
|
||||
{
|
||||
super(initialCapacity);
|
||||
accessOrder = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new insertion-orderd LinkedHashMap with a specific
|
||||
* inital capacity and load factor.
|
||||
*
|
||||
* @param initialCapacity the initial capacity (>= 0)
|
||||
* @param loadFactor the load factor (> 0, not NaN)
|
||||
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
||||
* ! (loadFactor > 0.0)
|
||||
*/
|
||||
public LinkedHashMap(int initialCapacity, float loadFactor)
|
||||
{
|
||||
super(initialCapacity, loadFactor);
|
||||
accessOrder = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new LinkedHashMap with a specific inital capacity, load
|
||||
* factor, and ordering mode.
|
||||
*
|
||||
* @param initialCapacity the initial capacity (>=0)
|
||||
* @param loadFactor the load factor (>0, not NaN)
|
||||
* @param accessOrder true for access-order, false for insertion-order
|
||||
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
||||
* ! (loadFactor > 0.0)
|
||||
*/
|
||||
public LinkedHashMap(int initialCapacity, float loadFactor,
|
||||
boolean accessOrder)
|
||||
{
|
||||
super(initialCapacity, loadFactor);
|
||||
this.accessOrder = accessOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the Map so it has no keys. This is O(1).
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
super.clear();
|
||||
root = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this HashMap contains a value
|
||||
* <code>o</code>, such that <code>o.equals(value)</code>.
|
||||
*
|
||||
* @param value the value to search for in this HashMap
|
||||
* @return <code>true</code> if at least one key maps to the value
|
||||
*/
|
||||
public boolean containsValue(Object value)
|
||||
{
|
||||
LinkedHashEntry e = root;
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(value, e.value))
|
||||
return true;
|
||||
e = e.succ;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value in this Map associated with the supplied key,
|
||||
* or <code>null</code> if the key maps to nothing. If this is an
|
||||
* access-ordered Map and the key is found, this performs structural
|
||||
* modification, moving the key to the newest end of the list. NOTE:
|
||||
* Since the value could also be null, you must use containsKey to
|
||||
* see if this key actually maps to something.
|
||||
*
|
||||
* @param key the key for which to fetch an associated value
|
||||
* @return what the key maps to, if present
|
||||
* @see #put(Object, Object)
|
||||
* @see #containsKey(Object)
|
||||
*/
|
||||
public Object get(Object key)
|
||||
{
|
||||
int idx = hash(key);
|
||||
HashEntry e = buckets[idx];
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(key, e.key))
|
||||
{
|
||||
e.access();
|
||||
return e.value;
|
||||
}
|
||||
e = e.next;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this map should remove the eldest entry.
|
||||
* This method is invoked by all calls to <code>put</code> and
|
||||
* <code>putAll</code> which place a new entry in the map, providing
|
||||
* the implementer an opportunity to remove the eldest entry any time
|
||||
* a new one is added. This can be used to save memory usage of the
|
||||
* hashtable, as well as emulating a cache, by deleting stale entries.
|
||||
* <p>
|
||||
*
|
||||
* For example, to keep the Map limited to 100 entries, override as follows:
|
||||
* <pre>
|
||||
* private static final int MAX_ENTRIES = 100;
|
||||
* protected boolean removeEldestEntry(Map.Entry eldest)
|
||||
* {
|
||||
* return size() > MAX_ENTRIES;
|
||||
* }
|
||||
* </pre><p>
|
||||
*
|
||||
* Typically, this method does not modify the map, but just uses the
|
||||
* return value as an indication to <code>put</code> whether to proceed.
|
||||
* However, if you override it to modify the map, you must return false
|
||||
* (indicating that <code>put</code> should leave the modified map alone),
|
||||
* or you face unspecified behavior. Remember that in access-order mode,
|
||||
* even calling <code>get</code> is a structural modification, but using
|
||||
* the collections views (such as <code>keySet</code>) is not.
|
||||
* <p>
|
||||
*
|
||||
* This method is called after the eldest entry has been inserted, so
|
||||
* if <code>put</code> was called on a previously empty map, the eldest
|
||||
* entry is the one you just put in! The default implementation just
|
||||
* returns <code>false</code>, so that this map always behaves like
|
||||
* a normal one with unbounded growth.
|
||||
*
|
||||
* @param eldest the eldest element which would be removed if this
|
||||
* returns true. For an access-order map, this is the least
|
||||
* recently accessed; for an insertion-order map, this is the
|
||||
* earliest element inserted.
|
||||
* @return true if <code>eldest</code> should be removed
|
||||
*/
|
||||
protected boolean removeEldestEntry(Map.Entry eldest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method called by <code>put</code>, which creates and adds a
|
||||
* new Entry, followed by performing bookkeeping (like removeEldestEntry).
|
||||
*
|
||||
* @param key the key of the new Entry
|
||||
* @param value the value
|
||||
* @param idx the index in buckets where the new Entry belongs
|
||||
* @param callRemove whether to call the removeEldestEntry method
|
||||
* @see #put(Object, Object)
|
||||
* @see #removeEldestEntry(Map.Entry)
|
||||
* @see LinkedHashEntry#LinkedHashEntry(Object, Object)
|
||||
*/
|
||||
void addEntry(Object key, Object value, int idx, boolean callRemove)
|
||||
{
|
||||
LinkedHashEntry e = new LinkedHashEntry(key, value);
|
||||
e.next = buckets[idx];
|
||||
buckets[idx] = e;
|
||||
if (callRemove && removeEldestEntry(root))
|
||||
remove(root.key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method, called by clone() to reset the doubly-linked list.
|
||||
*
|
||||
* @param m the map to add entries from
|
||||
* @see #clone()
|
||||
*/
|
||||
void putAllInternal(Map m)
|
||||
{
|
||||
root = null;
|
||||
super.putAllInternal(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a parameterized iterator. This allows traversal to follow
|
||||
* the doubly-linked list instead of the random bin order of HashMap.
|
||||
*
|
||||
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
|
||||
* @return the appropriate iterator
|
||||
*/
|
||||
Iterator iterator(final int type)
|
||||
{
|
||||
return new Iterator()
|
||||
{
|
||||
/** The current Entry. */
|
||||
LinkedHashEntry current = root;
|
||||
|
||||
/** The previous Entry returned by next(). */
|
||||
LinkedHashEntry last;
|
||||
|
||||
/** The number of known modifications to the backing Map. */
|
||||
int knownMod = modCount;
|
||||
|
||||
/**
|
||||
* Returns true if the Iterator has more elements.
|
||||
*
|
||||
* @return true if there are more elements
|
||||
* @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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 < 0) or (n >= size).
|
||||
*
|
||||
* @param n the number of the entry to get
|
||||
* @return the entry at position n
|
||||
*/
|
||||
// Package visible for use in nested classes.
|
||||
Entry getEntry(int n)
|
||||
{
|
||||
Entry e;
|
||||
if (n < size / 2)
|
||||
{
|
||||
e = first;
|
||||
// n less than size/2, iterate from start
|
||||
while (n-- > 0)
|
||||
e = e.next;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = last;
|
||||
// n greater than size/2, iterate from end
|
||||
while (++n < size)
|
||||
e = e.previous;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an entry from the list. This will adjust size and deal with
|
||||
* `first' and `last' appropriatly.
|
||||
*
|
||||
* @param e the entry to remove
|
||||
*/
|
||||
// Package visible for use in nested classes.
|
||||
void removeEntry(Entry e)
|
||||
{
|
||||
modCount++;
|
||||
size--;
|
||||
if (size == 0)
|
||||
first = last = null;
|
||||
else
|
||||
{
|
||||
if (e == first)
|
||||
{
|
||||
first = e.next;
|
||||
e.next.previous = null;
|
||||
}
|
||||
else if (e == last)
|
||||
{
|
||||
last = e.previous;
|
||||
e.previous.next = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.next.previous = e.previous;
|
||||
e.previous.next = e.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the index is in the range of possible elements (inclusive).
|
||||
*
|
||||
* @param index the index to check
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index > size
|
||||
*/
|
||||
private void checkBoundsInclusive(int index)
|
||||
{
|
||||
if (index < 0 || index > size)
|
||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
|
||||
+ size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the index is in the range of existing elements (exclusive).
|
||||
*
|
||||
* @param index the index to check
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index >= size
|
||||
*/
|
||||
private void checkBoundsExclusive(int index)
|
||||
{
|
||||
if (index < 0 || index >= size)
|
||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
|
||||
+ size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty linked list.
|
||||
*/
|
||||
public LinkedList()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a linked list containing the elements, in order, of a given
|
||||
* collection.
|
||||
*
|
||||
* @param c the collection to populate this list from
|
||||
* @throws NullPointerException if c is null
|
||||
*/
|
||||
public LinkedList(Collection c)
|
||||
{
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first element in the list.
|
||||
*
|
||||
* @return the first list element
|
||||
* @throws NoSuchElementException if the list is empty
|
||||
*/
|
||||
public Object getFirst()
|
||||
{
|
||||
if (size == 0)
|
||||
throw new NoSuchElementException();
|
||||
return first.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last element in the list.
|
||||
*
|
||||
* @return the last list element
|
||||
* @throws NoSuchElementException if the list is empty
|
||||
*/
|
||||
public Object getLast()
|
||||
{
|
||||
if (size == 0)
|
||||
throw new NoSuchElementException();
|
||||
return last.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove and return the first element in the list.
|
||||
*
|
||||
* @return the former first element in the list
|
||||
* @throws NoSuchElementException if the list is empty
|
||||
*/
|
||||
public Object removeFirst()
|
||||
{
|
||||
if (size == 0)
|
||||
throw new NoSuchElementException();
|
||||
modCount++;
|
||||
size--;
|
||||
Object r = first.data;
|
||||
|
||||
if (first.next != null)
|
||||
first.next.previous = null;
|
||||
else
|
||||
last = null;
|
||||
|
||||
first = first.next;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove and return the last element in the list.
|
||||
*
|
||||
* @return the former last element in the list
|
||||
* @throws NoSuchElementException if the list is empty
|
||||
*/
|
||||
public Object removeLast()
|
||||
{
|
||||
if (size == 0)
|
||||
throw new NoSuchElementException();
|
||||
modCount++;
|
||||
size--;
|
||||
Object r = last.data;
|
||||
|
||||
if (last.previous != null)
|
||||
last.previous.next = null;
|
||||
else
|
||||
first = null;
|
||||
|
||||
last = last.previous;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the first of the list.
|
||||
*
|
||||
* @param o the element to insert
|
||||
*/
|
||||
public void addFirst(Object o)
|
||||
{
|
||||
Entry e = new Entry(o);
|
||||
|
||||
modCount++;
|
||||
if (size == 0)
|
||||
first = last = e;
|
||||
else
|
||||
{
|
||||
e.next = first;
|
||||
first.previous = e;
|
||||
first = e;
|
||||
}
|
||||
size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the last of the list.
|
||||
*
|
||||
* @param o the element to insert
|
||||
*/
|
||||
public void addLast(Object o)
|
||||
{
|
||||
addLastEntry(new Entry(o));
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an element at the end of the list.
|
||||
*
|
||||
* @param e the entry to add
|
||||
*/
|
||||
private void addLastEntry(Entry e)
|
||||
{
|
||||
modCount++;
|
||||
if (size == 0)
|
||||
first = last = e;
|
||||
else
|
||||
{
|
||||
e.previous = last;
|
||||
last.next = e;
|
||||
last = e;
|
||||
}
|
||||
size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the list contains the given object. Comparison is done by
|
||||
* <code>o == null ? e = null : o.equals(e)</code>.
|
||||
*
|
||||
* @param o the element to look for
|
||||
* @return true if it is found
|
||||
*/
|
||||
public boolean contains(Object o)
|
||||
{
|
||||
Entry e = first;
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(o, e.data))
|
||||
return true;
|
||||
e = e.next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the list.
|
||||
*
|
||||
* @return the list size
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an element to the end of the list.
|
||||
*
|
||||
* @param 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 < 0 || index > size()
|
||||
*/
|
||||
public boolean addAll(int index, Collection c)
|
||||
{
|
||||
checkBoundsInclusive(index);
|
||||
int csize = c.size();
|
||||
|
||||
if (csize == 0)
|
||||
return false;
|
||||
|
||||
Iterator itr = c.iterator();
|
||||
|
||||
// Get the entries just before and after index. If index is at the start
|
||||
// of the list, BEFORE is null. If index is at the end of the list, AFTER
|
||||
// is null. If the list is empty, both are null.
|
||||
Entry after = null;
|
||||
Entry before = null;
|
||||
if (index != size)
|
||||
{
|
||||
after = getEntry(index);
|
||||
before = after.previous;
|
||||
}
|
||||
else
|
||||
before = last;
|
||||
|
||||
// Create the first new entry. We do not yet set the link from `before'
|
||||
// to the first entry, in order to deal with the case where (c == this).
|
||||
// [Actually, we don't have to handle this case to fufill the
|
||||
// contract for addAll(), but Sun's implementation appears to.]
|
||||
Entry e = new Entry(itr.next());
|
||||
e.previous = before;
|
||||
Entry prev = e;
|
||||
Entry firstNew = e;
|
||||
|
||||
// Create and link all the remaining entries.
|
||||
for (int pos = 1; pos < csize; pos++)
|
||||
{
|
||||
e = new Entry(itr.next());
|
||||
e.previous = prev;
|
||||
prev.next = e;
|
||||
prev = e;
|
||||
}
|
||||
|
||||
// Link the new chain of entries into the list.
|
||||
modCount++;
|
||||
size += csize;
|
||||
prev.next = after;
|
||||
if (after != null)
|
||||
after.previous = e;
|
||||
else
|
||||
last = e;
|
||||
|
||||
if (before != null)
|
||||
before.next = firstNew;
|
||||
else
|
||||
first = firstNew;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements from this list.
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
modCount++;
|
||||
first = null;
|
||||
last = null;
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the element at index.
|
||||
*
|
||||
* @param index the place to look
|
||||
* @return the element at index
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||
*/
|
||||
public Object get(int index)
|
||||
{
|
||||
checkBoundsExclusive(index);
|
||||
return getEntry(index).data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the element at the given location in the list.
|
||||
*
|
||||
* @param index which index to change
|
||||
* @param o the new element
|
||||
* @return the prior element
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||
*/
|
||||
public Object set(int index, Object o)
|
||||
{
|
||||
checkBoundsExclusive(index);
|
||||
Entry e = getEntry(index);
|
||||
Object old = e.data;
|
||||
e.data = o;
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts an element in the given position in the list.
|
||||
*
|
||||
* @param index where to insert the element
|
||||
* @param o the element to insert
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||
*/
|
||||
public void add(int index, Object o)
|
||||
{
|
||||
checkBoundsInclusive(index);
|
||||
Entry e = new Entry(o);
|
||||
|
||||
if (index < size)
|
||||
{
|
||||
modCount++;
|
||||
Entry after = getEntry(index);
|
||||
e.next = after;
|
||||
e.previous = after.previous;
|
||||
if (after.previous == null)
|
||||
first = e;
|
||||
else
|
||||
after.previous.next = e;
|
||||
after.previous = e;
|
||||
size++;
|
||||
}
|
||||
else
|
||||
addLastEntry(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at the given position from the list.
|
||||
*
|
||||
* @param index the location of the element to remove
|
||||
* @return the removed element
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||
*/
|
||||
public Object remove(int index)
|
||||
{
|
||||
checkBoundsExclusive(index);
|
||||
Entry e = getEntry(index);
|
||||
removeEntry(e);
|
||||
return e.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first index where the element is located in the list, or -1.
|
||||
*
|
||||
* @param o the element to look for
|
||||
* @return its position, or -1 if not found
|
||||
*/
|
||||
public int indexOf(Object o)
|
||||
{
|
||||
int index = 0;
|
||||
Entry e = first;
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(o, e.data))
|
||||
return index;
|
||||
index++;
|
||||
e = e.next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last index where the element is located in the list, or -1.
|
||||
*
|
||||
* @param o the element to look for
|
||||
* @return its position, or -1 if not found
|
||||
*/
|
||||
public int lastIndexOf(Object o)
|
||||
{
|
||||
int index = size - 1;
|
||||
Entry e = last;
|
||||
while (e != null)
|
||||
{
|
||||
if (equals(o, e.data))
|
||||
return index;
|
||||
index--;
|
||||
e = e.previous;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a ListIterator over this list, starting at a given index. The
|
||||
* ListIterator returned by this method supports the add, remove and set
|
||||
* methods.
|
||||
*
|
||||
* @param index the index of the element to be returned by the first call to
|
||||
* next(), or size() to be initially positioned at the end of the list
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||
*/
|
||||
public ListIterator listIterator(int index)
|
||||
{
|
||||
checkBoundsInclusive(index);
|
||||
return new LinkedListItr(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shallow copy of this LinkedList (the elements are not cloned).
|
||||
*
|
||||
* @return an object of the same class as this object, containing the
|
||||
* same elements in the same order
|
||||
*/
|
||||
public Object clone()
|
||||
{
|
||||
LinkedList copy = null;
|
||||
try
|
||||
{
|
||||
copy = (LinkedList) super.clone();
|
||||
}
|
||||
catch (CloneNotSupportedException ex)
|
||||
{
|
||||
}
|
||||
copy.clear();
|
||||
copy.addAll(this);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array which contains the elements of the list in order.
|
||||
*
|
||||
* @return an array containing the list elements
|
||||
*/
|
||||
public Object[] toArray()
|
||||
{
|
||||
Object[] array = new Object[size];
|
||||
Entry e = first;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
array[i] = e.data;
|
||||
e = e.next;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Array whose component type is the runtime component type of
|
||||
* the passed-in Array. The returned Array is populated with all of the
|
||||
* elements in this LinkedList. If the passed-in Array is not large enough
|
||||
* to store all of the elements in this List, a new Array will be created
|
||||
* and returned; if the passed-in Array is <i>larger</i> than the size
|
||||
* of this List, then size() index will be set to null.
|
||||
*
|
||||
* @param a the passed-in Array
|
||||
* @return an array representation of this list
|
||||
* @throws ArrayStoreException if the runtime type of a does not allow
|
||||
* an element in this list
|
||||
* @throws NullPointerException if a is null
|
||||
*/
|
||||
public Object[] toArray(Object[] a)
|
||||
{
|
||||
if (a.length < size)
|
||||
a = (Object[]) Array.newInstance(a.getClass().getComponentType(), size);
|
||||
else if (a.length > size)
|
||||
a[size] = null;
|
||||
Entry e = first;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
a[i] = e.data;
|
||||
e = e.next;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes this object to the given stream.
|
||||
*
|
||||
* @param s the stream to write to
|
||||
* @throws IOException if the underlying stream fails
|
||||
* @serialData the size of the list (int), followed by all the elements
|
||||
* (Object) in proper order
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream s) throws IOException
|
||||
{
|
||||
s.defaultWriteObject();
|
||||
s.writeInt(size);
|
||||
Entry e = first;
|
||||
while (e != null)
|
||||
{
|
||||
s.writeObject(e.data);
|
||||
e = e.next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes this object from the given stream.
|
||||
*
|
||||
* @param s the stream to read from
|
||||
* @throws ClassNotFoundException if the underlying stream fails
|
||||
* @throws IOException if the underlying stream fails
|
||||
* @serialData the size of the list (int), followed by all the elements
|
||||
* (Object) in proper order
|
||||
*/
|
||||
private void readObject(ObjectInputStream s)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
s.defaultReadObject();
|
||||
int i = s.readInt();
|
||||
while (--i >= 0)
|
||||
addLastEntry(new Entry(s.readObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* A ListIterator over the list. This class keeps track of its
|
||||
* position in the list and the two list entries it is between.
|
||||
*
|
||||
* @author Original author unknown
|
||||
* @author Eric Blake (ebb9@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
|
||||
}
|
||||
@@ -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 < 0 || index > size()
|
||||
* @throws ClassCastException if o cannot be added to this list due to its
|
||||
* type
|
||||
* @throws IllegalArgumentException if o cannot be added to this list for
|
||||
* some other reason
|
||||
* @throws NullPointerException if o is null and this list doesn't support
|
||||
* the addition of null values.
|
||||
*/
|
||||
void add(int index, Object o);
|
||||
|
||||
/**
|
||||
* Add an element to the end of the list (optional operation). If the list
|
||||
* imposes restraints on what can be inserted, such as no null elements,
|
||||
* this should be documented.
|
||||
*
|
||||
* @param o the object to add
|
||||
* @return true, as defined by Collection for a modified list
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* add operation
|
||||
* @throws ClassCastException if o cannot be added to this list due to its
|
||||
* type
|
||||
* @throws IllegalArgumentException if o cannot be added to this list for
|
||||
* some other reason
|
||||
* @throws NullPointerException if o is null and this list doesn't support
|
||||
* the addition of null values.
|
||||
*/
|
||||
boolean add(Object o);
|
||||
|
||||
/**
|
||||
* Insert the contents of a collection into the list at a given position
|
||||
* (optional operation). Shift all elements at that position to the right
|
||||
* by the number of elements inserted. This operation is undefined if
|
||||
* this list is modified during the operation (for example, if you try
|
||||
* to insert a list into itself).
|
||||
*
|
||||
* @param index the location to insert the collection
|
||||
* @param c the collection to insert
|
||||
* @return true if the list was modified by this action, that is, if c is
|
||||
* non-empty
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* addAll operation
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||
* @throws ClassCastException if some element of c cannot be added to this
|
||||
* list due to its type
|
||||
* @throws IllegalArgumentException if some element of c cannot be added
|
||||
* to this list for some other reason
|
||||
* @throws NullPointerException if some element of c is null and this list
|
||||
* doesn't support the addition of null values.
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
* @see #add(int, Object)
|
||||
*/
|
||||
boolean addAll(int index, Collection c);
|
||||
|
||||
/**
|
||||
* Add the contents of a collection to the end of the list (optional
|
||||
* operation). This operation is undefined if this list is modified
|
||||
* during the operation (for example, if you try to insert a list into
|
||||
* itself).
|
||||
*
|
||||
* @param c the collection to add
|
||||
* @return true if the list was modified by this action, that is, if c is
|
||||
* non-empty
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* addAll operation
|
||||
* @throws ClassCastException if some element of c cannot be added to this
|
||||
* list due to its type
|
||||
* @throws IllegalArgumentException if some element of c cannot be added
|
||||
* to this list for some other reason
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
* @throws NullPointerException if some element of c is null and this list
|
||||
* doesn't support the addition of null values.
|
||||
* @see #add(Object)
|
||||
*/
|
||||
boolean addAll(Collection c);
|
||||
|
||||
/**
|
||||
* Clear the list, such that a subsequent call to isEmpty() would return
|
||||
* true (optional operation).
|
||||
*
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* clear operation
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Test whether this list contains a given object as one of its elements.
|
||||
* This is defined as the existence of an element e such that
|
||||
* <code>o == null ? e == null : o.equals(e)</code>.
|
||||
*
|
||||
* @param o the element to look for
|
||||
* @return true if this list contains the element
|
||||
* @throws ClassCastException if the type of o is not a valid type
|
||||
* for this list.
|
||||
* @throws NullPointerException if o is null and the list doesn't
|
||||
* support null values.
|
||||
*/
|
||||
boolean contains(Object o);
|
||||
|
||||
/**
|
||||
* Test whether this list contains every element in a given collection.
|
||||
*
|
||||
* @param c the collection to test for
|
||||
* @return true if for every element o in c, contains(o) would return true
|
||||
* @throws NullPointerException if the collection is null
|
||||
* @throws ClassCastException if the type of any element in c is not a valid
|
||||
* type for this list.
|
||||
* @throws NullPointerException if some element of c is null and this
|
||||
* list does not support null values.
|
||||
* @see #contains(Object)
|
||||
*/
|
||||
boolean containsAll(Collection c);
|
||||
|
||||
/**
|
||||
* Test whether this list is equal to another object. A List is defined to be
|
||||
* equal to an object if and only if that object is also a List, and the two
|
||||
* lists have the same sequence. Two lists l1 and l2 are equal if and only
|
||||
* if <code>l1.size() == l2.size()</code>, and for every integer n between 0
|
||||
* and <code>l1.size() - 1</code> inclusive, <code>l1.get(n) == null ?
|
||||
* l2.get(n) == null : l1.get(n).equals(l2.get(n))</code>.
|
||||
*
|
||||
* @param o the object to test for equality with this list
|
||||
* @return true if o is equal to this list
|
||||
* @see Object#equals(Object)
|
||||
* @see #hashCode()
|
||||
*/
|
||||
boolean equals(Object o);
|
||||
|
||||
/**
|
||||
* Get the element at a given index in this list.
|
||||
*
|
||||
* @param index the index of the element to be returned
|
||||
* @return the element at index index in this list
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||
*/
|
||||
Object get(int index);
|
||||
|
||||
/**
|
||||
* Obtains a hash code for this list. In order to obey the general
|
||||
* contract of the hashCode method of class Object, this value is
|
||||
* calculated as follows:
|
||||
*
|
||||
<p><pre>hashCode = 1;
|
||||
Iterator i = list.iterator();
|
||||
while (i.hasNext())
|
||||
{
|
||||
Object obj = i.next();
|
||||
hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
|
||||
}</pre>
|
||||
*
|
||||
* <p>This ensures that the general contract of Object.hashCode()
|
||||
* is adhered to.
|
||||
*
|
||||
* @return the hash code of this list
|
||||
* @see Object#hashCode()
|
||||
* @see #equals(Object)
|
||||
*/
|
||||
int hashCode();
|
||||
|
||||
/**
|
||||
* Obtain the first index at which a given object is to be found in this
|
||||
* list.
|
||||
*
|
||||
* @param o the object to search for
|
||||
* @return the least integer n such that <code>o == null ? get(n) == null :
|
||||
* o.equals(get(n))</code>, or -1 if there is no such index.
|
||||
* @throws ClassCastException if the type of o is not a valid
|
||||
* type for this list.
|
||||
* @throws NullPointerException if o is null and this
|
||||
* list does not support null values.
|
||||
*/
|
||||
int indexOf(Object o);
|
||||
|
||||
/**
|
||||
* Test whether this list is empty, that is, if size() == 0.
|
||||
*
|
||||
* @return true if this list contains no elements
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Obtain an Iterator over this list, whose sequence is the list order.
|
||||
*
|
||||
* @return an Iterator over the elements of this list, in order
|
||||
*/
|
||||
Iterator iterator();
|
||||
|
||||
/**
|
||||
* Obtain the last index at which a given object is to be found in this
|
||||
* list.
|
||||
*
|
||||
* @return the greatest integer n such that <code>o == null ? get(n) == null
|
||||
* : o.equals(get(n))</code>, or -1 if there is no such index.
|
||||
* @throws ClassCastException if the type of o is not a valid
|
||||
* type for this list.
|
||||
* @throws NullPointerException if o is null and this
|
||||
* list does not support null values.
|
||||
*/
|
||||
int lastIndexOf(Object o);
|
||||
|
||||
/**
|
||||
* Obtain a ListIterator over this list, starting at the beginning.
|
||||
*
|
||||
* @return a ListIterator over the elements of this list, in order, starting
|
||||
* at the beginning
|
||||
*/
|
||||
ListIterator listIterator();
|
||||
|
||||
/**
|
||||
* Obtain a ListIterator over this list, starting at a given position.
|
||||
* A first call to next() would return the same as get(index), and a
|
||||
* first call to previous() would return the same as get(index - 1).
|
||||
*
|
||||
* @param index the position, between 0 and size() inclusive, to begin the
|
||||
* iteration from
|
||||
* @return a ListIterator over the elements of this list, in order, starting
|
||||
* at index
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||
*/
|
||||
ListIterator listIterator(int index);
|
||||
|
||||
/**
|
||||
* Remove the element at a given position in this list (optional operation).
|
||||
* Shifts all remaining elements to the left to fill the gap.
|
||||
*
|
||||
* @param index the position within the list of the object to remove
|
||||
* @return the object that was removed
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* remove operation
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||
*/
|
||||
Object remove(int index);
|
||||
|
||||
/**
|
||||
* Remove the first occurence of an object from this list (optional
|
||||
* operation). That is, remove the first element e such that
|
||||
* <code>o == null ? e == null : o.equals(e)</code>.
|
||||
*
|
||||
* @param o the object to remove
|
||||
* @return true if the list changed as a result of this call, that is, if
|
||||
* the list contained at least one occurrence of o
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* remove operation
|
||||
* @throws ClassCastException if the type of o is not a valid
|
||||
* type for this list.
|
||||
* @throws NullPointerException if o is null and this
|
||||
* list does not support removing null values.
|
||||
*/
|
||||
boolean remove(Object o);
|
||||
|
||||
/**
|
||||
* Remove all elements of a given collection from this list (optional
|
||||
* operation). That is, remove every element e such that c.contains(e).
|
||||
*
|
||||
* @param c the collection to filter out
|
||||
* @return true if this list was modified as a result of this call
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* removeAll operation
|
||||
* @throws NullPointerException if the collection is null
|
||||
* @throws ClassCastException if the type of any element in c is not a valid
|
||||
* type for this list.
|
||||
* @throws NullPointerException if some element of c is null and this
|
||||
* list does not support removing null values.
|
||||
* @see #remove(Object)
|
||||
* @see #contains(Object)
|
||||
*/
|
||||
boolean removeAll(Collection c);
|
||||
|
||||
/**
|
||||
* Remove all elements of this list that are not contained in a given
|
||||
* collection (optional operation). That is, remove every element e such
|
||||
* that !c.contains(e).
|
||||
*
|
||||
* @param c the collection to retain
|
||||
* @return true if this list was modified as a result of this call
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* retainAll operation
|
||||
* @throws NullPointerException if the collection is null
|
||||
* @throws ClassCastException if the type of any element in c is not a valid
|
||||
* type for this list.
|
||||
* @throws NullPointerException if some element of c is null and this
|
||||
* list does not support retaining null values.
|
||||
* @see #remove(Object)
|
||||
* @see #contains(Object)
|
||||
*/
|
||||
boolean retainAll(Collection c);
|
||||
|
||||
/**
|
||||
* Replace an element of this list with another object (optional operation).
|
||||
*
|
||||
* @param index the position within this list of the element to be replaced
|
||||
* @param o the object to replace it with
|
||||
* @return the object that was replaced
|
||||
* @throws UnsupportedOperationException if this list does not support the
|
||||
* set operation
|
||||
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||
* @throws ClassCastException if o cannot be added to this list due to its
|
||||
* type
|
||||
* @throws IllegalArgumentException if o cannot be added to this list for
|
||||
* some other reason
|
||||
* @throws NullPointerException if o is null and this
|
||||
* list does not support null values.
|
||||
*/
|
||||
Object set(int index, Object o);
|
||||
|
||||
/**
|
||||
* Get the number of elements in this list. If the list contains more
|
||||
* than Integer.MAX_VALUE elements, return Integer.MAX_VALUE.
|
||||
*
|
||||
* @return the number of elements in the list
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* Obtain a List view of a subsection of this list, from fromIndex
|
||||
* (inclusive) to toIndex (exclusive). If the two indices are equal, the
|
||||
* sublist is empty. The returned list should be modifiable if and only
|
||||
* if this list is modifiable. Changes to the returned list should be
|
||||
* reflected in this list. If this list is structurally modified in
|
||||
* any way other than through the returned list, the result of any subsequent
|
||||
* operations on the returned list is undefined.
|
||||
*
|
||||
* @param fromIndex the index that the returned list should start from
|
||||
* (inclusive)
|
||||
* @param toIndex the index that the returned list should go to (exclusive)
|
||||
* @return a List backed by a subsection of this list
|
||||
* @throws IndexOutOfBoundsException if fromIndex < 0
|
||||
* || toIndex > size() || fromIndex > toIndex
|
||||
*/
|
||||
List subList(int fromIndex, int toIndex);
|
||||
|
||||
/**
|
||||
* Copy the current contents of this list into an array.
|
||||
*
|
||||
* @return an array of type Object[] and length equal to the length of this
|
||||
* list, containing the elements currently in this list, in order
|
||||
*/
|
||||
Object[] toArray();
|
||||
|
||||
/**
|
||||
* Copy the current contents of this list into an array. If the array passed
|
||||
* as an argument has length less than that of this list, an array of the
|
||||
* same run-time type as a, and length equal to the length of this list, is
|
||||
* allocated using Reflection. Otherwise, a itself is used. The elements of
|
||||
* this list are copied into it, and if there is space in the array, the
|
||||
* following element is set to null. The resultant array is returned.
|
||||
* Note: The fact that the following element is set to null is only useful
|
||||
* if it is known that this list does not contain any null elements.
|
||||
*
|
||||
* @param a the array to copy this list into
|
||||
* @return an array containing the elements currently in this list, in
|
||||
* order
|
||||
* @throws ArrayStoreException if the type of any element of the
|
||||
* collection is not a subtype of the element type of a
|
||||
* @throws NullPointerException if the specified array is null
|
||||
*/
|
||||
Object[] toArray(Object[] a);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 << 48) - 1);
|
||||
haveNextNextGaussian = false;
|
||||
}</pre>
|
||||
*
|
||||
* @param seed the new seed
|
||||
*/
|
||||
public synchronized void setSeed(long seed)
|
||||
{
|
||||
this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
|
||||
haveNextNextGaussian = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next pseudorandom number. This returns
|
||||
* an int value whose <code>bits</code> low order bits are
|
||||
* independent chosen random bits (0 and 1 are equally likely).
|
||||
* The implementation for java.util.Random is:
|
||||
*
|
||||
<pre>protected synchronized int next(int bits)
|
||||
{
|
||||
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
|
||||
return (int) (seed >>> (48 - bits));
|
||||
}</pre>
|
||||
*
|
||||
* @param bits the number of random bits to generate, in the range 1..32
|
||||
* @return the next pseudorandom value
|
||||
* @since 1.1
|
||||
*/
|
||||
protected synchronized int next(int bits)
|
||||
{
|
||||
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
|
||||
return (int) (seed >>> (48 - bits));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills an array of bytes with random numbers. All possible values
|
||||
* are (approximately) equally likely.
|
||||
* The JDK documentation gives no implementation, but it seems to be:
|
||||
*
|
||||
<pre>public void nextBytes(byte[] bytes)
|
||||
{
|
||||
for (int i = 0; i < bytes.length; i += 4)
|
||||
{
|
||||
int random = next(32);
|
||||
for (int j = 0; i + j < bytes.length && j < 4; j++)
|
||||
{
|
||||
bytes[i+j] = (byte) (random & 0xff)
|
||||
random >>= 8;
|
||||
}
|
||||
}
|
||||
}</pre>
|
||||
*
|
||||
* @param bytes the byte array that should be filled
|
||||
* @throws NullPointerException if bytes is null
|
||||
* @since 1.1
|
||||
*/
|
||||
public void nextBytes(byte[] bytes)
|
||||
{
|
||||
int random;
|
||||
// Do a little bit unrolling of the above algorithm.
|
||||
int max = bytes.length & ~0x3;
|
||||
for (int i = 0; i < max; i += 4)
|
||||
{
|
||||
random = next(32);
|
||||
bytes[i] = (byte) random;
|
||||
bytes[i + 1] = (byte) (random >> 8);
|
||||
bytes[i + 2] = (byte) (random >> 16);
|
||||
bytes[i + 3] = (byte) (random >> 24);
|
||||
}
|
||||
if (max < bytes.length)
|
||||
{
|
||||
random = next(32);
|
||||
for (int j = max; j < bytes.length; j++)
|
||||
{
|
||||
bytes[j] = (byte) random;
|
||||
random >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next pseudorandom number. This returns
|
||||
* an int value whose 32 bits are independent chosen random bits
|
||||
* (0 and 1 are equally likely). The implementation for
|
||||
* java.util.Random is:
|
||||
*
|
||||
<pre>public int nextInt()
|
||||
{
|
||||
return next(32);
|
||||
}</pre>
|
||||
*
|
||||
* @return the next pseudorandom value
|
||||
*/
|
||||
public int nextInt()
|
||||
{
|
||||
return next(32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next pseudorandom number. This returns
|
||||
* a value between 0(inclusive) and <code>n</code>(exclusive), and
|
||||
* each value has the same likelihodd (1/<code>n</code>).
|
||||
* (0 and 1 are equally likely). The implementation for
|
||||
* java.util.Random is:
|
||||
*
|
||||
<pre>
|
||||
public int nextInt(int n)
|
||||
{
|
||||
if (n <= 0)
|
||||
throw new IllegalArgumentException("n must be positive");
|
||||
|
||||
if ((n & -n) == n) // i.e., n is a power of 2
|
||||
return (int)((n * (long) next(31)) >> 31);
|
||||
|
||||
int bits, val;
|
||||
do
|
||||
{
|
||||
bits = next(31);
|
||||
val = bits % n;
|
||||
}
|
||||
while(bits - val + (n-1) < 0);
|
||||
|
||||
return val;
|
||||
}</pre>
|
||||
*
|
||||
* <p>This algorithm would return every value with exactly the same
|
||||
* probability, if the next()-method would be a perfect random number
|
||||
* generator.
|
||||
*
|
||||
* The loop at the bottom only accepts a value, if the random
|
||||
* number was between 0 and the highest number less then 1<<31,
|
||||
* which is divisible by n. The probability for this is high for small
|
||||
* n, and the worst case is 1/2 (for n=(1<<30)+1).
|
||||
*
|
||||
* The special treatment for n = power of 2, selects the high bits of
|
||||
* the random number (the loop at the bottom would select the low order
|
||||
* bits). This is done, because the low order bits of linear congruential
|
||||
* number generators (like the one used in this class) are known to be
|
||||
* ``less random'' than the high order bits.
|
||||
*
|
||||
* @param n the upper bound
|
||||
* @throws IllegalArgumentException if the given upper bound is negative
|
||||
* @return the next pseudorandom value
|
||||
* @since 1.2
|
||||
*/
|
||||
public int nextInt(int n)
|
||||
{
|
||||
if (n <= 0)
|
||||
throw new IllegalArgumentException("n must be positive");
|
||||
if ((n & -n) == n) // i.e., n is a power of 2
|
||||
return (int) ((n * (long) next(31)) >> 31);
|
||||
int bits, val;
|
||||
do
|
||||
{
|
||||
bits = next(31);
|
||||
val = bits % n;
|
||||
}
|
||||
while (bits - val + (n - 1) < 0);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next pseudorandom long number. All bits of this
|
||||
* long are independently chosen and 0 and 1 have equal likelihood.
|
||||
* The implementation for java.util.Random is:
|
||||
*
|
||||
<pre>public long nextLong()
|
||||
{
|
||||
return ((long) next(32) << 32) + next(32);
|
||||
}</pre>
|
||||
*
|
||||
* @return the next pseudorandom value
|
||||
*/
|
||||
public long nextLong()
|
||||
{
|
||||
return ((long) next(32) << 32) + next(32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next pseudorandom boolean. True and false have
|
||||
* the same probability. The implementation is:
|
||||
*
|
||||
<pre>public boolean nextBoolean()
|
||||
{
|
||||
return next(1) != 0;
|
||||
}</pre>
|
||||
*
|
||||
* @return the next pseudorandom boolean
|
||||
* @since 1.2
|
||||
*/
|
||||
public boolean nextBoolean()
|
||||
{
|
||||
return next(1) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next pseudorandom float uniformly distributed
|
||||
* between 0.0f (inclusive) and 1.0f (exclusive). The
|
||||
* implementation is as follows.
|
||||
*
|
||||
<pre>public float nextFloat()
|
||||
{
|
||||
return next(24) / ((float)(1 << 24));
|
||||
}</pre>
|
||||
*
|
||||
* @return the next pseudorandom float
|
||||
*/
|
||||
public float nextFloat()
|
||||
{
|
||||
return next(24) / (float) (1 << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next pseudorandom double uniformly distributed
|
||||
* between 0.0 (inclusive) and 1.0 (exclusive). The
|
||||
* implementation is as follows.
|
||||
*
|
||||
<pre>public double nextDouble()
|
||||
{
|
||||
return (((long) next(26) << 27) + next(27)) / (double)(1L << 53);
|
||||
}</pre>
|
||||
*
|
||||
* @return the next pseudorandom double
|
||||
*/
|
||||
public double nextDouble()
|
||||
{
|
||||
return (((long) next(26) << 27) + next(27)) / (double) (1L << 53);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the next pseudorandom, Gaussian (normally) distributed
|
||||
* double value, with mean 0.0 and standard deviation 1.0.
|
||||
* The algorithm is as follows.
|
||||
*
|
||||
<pre>public synchronized double nextGaussian()
|
||||
{
|
||||
if (haveNextNextGaussian)
|
||||
{
|
||||
haveNextNextGaussian = false;
|
||||
return nextNextGaussian;
|
||||
}
|
||||
else
|
||||
{
|
||||
double v1, v2, s;
|
||||
do
|
||||
{
|
||||
v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
|
||||
v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
|
||||
s = v1 * v1 + v2 * v2;
|
||||
}
|
||||
while (s >= 1);
|
||||
|
||||
double norm = Math.sqrt(-2 * Math.log(s) / s);
|
||||
nextNextGaussian = v2 * norm;
|
||||
haveNextNextGaussian = true;
|
||||
return v1 * norm;
|
||||
}
|
||||
}</pre>
|
||||
*
|
||||
* <p>This is described in section 3.4.1 of <em>The Art of Computer
|
||||
* Programming, Volume 2</em> by Donald Knuth.
|
||||
*
|
||||
* @return the next pseudorandom Gaussian distributed double
|
||||
*/
|
||||
public synchronized double nextGaussian()
|
||||
{
|
||||
if (haveNextNextGaussian)
|
||||
{
|
||||
haveNextNextGaussian = false;
|
||||
return nextNextGaussian;
|
||||
}
|
||||
double v1, v2, s;
|
||||
do
|
||||
{
|
||||
v1 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
|
||||
v2 = 2 * nextDouble() - 1; // Between -1.0 and 1.0.
|
||||
s = v1 * v1 + v2 * v2;
|
||||
}
|
||||
while (s >= 1);
|
||||
double norm = Math.sqrt(-2 * Math.log(s) / s);
|
||||
nextNextGaussian = v2 * norm;
|
||||
haveNextNextGaussian = true;
|
||||
return v1 * norm;
|
||||
}
|
||||
}
|
||||
@@ -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 < 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.
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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() < 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
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 <= 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 < 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 < 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 < 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 >= 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index > 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 < 0 || index >= 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 < 0 || index >= 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 < 0 || index > 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 < 0 || index >= 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 < 0 || index > 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 < 0
|
||||
* || toIndex > size()
|
||||
* @throws IllegalArgumentException if fromIndex > 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 > 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 > 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 >= 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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> <extension>-Extension-Name:
|
||||
* unique name of the extension</li>
|
||||
* <li> <extension>-Specification-Version:
|
||||
* minimum specification version</li>
|
||||
* <li> <extension>-Implementation-Version:
|
||||
* minimum implementation version</li>
|
||||
* <li> <extension>-Implementation-Vendor-Id:
|
||||
* unique id of implementation vendor</li>
|
||||
* <li> <extension>-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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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("&");
|
||||
break;
|
||||
|
||||
case '<':
|
||||
buf.append("<");
|
||||
break;
|
||||
|
||||
case '>':
|
||||
buf.append(">");
|
||||
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 Ӓ 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);
|
||||
|
||||
}
|
||||
@@ -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 "<unnamed>".
|
||||
* 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 "<unnamed>".
|
||||
* 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();
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user