diff options
Diffstat (limited to 'libjava/classpath/java/util')
-rw-r--r-- | libjava/classpath/java/util/AbstractMap.java | 2 | ||||
-rw-r--r-- | libjava/classpath/java/util/Calendar.java | 8 | ||||
-rw-r--r-- | libjava/classpath/java/util/Collections.java | 4 | ||||
-rw-r--r-- | libjava/classpath/java/util/Date.java | 2 | ||||
-rw-r--r-- | libjava/classpath/java/util/Formatter.java | 4 | ||||
-rw-r--r-- | libjava/classpath/java/util/Hashtable.java | 10 | ||||
-rw-r--r-- | libjava/classpath/java/util/LinkedHashSet.java | 4 | ||||
-rw-r--r-- | libjava/classpath/java/util/Locale.java | 20 | ||||
-rw-r--r-- | libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java | 1015 | ||||
-rw-r--r-- | libjava/classpath/java/util/jar/Manifest.java | 2 | ||||
-rw-r--r-- | libjava/classpath/java/util/logging/Logger.java | 1624 | ||||
-rw-r--r-- | libjava/classpath/java/util/zip/ZipEntry.java | 2 |
12 files changed, 1814 insertions, 883 deletions
diff --git a/libjava/classpath/java/util/AbstractMap.java b/libjava/classpath/java/util/AbstractMap.java index 2f58121cede..02a30a294de 100644 --- a/libjava/classpath/java/util/AbstractMap.java +++ b/libjava/classpath/java/util/AbstractMap.java @@ -524,7 +524,7 @@ public abstract class AbstractMap<K, V> implements Map<K, V> public String toString() { Iterator<Map.Entry<K, V>> entries = entrySet().iterator(); - StringBuffer r = new StringBuffer("{"); + StringBuilder r = new StringBuilder("{"); for (int pos = size(); pos > 0; pos--) { Map.Entry<K, V> entry = entries.next(); diff --git a/libjava/classpath/java/util/Calendar.java b/libjava/classpath/java/util/Calendar.java index 2b385b1a0b2..712296b1a2a 100644 --- a/libjava/classpath/java/util/Calendar.java +++ b/libjava/classpath/java/util/Calendar.java @@ -572,7 +572,7 @@ public abstract class Calendar * Cache of locale->calendar-class mappings. This avoids having to do a ResourceBundle * lookup for every getInstance call. */ - private static HashMap<Locale,Class> cache = new HashMap<Locale,Class>(); + private static final HashMap<Locale,Class> cache = new HashMap<Locale,Class>(); /** Preset argument types for calendar-class constructor lookup. */ private static Class[] ctorArgTypes = new Class[] @@ -1266,7 +1266,7 @@ public abstract class Calendar /** * Compares the time of two calendar instances. - * @param calendar the calendar to which the time should be compared. + * @param cal the calendar to which the time should be compared. * @return 0 if the two calendars are set to the same time, * less than 0 if the time of this calendar is before that of * <code>cal</code>, or more than 0 if the time of this calendar is after @@ -1328,8 +1328,8 @@ public abstract class Calendar */ public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(getClass().getName()).append('['); + StringBuilder sb = new StringBuilder(getClass().getName()); + sb.append('['); sb.append("time="); if (isTimeSet) sb.append(time); diff --git a/libjava/classpath/java/util/Collections.java b/libjava/classpath/java/util/Collections.java index fd802fe9db4..ae2010f1ce5 100644 --- a/libjava/classpath/java/util/Collections.java +++ b/libjava/classpath/java/util/Collections.java @@ -6167,7 +6167,7 @@ public class Collections * correct type. * * @param index the index at which to place the new element. - * @param c the collections of objects to add. + * @param coll the collections of objects to add. * @throws ClassCastException if the type of any element in c is not a * valid type for the underlying collection. */ @@ -6870,7 +6870,7 @@ public class Collections * Adds all pairs within the supplied map to the underlying map, * provided they are all have the correct key and value types. * - * @param m the map, the entries of which should be added + * @param map the map, the entries of which should be added * to the underlying map. * @throws ClassCastException if the type of a key or value is * not a valid type for the underlying map. diff --git a/libjava/classpath/java/util/Date.java b/libjava/classpath/java/util/Date.java index 1ad128ebfc5..8646c19175e 100644 --- a/libjava/classpath/java/util/Date.java +++ b/libjava/classpath/java/util/Date.java @@ -722,7 +722,7 @@ public class Date boolean localTimezone = true; // Trim out any nested stuff in parentheses now to make parsing easier. - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); int parenNesting = 0; int len = string.length(); for (int i = 0; i < len; i++) diff --git a/libjava/classpath/java/util/Formatter.java b/libjava/classpath/java/util/Formatter.java index 12b705bce06..82130782e0f 100644 --- a/libjava/classpath/java/util/Formatter.java +++ b/libjava/classpath/java/util/Formatter.java @@ -291,7 +291,7 @@ public final class Formatter * If the locale is <code>null</code>, then no localization is * applied. * - * @param file the output stream. + * @param out the output stream. * @param charset the character set to use for output. * @param loc the locale to use. * @throws UnsupportedEncodingException if the supplied character @@ -1427,7 +1427,7 @@ public final class Formatter * Outputs a formatted string based on the supplied specification, * <code>fmt</code>, and its arguments using the formatter's locale. * - * @param fmt the format specification. + * @param format the format specification. * @param args the arguments to apply to the specification. * @throws IllegalFormatException if there is a problem with * the syntax of the format diff --git a/libjava/classpath/java/util/Hashtable.java b/libjava/classpath/java/util/Hashtable.java index a85674637e7..07bd9469318 100644 --- a/libjava/classpath/java/util/Hashtable.java +++ b/libjava/classpath/java/util/Hashtable.java @@ -579,7 +579,7 @@ public class Hashtable<K, V> extends Dictionary<K, V> // would repeatedly re-lock/release the monitor, we directly use the // unsynchronized EntryIterator instead. Iterator<Map.Entry<K, V>> entries = new EntryIterator(); - StringBuffer r = new StringBuffer("{"); + StringBuilder r = new StringBuilder("{"); for (int pos = size; pos > 0; pos--) { r.append(entries.next()); @@ -1088,7 +1088,7 @@ public class Hashtable<K, V> extends Dictionary<K, V> * <code>next()</code> gives a different result, by returning just * the key rather than the whole element. */ - private EntryIterator iterator; + private final EntryIterator iterator; /** * Construct a new KeyIterator @@ -1153,7 +1153,7 @@ public class Hashtable<K, V> extends Dictionary<K, V> * <code>next()</code> gives a different result, by returning just * the value rather than the whole element. */ - private EntryIterator iterator; + private final EntryIterator iterator; /** * Construct a new KeyIterator @@ -1294,7 +1294,7 @@ public class Hashtable<K, V> extends Dictionary<K, V> * <code>nextElement()</code> gives a different result, by returning just * the key rather than the whole element. */ - private EntryEnumerator enumerator; + private final EntryEnumerator enumerator; /** * Construct a new KeyEnumerator @@ -1355,7 +1355,7 @@ public class Hashtable<K, V> extends Dictionary<K, V> * <code>nextElement()</code> gives a different result, by returning just * the value rather than the whole element. */ - private EntryEnumerator enumerator; + private final EntryEnumerator enumerator; /** * Construct a new ValueEnumerator diff --git a/libjava/classpath/java/util/LinkedHashSet.java b/libjava/classpath/java/util/LinkedHashSet.java index a0b32f34964..03b9556062c 100644 --- a/libjava/classpath/java/util/LinkedHashSet.java +++ b/libjava/classpath/java/util/LinkedHashSet.java @@ -1,6 +1,6 @@ /* LinkedHashSet.java -- a set backed by a LinkedHashMap, for linked list traversal. - Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -98,7 +98,7 @@ public class LinkedHashSet<T> extends HashSet<T> /** * Construct a new, empty HashSet whose backing HashMap has the default - * capacity (11) and loadFacor (0.75). + * capacity (11) and loadFactor (0.75). */ public LinkedHashSet() { diff --git a/libjava/classpath/java/util/Locale.java b/libjava/classpath/java/util/Locale.java index 846ae7baadc..cd372f24551 100644 --- a/libjava/classpath/java/util/Locale.java +++ b/libjava/classpath/java/util/Locale.java @@ -178,21 +178,21 @@ public final class Locale implements Serializable, Cloneable * * @serial the languange, possibly "" */ - private String language; + private final String language; /** * The country code, as returned by getCountry(). * * @serial the country, possibly "" */ - private String country; + private final String country; /** * The variant code, as returned by getVariant(). * * @serial the variant, possibly "" */ - private String variant; + private final String variant; /** * This is the cached hashcode. When writing to stream, we write -1. @@ -324,13 +324,12 @@ public final class Locale implements Serializable, Cloneable // default locale. if (defaultLocale != null) { - language = convertLanguage(language).intern(); - country = country.toUpperCase().intern(); - variant = variant.intern(); + language = convertLanguage(language); + country = country.toUpperCase(); } - this.language = language; - this.country = country; - this.variant = variant; + this.language = language.intern(); + this.country = country.intern(); + this.variant = variant.intern(); hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode(); } @@ -1022,9 +1021,6 @@ public final class Locale implements Serializable, Cloneable throws IOException, ClassNotFoundException { s.defaultReadObject(); - language = language.intern(); - country = country.intern(); - variant = variant.intern(); hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode(); } } // class Locale diff --git a/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java b/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java index 48c017f50fa..6e4fb9a8ac9 100644 --- a/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java +++ b/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java @@ -41,18 +41,71 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; + import java.lang.reflect.Array; + import java.util.AbstractList; +import java.util.Arrays; import java.util.Collection; +import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; import java.util.RandomAccess; -/** @since 1.5 */ -public class CopyOnWriteArrayList<E> extends AbstractList<E> implements - List<E>, RandomAccess, Cloneable, Serializable +/** + * A thread-safe implementation of an ArrayList. A CopyOnWriteArrayList is + * as special ArrayList which performs copies of the underlying storage + * each time a write (<code>remove</code>, <code>add</code> etc..) operation + * is performed.<br /> + * <br /> + * The update operation in this class run usually in <code>O(n)</code> or worse, + * but traversal operations are fast and efficient, especially when running in + * a multi-thread environment without the need to design complex synchronize + * mechanisms.<br /> + * <br /> + * <code>Iterator</code>s in this class work on a snapshot of the backing store + * at the moment the iterator itself was created, hence the iterator will not + * reflect changes in the underlying storage. Thus, update operation on the + * <code>Iterator</code>s are not supported, but as interferences from other + * threads are impossible, no <code>ConcurrentModificationException</code> + * will be ever thrown from within the <code>Iterator</code>. + * <br /><br /> + * This class is especially useful when used with event handling, like the + * following code demonstrates:<br /> + * <code><pre> + * + * CopyOnWriteArrayList<EventListener> listeners = + * new CopyOnWriteArrayList<EventListener>(); + * + * [...] + * + * for (final EventListener listener : listeners) + * { + * Runnable dispatcher = new Runnable() { + * public void run() + * { + * listener.preferenceChange(event); + * } + * }; + * + * Executor executor = Executors.newSingleThreadExecutor(); + * executor.execute(dispatcher); + * } + * </pre></code> + * + * @since 1.5 + */ +public class CopyOnWriteArrayList<E> + implements List<E>, RandomAccess, Cloneable, Serializable { /** + * + */ + private static final long serialVersionUID = 8673264195747942595L; + + /** * Where the data is stored. */ private transient E[] data; @@ -118,7 +171,7 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements } /** - * Returns true iff element is in this ArrayList. + * Returns true if element is in this ArrayList. * * @param e * the element whose inclusion in the List is being tested @@ -130,6 +183,28 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements } /** + * 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; + } + + /** * Returns the lowest index at which element appears in this List, or -1 if it * does not appear. * @@ -161,7 +236,7 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements for (int i = index; i < data.length; i++) if (equals(e, data[i])) - return i; + return i; return -1; } @@ -197,7 +272,7 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements for (int i = index; i >= 0; i--) if (equals(e, data[i])) - return i; + return i; return -1; } @@ -212,7 +287,6 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements try { clone = (CopyOnWriteArrayList<E>) super.clone(); - clone.data = (E[]) data.clone(); } catch (CloneNotSupportedException e) { @@ -347,18 +421,154 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements */ public synchronized E remove(int index) { - E[] data = this.data; - E[] newData = (E[]) new Object[data.length - 1]; + if (index < 0 || index >= this.size()) + throw new IndexOutOfBoundsException("index = " + index); + + E[] snapshot = this.data; + E[] newData = (E[]) new Object[snapshot.length - 1]; + + E result = snapshot[index]; + if (index > 0) - System.arraycopy(data, 0, newData, 0, index - 1); - System.arraycopy(data, index + 1, newData, index, - data.length - index - 1); - E r = data[index]; + System.arraycopy(snapshot, 0, newData, 0, index); + + System.arraycopy(snapshot, index + 1, newData, index, + snapshot.length - index - 1); + this.data = newData; - return r; + + return result; } /** + * Remove the first occurrence, if any, of the given object from this list, + * returning <code>true</code> if the object was removed, <code>false</code> + * otherwise. + * + * @param element the object to be removed. + * @return true if element was removed, false otherwise. false means also that + * the underlying storage was unchanged after this operation concluded. + */ + public synchronized boolean remove(Object element) + { + E[] snapshot = this.data; + E[] newData = (E[]) new Object[snapshot.length - 1]; + + // search the element to remove while filling the backup array + // this way we can run this method in O(n) + int elementIndex = -1; + for (int i = 0; i < snapshot.length; i++) + { + if (equals(element, snapshot[i])) + { + elementIndex = i; + break; + } + + if (i < newData.length) + newData[i] = snapshot[i]; + } + + if (elementIndex < 0) + return false; + + System.arraycopy(snapshot, elementIndex + 1, newData, elementIndex, + snapshot.length - elementIndex - 1); + this.data = newData; + + return true; + } + + /** + * Removes all the elements contained in the given collection. + * This method removes the elements that are contained in both + * this list and in the given collection. + * + * @param c the collection containing the elements to be removed from this + * list. + * @return true if at least one element was removed, indicating that + * the list internal storage changed as a result, false otherwise. + */ + public synchronized boolean removeAll(Collection<?> c) + { + if (c.size() == 0) + return false; + + E [] snapshot = this.data; + E [] storage = (E[]) new Object[this.data.length]; + boolean changed = false; + + int length = 0; + for (E element : snapshot) + { + // copy all the elements, including null values + // if the collection can hold it + // FIXME: slow operation + if (c.contains(element)) + changed = true; + else + storage[length++] = element; + } + + if (!changed) + return false; + + E[] newData = (E[]) new Object[length]; + System.arraycopy(storage, 0, newData, 0, length); + + this.data = newData; + + return true; + } + + /** + * Removes all the elements that are not in the passed collection. + * If the collection is void, this method has the same effect of + * <code>clear()</code>. + * Please, note that this method is extremely slow (unless the argument has + * <code>size == 0</code>) and has bad performance is both space and time + * usage. + * + * @param c the collection containing the elements to be retained by this + * list. + * @return true the list internal storage changed as a result of this + * operation, false otherwise. + */ + public synchronized boolean retainAll(Collection<?> c) + { + // if the given collection does not contain elements + // we remove all the elements from our storage + if (c.size() == 0) + { + this.clear(); + return true; + } + + E [] snapshot = this.data; + E [] storage = (E[]) new Object[this.data.length]; + + int length = 0; + for (E element : snapshot) + { + if (c.contains(element)) + storage[length++] = element; + } + + // means we retained all the elements previously in our storage + // we are running already slow here, but at least we avoid copying + // another array and changing the internal storage + if (length == snapshot.length) + return false; + + E[] newData = (E[]) new Object[length]; + System.arraycopy(storage, 0, newData, 0, length); + + this.data = newData; + + return true; + } + + /** * Removes all elements from this List */ public synchronized void clear() @@ -399,21 +609,42 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements */ public synchronized boolean addAll(int index, Collection< ? extends E> c) { - E[] data = this.data; - Iterator<? extends E> itr = c.iterator(); + if (index < 0 || index > this.size()) + throw new IndexOutOfBoundsException("index = " + index); + int csize = c.size(); if (csize == 0) return false; - + + E[] data = this.data; + Iterator<? extends E> itr = c.iterator(); + E[] newData = (E[]) new Object[data.length + csize]; - System.arraycopy(data, 0, newData, 0, data.length); - int end = data.length; + + // avoid this call at all if we were asked to put the elements at the + // beginning of our storage + if (index != 0) + System.arraycopy(data, 0, newData, 0, index); + + int itemsLeft = index; + for (E value : c) - newData[end++] = value; + newData[index++] = value; + + // now copy the remaining elements + System.arraycopy(data, itemsLeft, newData, 0, data.length - itemsLeft); + this.data = newData; + return true; } + /** + * Adds an element if the list does not contains it already. + * + * @param val the element to add to the list. + * @return true if the element was added, false otherwise. + */ public synchronized boolean addIfAbsent(E val) { if (contains(val)) @@ -422,16 +653,752 @@ public class CopyOnWriteArrayList<E> extends AbstractList<E> implements return true; } + /** + * Adds all the element from the given collection that are not already + * in this list. + * + * @param c the Collection containing the elements to be inserted + * @return true the list internal storage changed as a result of this + * operation, false otherwise. + */ public synchronized int addAllAbsent(Collection<? extends E> c) { - int result = 0; + int size = c.size(); + if (size == 0) + return 0; + + E [] snapshot = this.data; + E [] storage = (E[]) new Object[size]; + + size = 0; for (E val : c) { - if (addIfAbsent(val)) - ++result; + if (!this.contains(val)) + storage[size++] = val; } - return result; + + if (size == 0) + return 0; + + // append storage to data + E [] newData = (E[]) new Object[snapshot.length + size]; + + System.arraycopy(snapshot, 0, newData, 0, snapshot.length); + System.arraycopy(storage, 0, newData, snapshot.length, size); + + this.data = newData; + + return size; + } + + public String toString() + { + return Arrays.toString(this.data); + } + + public boolean equals(Object o) + { + if (o == null) + return false; + + if (this == o) + return true; + + // let's see if 'o' is a list, if so, we need to compare the elements + // as returned by the iterator + if (o instanceof List) + { + List<?> source = (List<?>) o; + + if (source.size() != this.size()) + return false; + + Iterator<?> sourceIterator = source.iterator(); + for (E element : this) + { + if (!element.equals(sourceIterator.next())) + return false; + } + + return true; + } + + return false; + } + + public int hashCode() + { + // see http://java.sun.com/6/docs/api/java/util/List.html#hashcode() + int hashcode = 1; + for (E element : this) + { + hashcode = 31 * hashcode + (element == null ? 0 : element.hashCode()); + } + return hashcode; + } + + /** + * Return an Iterator containing the elements of this list. + * The Iterator uses a snapshot of the state of the internal storage + * at the moment this method is called and does <strong>not</strong> support + * update operations, so no synchronization is needed to traverse the + * iterator. + * + * @return an Iterator containing the elements of this list in sequence. + */ + public Iterator<E> iterator() + { + return new Iterator<E>() + { + E [] iteratorData = CopyOnWriteArrayList.this.data; + int currentElement = 0; + + public boolean hasNext() + { + return (currentElement < iteratorData.length); + } + + public E next() + { + return iteratorData[currentElement++]; + } + + public void remove() + { + throw new UnsupportedOperationException("updating of elements in " + + "iterators is not supported " + + "by this class"); + } + }; } + + /** + * Return a ListIterator containing the elements of this list. + * The Iterator uses a snapshot of the state of the internal storage + * at the moment this method is called and does <strong>not</strong> support + * update operations, so no synchronization is needed to traverse the + * iterator. + * + * @return a ListIterator containing the elements of this list in sequence. + */ + public ListIterator<E> listIterator() + { + return listIterator(0); + } + + /** + * Return a ListIterator over the elements of this list starting at + * the specified index. An initial call to {@code next()} will thus + * return the element at {@code index}, while an initial call to + * {@code previous()} will return the element at {@code index-1}. The + * Iterator uses a snapshot of the state of the internal storage + * at the moment this method is called and does <strong>not</strong> support + * update operations, so no synchronization is needed to traverse the + * iterator. + * + * @param index the index at which to start iterating. + * @return a ListIterator containing the elements of this list in sequence. + */ + public ListIterator<E> listIterator(final int index) + { + if (index < 0 || index > size()) + throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + + size()); + + return new ListIterator<E>() + { + E [] iteratorData = CopyOnWriteArrayList.this.data; + int currentElement = index; + + public void add(E o) + { + throw new UnsupportedOperationException("updating of elements in " + + "iterators is not supported " + + "by this class"); + } + + public boolean hasNext() + { + return (currentElement < iteratorData.length); + } + + public boolean hasPrevious() + { + return (currentElement > 0); + } + + public E next() + { + if (hasNext() == false) + throw new java.util.NoSuchElementException(); + + return iteratorData[currentElement++]; + } + + public int nextIndex() + { + return (currentElement + 1); + } + + public E previous() + { + if (hasPrevious() == false) + throw new java.util.NoSuchElementException(); + + return iteratorData[--currentElement]; + } + + public int previousIndex() + { + return (currentElement - 1); + } + + public void remove() + { + throw new UnsupportedOperationException("updating of elements in " + + "iterators is not supported " + + "by this class"); + } + + public void set(E o) + { + throw new UnsupportedOperationException("updating of elements in " + + "iterators is not supported " + + "by this class"); + } + + }; + } + + /** + * 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. + * <p> + * + * This implementation returns a subclass of AbstractList. It stores, in + * private fields, the offset and size of the sublist, and the expected + * modCount of the backing list. If the backing list implements RandomAccess, + * the sublist will also. + * <p> + * + * The subclass's <code>set(int, Object)</code>, <code>get(int)</code>, + * <code>add(int, Object)</code>, <code>remove(int)</code>, + * <code>addAll(int, Collection)</code> and + * <code>removeRange(int, int)</code> methods all delegate to the + * corresponding methods on the backing abstract list, after + * bounds-checking the index and adjusting for the offset. The + * <code>addAll(Collection c)</code> method merely returns addAll(size, c). + * The <code>listIterator(int)</code> method returns a "wrapper object" + * over a list iterator on the backing list, which is created with the + * corresponding method on the backing list. The <code>iterator()</code> + * method merely returns listIterator(), and the <code>size()</code> method + * merely returns the subclass's size field. + * <p> + * + * All methods first check to see if the actual modCount of the backing + * list is equal to its expected value, and throw a + * ConcurrentModificationException if it is not. + * + * @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() + * @throws IndexOutOfBoundsException if fromIndex > toIndex + * @see ConcurrentModificationException + * @see RandomAccess + */ + public synchronized List<E> subList(int fromIndex, int toIndex) + { + // This follows the specification of AbstractList, but is inconsistent + // with the one in List. Don't you love Sun's inconsistencies? + if (fromIndex > toIndex) + throw new IndexOutOfBoundsException(fromIndex + " > " + toIndex); + if (fromIndex < 0 || toIndex > size()) + throw new IndexOutOfBoundsException(); + + if (this instanceof RandomAccess) + return new RandomAccessSubList<E>(this, fromIndex, toIndex); + return new SubList<E>(this, fromIndex, toIndex); + } + + /** + * This class follows the implementation requirements set forth in + * {@link AbstractList#subList(int, int)}. It matches Sun's implementation + * by using a non-public top-level class in the same package. + * + * @author Original author unknown + * @author Eric Blake (ebb9@email.byu.edu) + */ + private static class SubList<E> + extends AbstractList<E> + { + // Package visible, for use by iterator. + /** The original list. */ + final CopyOnWriteArrayList<E> backingList; + /** The index of the first element of the sublist. */ + final int offset; + /** The size of the sublist. */ + int size; + /** The backing data */ + E[] data; + + /** + * Construct the sublist. + * + * @param backing the list this comes from + * @param fromIndex the lower bound, inclusive + * @param toIndex the upper bound, exclusive + */ + SubList(CopyOnWriteArrayList<E> backing, int fromIndex, int toIndex) + { + backingList = backing; + data = backing.data; + offset = fromIndex; + size = toIndex - fromIndex; + } + + /** + * This method checks the two modCount fields to ensure that there has + * not been a concurrent modification, returning if all is okay. + * + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + */ + // This can be inlined. Package visible, for use by iterator. + void checkMod() + { + if (data != backingList.data) + throw new ConcurrentModificationException(); + } + + /** + * This method checks that a value is between 0 and size (inclusive). If + * it is not, an exception is thrown. + * + * @param index the value to check + * @throws IndexOutOfBoundsException if index < 0 || index > size() + */ + // This will get inlined, since it is private. + private void checkBoundsInclusive(int index) + { + if (index < 0 || index > size) + throw new IndexOutOfBoundsException("Index: " + index + + ", Size:" + size); + } + + /** + * This method checks that a value is between 0 (inclusive) and size + * (exclusive). If it is not, an exception is thrown. + * + * @param index the value to check + * @throws IndexOutOfBoundsException if index < 0 || index >= size() + */ + // This will get inlined, since it is private. + private void checkBoundsExclusive(int index) + { + if (index < 0 || index >= size) + throw new IndexOutOfBoundsException("Index: " + index + + ", Size:" + size); + } + + /** + * Specified by AbstractList.subList to return the private field size. + * + * @return the sublist size + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + */ + public int size() + { + synchronized (backingList) + { + checkMod(); + return size; + } + } + + public void clear() + { + synchronized (backingList) + { + E[] snapshot = backingList.data; + E[] newData = (E[]) new Object[snapshot.length - size]; + + int toIndex = size + offset; + + System.arraycopy(snapshot, 0, newData, 0, offset); + System.arraycopy(snapshot, toIndex, newData, offset, + snapshot.length - toIndex); + + backingList.data = newData; + this.data = backingList.data; + this.size = 0; + } + } + + /** + * Specified by AbstractList.subList to delegate to the backing list. + * + * @param index the location to modify + * @param o the new value + * @return the old value + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + * @throws UnsupportedOperationException if the backing list does not + * support the set operation + * @throws IndexOutOfBoundsException if index < 0 || index >= size() + * @throws ClassCastException if o cannot be added to the backing list due + * to its type + * @throws IllegalArgumentException if o cannot be added to the backing list + * for some other reason + */ + public E set(int index, E o) + { + synchronized (backingList) + { + checkMod(); + checkBoundsExclusive(index); + + E el = backingList.set(index + offset, o); + this.data = backingList.data; + + return el; + } + } + + /** + * Specified by AbstractList.subList to delegate to the backing list. + * + * @param index the location to get from + * @return the object at that location + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + * @throws IndexOutOfBoundsException if index < 0 || index >= size() + */ + public E get(int index) + { + synchronized (backingList) + { + checkMod(); + checkBoundsExclusive(index); + + return backingList.get(index + offset); + } + } + + /** + * Specified by AbstractList.subList to delegate to the backing list. + * + * @param index the index to insert at + * @param o the object to add + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + * @throws IndexOutOfBoundsException if index < 0 || index > size() + * @throws UnsupportedOperationException if the backing list does not + * support the add operation. + * @throws ClassCastException if o cannot be added to the backing list due + * to its type. + * @throws IllegalArgumentException if o cannot be added to the backing + * list for some other reason. + */ + public void add(int index, E o) + { + synchronized (backingList) + { + checkMod(); + checkBoundsInclusive(index); + + backingList.add(index + offset, o); + + this.data = backingList.data; + size++; + } + } + + /** + * Specified by AbstractList.subList to delegate to the backing list. + * + * @param index the index to remove + * @return the removed object + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + * @throws IndexOutOfBoundsException if index < 0 || index >= size() + * @throws UnsupportedOperationException if the backing list does not + * support the remove operation + */ + public E remove(int index) + { + synchronized (backingList) + { + checkMod(); + checkBoundsExclusive(index); + E o = backingList.remove(index + offset); + + this.data = backingList.data; + size--; + + return o; + } + } + + /** + * Specified by AbstractList.subList to delegate to the backing list. + * + * @param index the location to insert at + * @param c the collection to insert + * @return true if this list was modified, in other words, c is non-empty + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + * @throws IndexOutOfBoundsException if index < 0 || index > size() + * @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 + */ + public boolean addAll(int index, Collection<? extends E> c) + { + synchronized (backingList) + { + checkMod(); + checkBoundsInclusive(index); + int csize = c.size(); + boolean result = backingList.addAll(offset + index, c); + + this.data = backingList.data; + size += csize; + + return result; + } + } + + /** + * Specified by AbstractList.subList to return addAll(size, c). + * + * @param c the collection to insert + * @return true if this list was modified, in other words, c is non-empty + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + * @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 + */ + public boolean addAll(Collection<? extends E> c) + { + synchronized (backingList) + { + return addAll(size, c); + } + } + + /** + * Specified by AbstractList.subList to return listIterator(). + * + * @return an iterator over the sublist + */ + public Iterator<E> iterator() + { + return listIterator(); + } + + /** + * Specified by AbstractList.subList to return a wrapper around the + * backing list's iterator. + * + * @param index the start location of the iterator + * @return a list iterator over the sublist + * @throws ConcurrentModificationException if the backing list has been + * modified externally to this sublist + * @throws IndexOutOfBoundsException if the value is out of range + */ + public ListIterator<E> listIterator(final int index) + { + checkMod(); + checkBoundsInclusive(index); + + return new ListIterator<E>() + { + private final ListIterator<E> i = + backingList.listIterator(index + offset); + private int position = index; + + /** + * Tests to see if there are any more objects to + * return. + * + * @return True if the end of the list has not yet been + * reached. + */ + public boolean hasNext() + { + return position < size; + } + + /** + * Tests to see if there are objects prior to the + * current position in the list. + * + * @return True if objects exist prior to the current + * position of the iterator. + */ + public boolean hasPrevious() + { + return position > 0; + } + + /** + * Retrieves the next object from the list. + * + * @return The next object. + * @throws NoSuchElementException if there are no + * more objects to retrieve. + * @throws ConcurrentModificationException if the + * list has been modified elsewhere. + */ + public E next() + { + if (position == size) + throw new NoSuchElementException(); + position++; + return i.next(); + } + + /** + * Retrieves the previous object from the list. + * + * @return The next object. + * @throws NoSuchElementException if there are no + * previous objects to retrieve. + * @throws ConcurrentModificationException if the + * list has been modified elsewhere. + */ + public E previous() + { + if (position == 0) + throw new NoSuchElementException(); + position--; + return i.previous(); + } + + /** + * Returns the index of the next element in the + * list, which will be retrieved by <code>next()</code> + * + * @return The index of the next element. + */ + public int nextIndex() + { + return i.nextIndex() - offset; + } + + /** + * Returns the index of the previous element in the + * list, which will be retrieved by <code>previous()</code> + * + * @return The index of the previous element. + */ + public int previousIndex() + { + return i.previousIndex() - offset; + } + + /** + * Removes the last object retrieved by <code>next()</code> + * from the list, if the list supports object removal. + * + * @throws IllegalStateException if the iterator is positioned + * before the start of the list or the last object has already + * been removed. + * @throws UnsupportedOperationException if the list does + * not support removing elements. + */ + public void remove() + { + throw new UnsupportedOperationException("Modification not supported " + + "on CopyOnWriteArrayList iterators"); + } + + /** + * Replaces the last object retrieved by <code>next()</code> + * or <code>previous</code> with o, if the list supports object + * replacement and an add or remove operation has not already + * been performed. + * + * @throws IllegalStateException if the iterator is positioned + * before the start of the list or the last object has already + * been removed. + * @throws UnsupportedOperationException if the list doesn't support + * the addition or removal of elements. + * @throws ClassCastException if the type of o is not a valid type + * for this list. + * @throws IllegalArgumentException if something else related to o + * prevents its addition. + * @throws ConcurrentModificationException if the list + * has been modified elsewhere. + */ + public void set(E o) + { + throw new UnsupportedOperationException("Modification not supported " + + "on CopyOnWriteArrayList iterators"); + } + + /** + * Adds the supplied object before the element that would be returned + * by a call to <code>next()</code>, if the list supports addition. + * + * @param o The object to add to the list. + * @throws UnsupportedOperationException if the list doesn't support + * the addition of new elements. + * @throws ClassCastException if the type of o is not a valid type + * for this list. + * @throws IllegalArgumentException if something else related to o + * prevents its addition. + * @throws ConcurrentModificationException if the list + * has been modified elsewhere. + */ + public void add(E o) + { + throw new UnsupportedOperationException("Modification not supported " + + "on CopyOnWriteArrayList iterators"); + } + }; + } + } // class SubList + + /** + * This class is a RandomAccess version of SubList, as required by + * {@link AbstractList#subList(int, int)}. + * + * @author Eric Blake (ebb9@email.byu.edu) + */ + private static final class RandomAccessSubList<E> extends SubList<E> + implements RandomAccess + { + /** + * Construct the sublist. + * + * @param backing the list this comes from + * @param fromIndex the lower bound, inclusive + * @param toIndex the upper bound, exclusive + */ + RandomAccessSubList(CopyOnWriteArrayList<E> backing, int fromIndex, int toIndex) + { + super(backing, fromIndex, toIndex); + } + } // class RandomAccessSubList /** * Serializes this object to the given stream. diff --git a/libjava/classpath/java/util/jar/Manifest.java b/libjava/classpath/java/util/jar/Manifest.java index 8effc2878ce..980cfc60baf 100644 --- a/libjava/classpath/java/util/jar/Manifest.java +++ b/libjava/classpath/java/util/jar/Manifest.java @@ -138,7 +138,7 @@ public class Manifest implements Cloneable */ public Attributes getAttributes(String entryName) { - return (Attributes) getEntries().get(entryName); + return getEntries().get(entryName); } /** diff --git a/libjava/classpath/java/util/logging/Logger.java b/libjava/classpath/java/util/logging/Logger.java index 01ef8f522b8..f7157c17698 100644 --- a/libjava/classpath/java/util/logging/Logger.java +++ b/libjava/classpath/java/util/logging/Logger.java @@ -45,110 +45,105 @@ import java.security.AccessController; import java.security.PrivilegedAction; /** - * A Logger is used for logging information about events. Usually, there - * is a seprate logger for each subsystem or component, although there - * is a shared instance for components that make only occasional use of - * the logging framework. - * - * <p>It is common to name a logger after the name of a corresponding - * Java package. Loggers are organized into a hierarchical namespace; - * for example, the logger <code>"org.gnu.foo"</code> is the - * <em>parent</em> of logger <code>"org.gnu.foo.bar"</code>. - * - * <p>A logger for a named subsystem can be obtained through {@link - * java.util.logging.Logger#getLogger(java.lang.String)}. However, - * only code which has been granted the permission to control the - * logging infrastructure will be allowed to customize that logger. - * Untrusted code can obtain a private, anonymous logger through - * {@link #getAnonymousLogger()} if it wants to perform any - * modifications to the logger. - * - * <p>FIXME: Write more documentation. - * + * A Logger is used for logging information about events. Usually, there is a + * seprate logger for each subsystem or component, although there is a shared + * instance for components that make only occasional use of the logging + * framework. + * <p> + * It is common to name a logger after the name of a corresponding Java package. + * Loggers are organized into a hierarchical namespace; for example, the logger + * <code>"org.gnu.foo"</code> is the <em>parent</em> of logger + * <code>"org.gnu.foo.bar"</code>. + * <p> + * A logger for a named subsystem can be obtained through {@link + * java.util.logging.Logger#getLogger(java.lang.String)}. However, only code + * which has been granted the permission to control the logging infrastructure + * will be allowed to customize that logger. Untrusted code can obtain a + * private, anonymous logger through {@link #getAnonymousLogger()} if it wants + * to perform any modifications to the logger. + * <p> + * FIXME: Write more documentation. + * * @author Sascha Brawer (brawer@acm.org) */ public class Logger { - static final Logger root = new Logger("", null); /** - * A logger provided to applications that make only occasional use - * of the logging framework, typically early prototypes. Serious - * products are supposed to create and use their own Loggers, so - * they can be controlled individually. + * A logger provided to applications that make only occasional use of the + * logging framework, typically early prototypes. Serious products are + * supposed to create and use their own Loggers, so they can be controlled + * individually. */ public static final Logger global; + /** + * Use to lock methods on this class instead of calling synchronize on methods + * to avoid deadlocks. Yeah, no kidding, we got them :) + */ + private static final Object[] lock = new Object[0]; + static { // Our class might be initialized from an unprivileged context - global = (Logger) AccessController.doPrivileged - (new PrivilegedAction() - { - public Object run() - { - return getLogger("global"); - } - }); + global = (Logger) AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + return getLogger("global"); + } + }); } - /** - * The name of the Logger, or <code>null</code> if the logger is - * anonymous. - * - * <p>A previous version of the GNU Classpath implementation granted - * untrusted code the permission to control any logger whose name - * was null. However, test code revealed that the Sun J2SE 1.4 - * reference implementation enforces the security control for any - * logger that was not created through getAnonymousLogger, even if - * it has a null name. Therefore, a separate flag {@link - * Logger#anonymous} was introduced. + * The name of the Logger, or <code>null</code> if the logger is anonymous. + * <p> + * A previous version of the GNU Classpath implementation granted untrusted + * code the permission to control any logger whose name was null. However, + * test code revealed that the Sun J2SE 1.4 reference implementation enforces + * the security control for any logger that was not created through + * getAnonymousLogger, even if it has a null name. Therefore, a separate flag + * {@link Logger#anonymous} was introduced. */ private final String name; - /** * The name of the resource bundle used for localization. - * - * <p>This variable cannot be declared as <code>final</code> - * because its value can change as a result of calling - * getLogger(String,String). + * <p> + * This variable cannot be declared as <code>final</code> because its value + * can change as a result of calling getLogger(String,String). */ private String resourceBundleName; - /** * The resource bundle used for localization. - * - * <p>This variable cannot be declared as <code>final</code> - * because its value can change as a result of calling - * getLogger(String,String). + * <p> + * This variable cannot be declared as <code>final</code> because its value + * can change as a result of calling getLogger(String,String). */ private ResourceBundle resourceBundle; private Filter filter; private final List handlerList = new java.util.ArrayList(4); + private Handler[] handlers = new Handler[0]; /** - * Indicates whether or not this logger is anonymous. While - * a LoggingPermission is required for any modifications to - * a normal logger, untrusted code can obtain an anonymous logger - * and modify it according to its needs. - * - * <p>A previous version of the GNU Classpath implementation - * granted access to every logger whose name was null. - * However, test code revealed that the Sun J2SE 1.4 reference - * implementation enforces the security control for any logger - * that was not created through getAnonymousLogger, even - * if it has a null name. + * Indicates whether or not this logger is anonymous. While a + * LoggingPermission is required for any modifications to a normal logger, + * untrusted code can obtain an anonymous logger and modify it according to + * its needs. + * <p> + * A previous version of the GNU Classpath implementation granted access to + * every logger whose name was null. However, test code revealed that the Sun + * J2SE 1.4 reference implementation enforces the security control for any + * logger that was not created through getAnonymousLogger, even if it has a + * null name. */ private boolean anonymous; - private boolean useParentHandlers; private Level level; @@ -156,29 +151,26 @@ public class Logger private Logger parent; /** - * Constructs a Logger for a subsystem. Most applications do not - * need to create new Loggers explicitly; instead, they should call - * the static factory methods - * {@link #getLogger(java.lang.String,java.lang.String) getLogger} + * Constructs a Logger for a subsystem. Most applications do not need to + * create new Loggers explicitly; instead, they should call the static factory + * methods {@link #getLogger(java.lang.String,java.lang.String) getLogger} * (with ResourceBundle for localization) or - * {@link #getLogger(java.lang.String) getLogger} (without - * ResourceBundle), respectively. - * - * @param name the name for the logger, for example "java.awt" - * or "com.foo.bar". The name should be based on - * the name of the package issuing log records - * and consist of dot-separated Java identifiers. - * - * @param resourceBundleName the name of a resource bundle - * for localizing messages, or <code>null</code> - * to indicate that messages do not need to be localized. - * + * {@link #getLogger(java.lang.String) getLogger} (without ResourceBundle), + * respectively. + * + * @param name the name for the logger, for example "java.awt" or + * "com.foo.bar". The name should be based on the name of the + * package issuing log records and consist of dot-separated Java + * identifiers. + * @param resourceBundleName the name of a resource bundle for localizing + * messages, or <code>null</code> to indicate that messages do + * not need to be localized. * @throws java.util.MissingResourceException if - * <code>resourceBundleName</code> is not <code>null</code> - * and no such bundle could be located. + * <code>resourceBundleName</code> is not <code>null</code> + * and no such bundle could be located. */ protected Logger(String name, String resourceBundleName) - throws MissingResourceException + throws MissingResourceException { this.name = name; this.resourceBundleName = resourceBundleName; @@ -190,1002 +182,978 @@ public class Logger level = null; - /* This is null when the root logger is being constructed, - * and the root logger afterwards. + /* + * This is null when the root logger is being constructed, and the root + * logger afterwards. */ parent = root; useParentHandlers = (parent != null); } - - /** - * Finds a registered logger for a subsystem, or creates one in - * case no logger has been registered yet. - * - * @param name the name for the logger, for example "java.awt" - * or "com.foo.bar". The name should be based on - * the name of the package issuing log records - * and consist of dot-separated Java identifiers. - * - * @throws IllegalArgumentException if a logger for the subsystem - * identified by <code>name</code> has already been created, - * but uses a a resource bundle for localizing messages. - * - * @throws NullPointerException if <code>name</code> is - * <code>null</code>. - * - * @return a logger for the subsystem specified by <code>name</code> - * that does not localize messages. + * Finds a registered logger for a subsystem, or creates one in case no logger + * has been registered yet. + * + * @param name the name for the logger, for example "java.awt" or + * "com.foo.bar". The name should be based on the name of the + * package issuing log records and consist of dot-separated Java + * identifiers. + * @throws IllegalArgumentException if a logger for the subsystem identified + * by <code>name</code> has already been created, but uses a a + * resource bundle for localizing messages. + * @throws NullPointerException if <code>name</code> is <code>null</code>. + * @return a logger for the subsystem specified by <code>name</code> that + * does not localize messages. */ public static Logger getLogger(String name) { return getLogger(name, null); } - /** - * Finds a registered logger for a subsystem, or creates one in case - * no logger has been registered yet. - * - * <p>If a logger with the specified name has already been - * registered, the behavior depends on the resource bundle that is - * currently associated with the existing logger. - * - * <ul><li>If the existing logger uses the same resource bundle as - * specified by <code>resourceBundleName</code>, the existing logger - * is returned.</li> - * - * <li>If the existing logger currently does not localize messages, - * the existing logger is modified to use the bundle specified by - * <code>resourceBundleName</code>. The existing logger is then - * returned. Therefore, all subsystems currently using this logger - * will produce localized messages from now on.</li> - * - * <li>If the existing logger already has an associated resource - * bundle, but a different one than specified by - * <code>resourceBundleName</code>, an - * <code>IllegalArgumentException</code> is thrown.</li></ul> - * - * @param name the name for the logger, for example "java.awt" - * or "org.gnu.foo". The name should be based on - * the name of the package issuing log records - * and consist of dot-separated Java identifiers. - * - * @param resourceBundleName the name of a resource bundle - * for localizing messages, or <code>null</code> - * to indicate that messages do not need to be localized. - * + * Finds a registered logger for a subsystem, or creates one in case no logger + * has been registered yet. + * <p> + * If a logger with the specified name has already been registered, the + * behavior depends on the resource bundle that is currently associated with + * the existing logger. + * <ul> + * <li>If the existing logger uses the same resource bundle as specified by + * <code>resourceBundleName</code>, the existing logger is returned.</li> + * <li>If the existing logger currently does not localize messages, the + * existing logger is modified to use the bundle specified by + * <code>resourceBundleName</code>. The existing logger is then returned. + * Therefore, all subsystems currently using this logger will produce + * localized messages from now on.</li> + * <li>If the existing logger already has an associated resource bundle, but + * a different one than specified by <code>resourceBundleName</code>, an + * <code>IllegalArgumentException</code> is thrown.</li> + * </ul> + * + * @param name the name for the logger, for example "java.awt" or + * "org.gnu.foo". The name should be based on the name of the + * package issuing log records and consist of dot-separated Java + * identifiers. + * @param resourceBundleName the name of a resource bundle for localizing + * messages, or <code>null</code> to indicate that messages do + * not need to be localized. * @return a logger for the subsystem specified by <code>name</code>. - * * @throws java.util.MissingResourceException if - * <code>resourceBundleName</code> is not <code>null</code> - * and no such bundle could be located. - * - * @throws IllegalArgumentException if a logger for the subsystem - * identified by <code>name</code> has already been created, - * but uses a different resource bundle for localizing - * messages. - * - * @throws NullPointerException if <code>name</code> is - * <code>null</code>. + * <code>resourceBundleName</code> is not <code>null</code> + * and no such bundle could be located. + * @throws IllegalArgumentException if a logger for the subsystem identified + * by <code>name</code> has already been created, but uses a + * different resource bundle for localizing messages. + * @throws NullPointerException if <code>name</code> is <code>null</code>. */ public static Logger getLogger(String name, String resourceBundleName) { LogManager lm = LogManager.getLogManager(); - Logger result; + Logger result; if (name == null) throw new NullPointerException(); - /* Without synchronized(lm), it could happen that another thread - * would create a logger between our calls to getLogger and - * addLogger. While addLogger would indicate this by returning - * false, we could not be sure that this other logger was still - * existing when we called getLogger a second time in order - * to retrieve it -- note that LogManager is only allowed to - * keep weak references to registered loggers, so Loggers - * can be garbage collected at any time in general, and between - * our call to addLogger and our second call go getLogger - * in particular. - * - * Of course, we assume here that LogManager.addLogger etc. - * are synchronizing on the global LogManager object. There - * is a comment in the implementation of LogManager.addLogger - * referring to this comment here, so that any change in - * the synchronization of LogManager will be reflected here. + /* + * Without synchronized(lm), it could happen that another thread would + * create a logger between our calls to getLogger and addLogger. While + * addLogger would indicate this by returning false, we could not be sure + * that this other logger was still existing when we called getLogger a + * second time in order to retrieve it -- note that LogManager is only + * allowed to keep weak references to registered loggers, so Loggers can be + * garbage collected at any time in general, and between our call to + * addLogger and our second call go getLogger in particular. Of course, we + * assume here that LogManager.addLogger etc. are synchronizing on the + * global LogManager object. There is a comment in the implementation of + * LogManager.addLogger referring to this comment here, so that any change + * in the synchronization of LogManager will be reflected here. */ - synchronized (lm) - { - result = lm.getLogger(name); - if (result == null) - { - boolean couldBeAdded; - - result = new Logger(name, resourceBundleName); - couldBeAdded = lm.addLogger(result); - if (!couldBeAdded) - throw new IllegalStateException("cannot register new logger"); - } - else + synchronized (lock) { - /* The logger already exists. Make sure it uses - * the same resource bundle for localizing messages. - */ - String existingBundleName = result.getResourceBundleName(); - - /* The Sun J2SE 1.4 reference implementation will return the - * registered logger object, even if it does not have a resource - * bundle associated with it. However, it seems to change the - * resourceBundle of the registered logger to the bundle - * whose name was passed to getLogger. - */ - if ((existingBundleName == null) && (resourceBundleName != null)) - { - /* If ResourceBundle.getBundle throws an exception, the - * existing logger will be unchanged. This would be - * different if the assignment to resourceBundleName - * came first. - */ - result.resourceBundle = ResourceBundle.getBundle(resourceBundleName); - result.resourceBundleName = resourceBundleName; - return result; - } - - if ((existingBundleName != resourceBundleName) - && ((existingBundleName == null) - || !existingBundleName.equals(resourceBundleName))) - { - throw new IllegalArgumentException(); - } + synchronized (lm) + { + result = lm.getLogger(name); + if (result == null) + { + boolean couldBeAdded; + + result = new Logger(name, resourceBundleName); + couldBeAdded = lm.addLogger(result); + if (! couldBeAdded) + throw new IllegalStateException("cannot register new logger"); + } + else + { + /* + * The logger already exists. Make sure it uses the same + * resource bundle for localizing messages. + */ + String existingBundleName = result.getResourceBundleName(); + + /* + * The Sun J2SE 1.4 reference implementation will return the + * registered logger object, even if it does not have a resource + * bundle associated with it. However, it seems to change the + * resourceBundle of the registered logger to the bundle whose + * name was passed to getLogger. + */ + if ((existingBundleName == null) && + (resourceBundleName != null)) + { + /* + * If ResourceBundle.getBundle throws an exception, the + * existing logger will be unchanged. This would be + * different if the assignment to resourceBundleName came + * first. + */ + result.resourceBundle = + ResourceBundle.getBundle(resourceBundleName); + + result.resourceBundleName = resourceBundleName; + return result; + } + + if ((existingBundleName != resourceBundleName) + && ((existingBundleName == null) + || !existingBundleName.equals(resourceBundleName))) + { + throw new IllegalArgumentException(); + } + } + } } - } return result; } - /** - * Creates a new, unnamed logger. Unnamed loggers are not - * registered in the namespace of the LogManager, and no special - * security permission is required for changing their state. - * Therefore, untrusted applets are able to modify their private - * logger instance obtained through this method. - * - * <p>The parent of the newly created logger will the the root - * logger, from which the level threshold and the handlers are - * inherited. + * Creates a new, unnamed logger. Unnamed loggers are not registered in the + * namespace of the LogManager, and no special security permission is required + * for changing their state. Therefore, untrusted applets are able to modify + * their private logger instance obtained through this method. + * <p> + * The parent of the newly created logger will the the root logger, from which + * the level threshold and the handlers are inherited. */ public static Logger getAnonymousLogger() { return getAnonymousLogger(null); } - /** - * Creates a new, unnamed logger. Unnamed loggers are not - * registered in the namespace of the LogManager, and no special - * security permission is required for changing their state. - * Therefore, untrusted applets are able to modify their private - * logger instance obtained through this method. - * - * <p>The parent of the newly created logger will the the root - * logger, from which the level threshold and the handlers are - * inherited. - * - * @param resourceBundleName the name of a resource bundle - * for localizing messages, or <code>null</code> - * to indicate that messages do not need to be localized. - * + * Creates a new, unnamed logger. Unnamed loggers are not registered in the + * namespace of the LogManager, and no special security permission is required + * for changing their state. Therefore, untrusted applets are able to modify + * their private logger instance obtained through this method. + * <p> + * The parent of the newly created logger will the the root logger, from which + * the level threshold and the handlers are inherited. + * + * @param resourceBundleName the name of a resource bundle for localizing + * messages, or <code>null</code> to indicate that messages do + * not need to be localized. * @throws java.util.MissingResourceException if - * <code>resourceBundleName</code> is not <code>null</code> - * and no such bundle could be located. + * <code>resourceBundleName</code> is not <code>null</code> + * and no such bundle could be located. */ public static Logger getAnonymousLogger(String resourceBundleName) - throws MissingResourceException + throws MissingResourceException { - Logger result; + Logger result; result = new Logger(null, resourceBundleName); result.anonymous = true; return result; } - /** - * Returns the name of the resource bundle that is being used for - * localizing messages. - * - * @return the name of the resource bundle used for localizing messages, - * or <code>null</code> if the parent's resource bundle - * is used for this purpose. + * Returns the name of the resource bundle that is being used for localizing + * messages. + * + * @return the name of the resource bundle used for localizing messages, or + * <code>null</code> if the parent's resource bundle is used for + * this purpose. */ - public synchronized String getResourceBundleName() + public String getResourceBundleName() { - return resourceBundleName; + synchronized (lock) + { + return resourceBundleName; + } } - /** - * Returns the resource bundle that is being used for localizing - * messages. - * - * @return the resource bundle used for localizing messages, - * or <code>null</code> if the parent's resource bundle - * is used for this purpose. + * Returns the resource bundle that is being used for localizing messages. + * + * @return the resource bundle used for localizing messages, or + * <code>null</code> if the parent's resource bundle is used for + * this purpose. */ - public synchronized ResourceBundle getResourceBundle() + public ResourceBundle getResourceBundle() { - return resourceBundle; + synchronized (lock) + { + return resourceBundle; + } } - /** - * 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, or <code>null</code> if the logger inherits - * the threshold from its parent. + * 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, + * or <code>null</code> if the logger inherits the threshold from + * its parent. */ - public synchronized Level getLevel() + public Level getLevel() { - return level; + synchronized (lock) + { + return level; + } } - /** - * Returns whether or not a message of the specified level - * would be logged by this logger. - * - * @throws NullPointerException if <code>level</code> - * is <code>null</code>. + * Returns whether or not a message of the specified level would be logged by + * this logger. + * + * @throws NullPointerException if <code>level</code> is <code>null</code>. */ - public synchronized boolean isLoggable(Level level) + public boolean isLoggable(Level level) { - if (this.level != null) - return this.level.intValue() <= level.intValue(); + synchronized (lock) + { + if (this.level != null) + return this.level.intValue() <= level.intValue(); - if (parent != null) - return parent.isLoggable(level); - else - return false; + if (parent != null) + return parent.isLoggable(level); + else + return false; + } } - /** - * Sets the severity level threshold for this <code>Handler</code>. - * All log records with a lower severity level will be discarded - * immediately. 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, or <code>null</code> to - * indicate that the logger should inherit the - * threshold from its parent. - * - * @throws SecurityException if this logger is not anonymous, a - * security manager exists, and the caller is not granted - * the permission to control the logging infrastructure by - * having LoggingPermission("control"). Untrusted code can - * obtain an anonymous logger through the static factory method - * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. + * Sets the severity level threshold for this <code>Handler</code>. All log + * records with a lower severity level will be discarded immediately. 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, or <code>null</code> to indicate that the logger + * should inherit the threshold from its parent. + * @throws SecurityException if this logger is not anonymous, a security + * manager exists, and the caller is not granted the permission to + * control the logging infrastructure by having + * LoggingPermission("control"). Untrusted code can obtain an + * anonymous logger through the static factory method + * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. */ - public synchronized void setLevel(Level level) + public void setLevel(Level level) { - /* An application is allowed to control an anonymous logger - * without having the permission to control the logging - * infrastructure. - */ - if (!anonymous) - LogManager.getLogManager().checkAccess(); - - this.level = level; + synchronized (lock) + { + /* + * An application is allowed to control an anonymous logger without + * having the permission to control the logging infrastructure. + */ + if (! anonymous) + LogManager.getLogManager().checkAccess(); + + this.level = level; + } } - - public synchronized Filter getFilter() + public Filter getFilter() { - return filter; + synchronized (lock) + { + return filter; + } } - /** - * @throws SecurityException if this logger is not anonymous, a - * security manager exists, and the caller is not granted - * the permission to control the logging infrastructure by - * having LoggingPermission("control"). Untrusted code can - * obtain an anonymous logger through the static factory method - * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. + * @throws SecurityException if this logger is not anonymous, a security + * manager exists, and the caller is not granted the permission to + * control the logging infrastructure by having + * LoggingPermission("control"). Untrusted code can obtain an + * anonymous logger through the static factory method + * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. */ - public synchronized void setFilter(Filter filter) - throws SecurityException + public void setFilter(Filter filter) throws SecurityException { - /* An application is allowed to control an anonymous logger - * without having the permission to control the logging - * infrastructure. - */ - if (!anonymous) - LogManager.getLogManager().checkAccess(); - - this.filter = filter; + synchronized (lock) + { + /* + * An application is allowed to control an anonymous logger without + * having the permission to control the logging infrastructure. + */ + if (! anonymous) + LogManager.getLogManager().checkAccess(); + + this.filter = filter; + } } - - - /** * Returns the name of this logger. - * - * @return the name of this logger, or <code>null</code> if - * the logger is anonymous. + * + * @return the name of this logger, or <code>null</code> if the logger is + * anonymous. */ public String getName() { - /* Note that the name of a logger cannot be changed during - * its lifetime, so no synchronization is needed. + /* + * Note that the name of a logger cannot be changed during its lifetime, so + * no synchronization is needed. */ return name; } - /** - * Passes a record to registered handlers, provided the record - * is considered as loggable both by {@link #isLoggable(Level)} - * and a possibly installed custom {@link #setFilter(Filter) filter}. - * - * <p>If the logger has been configured to use parent handlers, - * the record will be forwarded to the parent of this logger - * in addition to being processed by the handlers registered with - * this logger. - * - * <p>The other logging methods in this class are convenience methods - * that merely create a new LogRecord and pass it to this method. - * Therefore, subclasses usually just need to override this single - * method for customizing the logging behavior. - * + * Passes a record to registered handlers, provided the record is considered + * as loggable both by {@link #isLoggable(Level)} and a possibly installed + * custom {@link #setFilter(Filter) filter}. + * <p> + * If the logger has been configured to use parent handlers, the record will + * be forwarded to the parent of this logger in addition to being processed by + * the handlers registered with this logger. + * <p> + * The other logging methods in this class are convenience methods that merely + * create a new LogRecord and pass it to this method. Therefore, subclasses + * usually just need to override this single method for customizing the + * logging behavior. + * * @param record the log record to be inspected and possibly forwarded. */ - public synchronized void log(LogRecord record) + public void log(LogRecord record) { - if (!isLoggable(record.getLevel())) - return; - - if ((filter != null) && !filter.isLoggable(record)) - return; - - /* If no logger name has been set for the log record, - * use the name of this logger. - */ - if (record.getLoggerName() == null) - record.setLoggerName(name); - - /* Avoid that some other thread is changing the logger hierarchy - * while we are traversing it. - */ - synchronized (LogManager.getLogManager()) - { - Logger curLogger = this; - - do + synchronized (lock) { - /* The Sun J2SE 1.4 reference implementation seems to call the - * filter only for the logger whose log method is called, - * never for any of its parents. Also, parent loggers publish - * log record whatever their level might be. This is pretty - * weird, but GNU Classpath tries to be as compatible as - * possible to the reference implementation. - */ - for (int i = 0; i < curLogger.handlers.length; i++) - curLogger.handlers[i].publish(record); - - if (curLogger.getUseParentHandlers() == false) - break; - - curLogger = curLogger.getParent(); + if (!isLoggable(record.getLevel())) + return; + + if ((filter != null) && ! filter.isLoggable(record)) + return; + + /* + * If no logger name has been set for the log record, use the name of + * this logger. + */ + if (record.getLoggerName() == null) + record.setLoggerName(name); + + /* + * Avoid that some other thread is changing the logger hierarchy while + * we are traversing it. + */ + synchronized (LogManager.getLogManager()) + { + Logger curLogger = this; + + do + { + /* + * The Sun J2SE 1.4 reference implementation seems to call the + * filter only for the logger whose log method is called, never + * for any of its parents. Also, parent loggers publish log + * record whatever their level might be. This is pretty weird, + * but GNU Classpath tries to be as compatible as possible to + * the reference implementation. + */ + for (int i = 0; i < curLogger.handlers.length; i++) + curLogger.handlers[i].publish(record); + + if (curLogger.getUseParentHandlers() == false) + break; + + curLogger = curLogger.getParent(); + } + while (parent != null); + } } - while (parent != null); - } } - public void log(Level level, String message) { if (isLoggable(level)) log(level, message, (Object[]) null); } - - public synchronized void log(Level level, - String message, - Object param) + public void log(Level level, String message, Object param) { - if (isLoggable(level)) + synchronized (lock) { - StackTraceElement caller = getCallerStackFrame(); - logp(level, - caller != null ? caller.getClassName() : "<unknown>", - caller != null ? caller.getMethodName() : "<unknown>", - message, - param); + if (isLoggable(level)) + { + StackTraceElement caller = getCallerStackFrame(); + logp(level, caller != null ? caller.getClassName() : "<unknown>", + caller != null ? caller.getMethodName() : "<unknown>", + message, param); + } } } - - public synchronized void log(Level level, - String message, - Object[] params) + public void log(Level level, String message, Object[] params) { - if (isLoggable(level)) + synchronized (lock) { - StackTraceElement caller = getCallerStackFrame(); - logp(level, - caller != null ? caller.getClassName() : "<unknown>", - caller != null ? caller.getMethodName() : "<unknown>", - message, - params); + if (isLoggable(level)) + { + StackTraceElement caller = getCallerStackFrame(); + logp(level, caller != null ? caller.getClassName() : "<unknown>", + caller != null ? caller.getMethodName() : "<unknown>", + message, params); + + } } } - - public synchronized void log(Level level, - String message, - Throwable thrown) + public void log(Level level, String message, Throwable thrown) { - if (isLoggable(level)) + synchronized (lock) { - StackTraceElement caller = getCallerStackFrame(); - logp(level, - caller != null ? caller.getClassName() : "<unknown>", - caller != null ? caller.getMethodName() : "<unknown>", - message, - thrown); + if (isLoggable(level)) + { + StackTraceElement caller = getCallerStackFrame(); + logp(level, caller != null ? caller.getClassName() : "<unknown>", + caller != null ? caller.getMethodName() : "<unknown>", + message, thrown); + } } } - - public synchronized void logp(Level level, - String sourceClass, - String sourceMethod, - String message) + public void logp(Level level, String sourceClass, String sourceMethod, + String message) { - logp(level, sourceClass, sourceMethod, message, - (Object[]) null); + synchronized (lock) + { + logp(level, sourceClass, sourceMethod, message, (Object[]) null); + } } - - public synchronized void logp(Level level, - String sourceClass, - String sourceMethod, - String message, - Object param) + public void logp(Level level, String sourceClass, String sourceMethod, + String message, Object param) { - logp(level, sourceClass, sourceMethod, message, - new Object[] { param }); - } + synchronized (lock) + { + logp(level, sourceClass, sourceMethod, message, new Object[] { param }); + } + } - private synchronized ResourceBundle findResourceBundle() + private ResourceBundle findResourceBundle() { - if (resourceBundle != null) - return resourceBundle; + synchronized (lock) + { + if (resourceBundle != null) + return resourceBundle; - if (parent != null) - return parent.findResourceBundle(); + if (parent != null) + return parent.findResourceBundle(); - return null; + return null; + } } - - private synchronized void logImpl(Level level, - String sourceClass, - String sourceMethod, - String message, - Object[] params) + private void logImpl(Level level, String sourceClass, String sourceMethod, + String message, Object[] params) { - LogRecord rec = new LogRecord(level, message); + synchronized (lock) + { + LogRecord rec = new LogRecord(level, message); - rec.setResourceBundle(findResourceBundle()); - rec.setSourceClassName(sourceClass); - rec.setSourceMethodName(sourceMethod); - rec.setParameters(params); + rec.setResourceBundle(findResourceBundle()); + rec.setSourceClassName(sourceClass); + rec.setSourceMethodName(sourceMethod); + rec.setParameters(params); - log(rec); + log(rec); + } } - - public synchronized void logp(Level level, - String sourceClass, - String sourceMethod, - String message, - Object[] params) + public void logp(Level level, String sourceClass, String sourceMethod, + String message, Object[] params) { - logImpl(level, sourceClass, sourceMethod, message, params); + synchronized (lock) + { + logImpl(level, sourceClass, sourceMethod, message, params); + } } - - public synchronized void logp(Level level, - String sourceClass, - String sourceMethod, - String message, - Throwable thrown) + public void logp(Level level, String sourceClass, String sourceMethod, + String message, Throwable thrown) { - LogRecord rec = new LogRecord(level, message); + synchronized (lock) + { + LogRecord rec = new LogRecord(level, message); - rec.setResourceBundle(resourceBundle); - rec.setSourceClassName(sourceClass); - rec.setSourceMethodName(sourceMethod); - rec.setThrown(thrown); + rec.setResourceBundle(resourceBundle); + rec.setSourceClassName(sourceClass); + rec.setSourceMethodName(sourceMethod); + rec.setThrown(thrown); - log(rec); + log(rec); + } } - - public synchronized void logrb(Level level, - String sourceClass, - String sourceMethod, - String bundleName, - String message) + public void logrb(Level level, String sourceClass, String sourceMethod, + String bundleName, String message) { - logrb(level, sourceClass, sourceMethod, bundleName, - message, (Object[]) null); + synchronized (lock) + { + logrb(level, sourceClass, sourceMethod, bundleName, message, + (Object[]) null); + } } - - public synchronized void logrb(Level level, - String sourceClass, - String sourceMethod, - String bundleName, - String message, - Object param) + public void logrb(Level level, String sourceClass, String sourceMethod, + String bundleName, String message, Object param) { - logrb(level, sourceClass, sourceMethod, bundleName, - message, new Object[] { param }); + synchronized (lock) + { + logrb(level, sourceClass, sourceMethod, bundleName, message, + new Object[] { param }); + } } - - public synchronized void logrb(Level level, - String sourceClass, - String sourceMethod, - String bundleName, - String message, - Object[] params) + public void logrb(Level level, String sourceClass, String sourceMethod, + String bundleName, String message, Object[] params) { - LogRecord rec = new LogRecord(level, message); + synchronized (lock) + { + LogRecord rec = new LogRecord(level, message); - rec.setResourceBundleName(bundleName); - rec.setSourceClassName(sourceClass); - rec.setSourceMethodName(sourceMethod); - rec.setParameters(params); + rec.setResourceBundleName(bundleName); + rec.setSourceClassName(sourceClass); + rec.setSourceMethodName(sourceMethod); + rec.setParameters(params); - log(rec); + log(rec); + } } - - public synchronized void logrb(Level level, - String sourceClass, - String sourceMethod, - String bundleName, - String message, - Throwable thrown) + public void logrb(Level level, String sourceClass, String sourceMethod, + String bundleName, String message, Throwable thrown) { - LogRecord rec = new LogRecord(level, message); + synchronized (lock) + { + LogRecord rec = new LogRecord(level, message); - rec.setResourceBundleName(bundleName); - rec.setSourceClassName(sourceClass); - rec.setSourceMethodName(sourceMethod); - rec.setThrown(thrown); + rec.setResourceBundleName(bundleName); + rec.setSourceClassName(sourceClass); + rec.setSourceMethodName(sourceMethod); + rec.setThrown(thrown); - log(rec); + log(rec); + } } - - public synchronized void entering(String sourceClass, - String sourceMethod) + public void entering(String sourceClass, String sourceMethod) { - if (isLoggable(Level.FINER)) - logp(Level.FINER, sourceClass, sourceMethod, "ENTRY"); + synchronized (lock) + { + if (isLoggable(Level.FINER)) + logp(Level.FINER, sourceClass, sourceMethod, "ENTRY"); + } } - - public synchronized void entering(String sourceClass, - String sourceMethod, - Object param) + public void entering(String sourceClass, String sourceMethod, Object param) { - if (isLoggable(Level.FINER)) - logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param); + synchronized (lock) + { + if (isLoggable(Level.FINER)) + logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param); + } } - - public synchronized void entering(String sourceClass, - String sourceMethod, - Object[] params) + public void entering(String sourceClass, String sourceMethod, Object[] params) { - if (isLoggable(Level.FINER)) - { - StringBuffer buf = new StringBuffer(80); - buf.append("ENTRY"); - for (int i = 0; i < params.length; i++) + synchronized (lock) { - buf.append(" {"); - buf.append(i); - buf.append('}'); + if (isLoggable(Level.FINER)) + { + StringBuffer buf = new StringBuffer(80); + buf.append("ENTRY"); + for (int i = 0; i < params.length; i++) + { + buf.append(" {"); + buf.append(i); + buf.append('}'); + } + + logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params); + } } - - logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params); - } } - - public synchronized void exiting(String sourceClass, - String sourceMethod) + public void exiting(String sourceClass, String sourceMethod) { - if (isLoggable(Level.FINER)) - logp(Level.FINER, sourceClass, sourceMethod, "RETURN"); + synchronized (lock) + { + if (isLoggable(Level.FINER)) + logp(Level.FINER, sourceClass, sourceMethod, "RETURN"); + } } - - public synchronized void exiting(String sourceClass, - String sourceMethod, - Object result) + public void exiting(String sourceClass, String sourceMethod, Object result) { - if (isLoggable(Level.FINER)) - logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result); + synchronized (lock) + { + if (isLoggable(Level.FINER)) + logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result); + } } - - public synchronized void throwing(String sourceClass, - String sourceMethod, - Throwable thrown) + public void throwing(String sourceClass, String sourceMethod, Throwable thrown) { - if (isLoggable(Level.FINER)) - logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown); + synchronized (lock) + { + if (isLoggable(Level.FINER)) + logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown); + } } - /** - * Logs a message with severity level SEVERE, indicating 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. - * + * Logs a message with severity level SEVERE, indicating 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. + * * @see Level#SEVERE - * - * @param message the message text, also used as look-up key if the - * logger is localizing messages with a resource - * bundle. While it is possible to pass - * <code>null</code>, this is not recommended, since - * a logging message without text is unlikely to be - * helpful. + * @param message the message text, also used as look-up key if the logger is + * localizing messages with a resource bundle. While it is possible + * to pass <code>null</code>, this is not recommended, since a + * logging message without text is unlikely to be helpful. */ - public synchronized void severe(String message) + public void severe(String message) { - if (isLoggable(Level.SEVERE)) - log(Level.SEVERE, message); + synchronized (lock) + { + if (isLoggable(Level.SEVERE)) + log(Level.SEVERE, message); + } } - /** - * Logs a message with severity level WARNING, indicating 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. - * + * Logs a message with severity level WARNING, indicating 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. + * * @see Level#WARNING - * - * @param message the message text, also used as look-up key if the - * logger is localizing messages with a resource - * bundle. While it is possible to pass - * <code>null</code>, this is not recommended, since - * a logging message without text is unlikely to be - * helpful. + * @param message the message text, also used as look-up key if the logger is + * localizing messages with a resource bundle. While it is possible + * to pass <code>null</code>, this is not recommended, since a + * logging message without text is unlikely to be helpful. */ - public synchronized void warning(String message) + public void warning(String message) { - if (isLoggable(Level.WARNING)) - log(Level.WARNING, message); + synchronized (lock) + { + if (isLoggable(Level.WARNING)) + log(Level.WARNING, message); + } } - /** - * Logs a message with severity level INFO. {@link Level#INFO} is - * intended for purely informational messages that do not indicate - * error or warning situations. 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. - * - * @param message the message text, also used as look-up key if the - * logger is localizing messages with a resource - * bundle. While it is possible to pass - * <code>null</code>, this is not recommended, since - * a logging message without text is unlikely to be - * helpful. + * Logs a message with severity level INFO. {@link Level#INFO} is intended for + * purely informational messages that do not indicate error or warning + * situations. 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. + * + * @param message the message text, also used as look-up key if the logger is + * localizing messages with a resource bundle. While it is possible + * to pass <code>null</code>, this is not recommended, since a + * logging message without text is unlikely to be helpful. */ - public synchronized void info(String message) + public void info(String message) { - if (isLoggable(Level.INFO)) - log(Level.INFO, message); + synchronized (lock) + { + if (isLoggable(Level.INFO)) + log(Level.INFO, message); + } } - /** - * Logs a message with severity level CONFIG. {@link Level#CONFIG} is - * intended for static configuration messages, for example about the - * windowing environment, the operating system version, etc. - * - * @param message the message text, also used as look-up key if the - * logger is localizing messages with a resource bundle. While - * it is possible to pass <code>null</code>, this is not - * recommended, since a logging message without text is unlikely - * to be helpful. + * Logs a message with severity level CONFIG. {@link Level#CONFIG} is intended + * for static configuration messages, for example about the windowing + * environment, the operating system version, etc. + * + * @param message the message text, also used as look-up key if the logger is + * localizing messages with a resource bundle. While it is possible + * to pass <code>null</code>, this is not recommended, since a + * logging message without text is unlikely to be helpful. */ - public synchronized void config(String message) + public void config(String message) { - if (isLoggable(Level.CONFIG)) - log(Level.CONFIG, message); + synchronized (lock) + { + if (isLoggable(Level.CONFIG)) + log(Level.CONFIG, message); + } } - /** - * Logs a message with severity level FINE. {@link Level#FINE} is - * intended for messages that are relevant for developers using - * the component generating log messages. Examples include minor, - * recoverable failures, or possible inefficiencies. - * - * @param message the message text, also used as look-up key if the - * logger is localizing messages with a resource - * bundle. While it is possible to pass - * <code>null</code>, this is not recommended, since - * a logging message without text is unlikely to be - * helpful. + * Logs a message with severity level FINE. {@link Level#FINE} is intended for + * messages that are relevant for developers using the component generating + * log messages. Examples include minor, recoverable failures, or possible + * inefficiencies. + * + * @param message the message text, also used as look-up key if the logger is + * localizing messages with a resource bundle. While it is possible + * to pass <code>null</code>, this is not recommended, since a + * logging message without text is unlikely to be helpful. */ - public synchronized void fine(String message) + public void fine(String message) { - if (isLoggable(Level.FINE)) - log(Level.FINE, message); + synchronized (lock) + { + if (isLoggable(Level.FINE)) + log(Level.FINE, message); + } } - /** - * Logs a message with severity level FINER. {@link Level#FINER} is - * intended for rather detailed tracing, for example entering a - * method, returning from a method, or throwing an exception. - * - * @param message the message text, also used as look-up key if the - * logger is localizing messages with a resource - * bundle. While it is possible to pass - * <code>null</code>, this is not recommended, since - * a logging message without text is unlikely to be - * helpful. + * Logs a message with severity level FINER. {@link Level#FINER} is intended + * for rather detailed tracing, for example entering a method, returning from + * a method, or throwing an exception. + * + * @param message the message text, also used as look-up key if the logger is + * localizing messages with a resource bundle. While it is possible + * to pass <code>null</code>, this is not recommended, since a + * logging message without text is unlikely to be helpful. */ - public synchronized void finer(String message) + public void finer(String message) { - if (isLoggable(Level.FINER)) - log(Level.FINER, message); + synchronized (lock) + { + if (isLoggable(Level.FINER)) + log(Level.FINER, message); + } } - /** - * Logs a message with severity level FINEST. {@link Level#FINEST} - * is intended for highly detailed tracing, for example reaching a - * certain point inside the body of a method. - * - * @param message the message text, also used as look-up key if the - * logger is localizing messages with a resource - * bundle. While it is possible to pass - * <code>null</code>, this is not recommended, since - * a logging message without text is unlikely to be - * helpful. + * Logs a message with severity level FINEST. {@link Level#FINEST} is intended + * for highly detailed tracing, for example reaching a certain point inside + * the body of a method. + * + * @param message the message text, also used as look-up key if the logger is + * localizing messages with a resource bundle. While it is possible + * to pass <code>null</code>, this is not recommended, since a + * logging message without text is unlikely to be helpful. */ - public synchronized void finest(String message) + public void finest(String message) { - if (isLoggable(Level.FINEST)) - log(Level.FINEST, message); + synchronized (lock) + { + if (isLoggable(Level.FINEST)) + log(Level.FINEST, message); + } } - /** - * Adds a handler to the set of handlers that get notified - * when a log record is to be published. - * + * Adds a handler to the set of handlers that get notified when a log record + * is to be published. + * * @param handler the handler to be added. - * - * @throws NullPointerException if <code>handler</code> - * is <code>null</code>. - * - * @throws SecurityException if this logger is not anonymous, a - * security manager exists, and the caller is not granted - * the permission to control the logging infrastructure by - * having LoggingPermission("control"). Untrusted code can - * obtain an anonymous logger through the static factory method - * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. + * @throws NullPointerException if <code>handler</code> is <code>null</code>. + * @throws SecurityException if this logger is not anonymous, a security + * manager exists, and the caller is not granted the permission to + * control the logging infrastructure by having + * LoggingPermission("control"). Untrusted code can obtain an + * anonymous logger through the static factory method + * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. */ - public synchronized void addHandler(Handler handler) - throws SecurityException + public void addHandler(Handler handler) throws SecurityException { - if (handler == null) - throw new NullPointerException(); - - /* An application is allowed to control an anonymous logger - * without having the permission to control the logging - * infrastructure. - */ - if (!anonymous) - LogManager.getLogManager().checkAccess(); - - if (!handlerList.contains(handler)) - { - handlerList.add(handler); - handlers = getHandlers(); - } + synchronized (lock) + { + if (handler == null) + throw new NullPointerException(); + + /* + * An application is allowed to control an anonymous logger without + * having the permission to control the logging infrastructure. + */ + if (! anonymous) + LogManager.getLogManager().checkAccess(); + + if (! handlerList.contains(handler)) + { + handlerList.add(handler); + handlers = getHandlers(); + } + } } - /** - * Removes a handler from the set of handlers that get notified - * when a log record is to be published. - * + * Removes a handler from the set of handlers that get notified when a log + * record is to be published. + * * @param handler the handler to be removed. - * - * @throws SecurityException if this logger is not anonymous, a - * security manager exists, and the caller is not granted the - * permission to control the logging infrastructure by having - * LoggingPermission("control"). Untrusted code can obtain an - * anonymous logger through the static factory method {@link - * #getAnonymousLogger(java.lang.String) getAnonymousLogger}. - * - * @throws NullPointerException if <code>handler</code> - * is <code>null</code>. + * @throws SecurityException if this logger is not anonymous, a security + * manager exists, and the caller is not granted the permission to + * control the logging infrastructure by having + * LoggingPermission("control"). Untrusted code can obtain an + * anonymous logger through the static factory method {@link + * #getAnonymousLogger(java.lang.String) getAnonymousLogger}. + * @throws NullPointerException if <code>handler</code> is <code>null</code>. */ - public synchronized void removeHandler(Handler handler) - throws SecurityException + public void removeHandler(Handler handler) throws SecurityException { - /* An application is allowed to control an anonymous logger - * without having the permission to control the logging - * infrastructure. - */ - if (!anonymous) - LogManager.getLogManager().checkAccess(); - - if (handler == null) - throw new NullPointerException(); - - handlerList.remove(handler); - handlers = getHandlers(); + synchronized (lock) + { + /* + * An application is allowed to control an anonymous logger without + * having the permission to control the logging infrastructure. + */ + if (! anonymous) + LogManager.getLogManager().checkAccess(); + + if (handler == null) + throw new NullPointerException(); + + handlerList.remove(handler); + handlers = getHandlers(); + } } - /** - * Returns the handlers currently registered for this Logger. - * When a log record has been deemed as being loggable, - * it will be passed to all registered handlers for - * publication. In addition, if the logger uses parent handlers - * (see {@link #getUseParentHandlers() getUseParentHandlers} - * and {@link #setUseParentHandlers(boolean) setUseParentHandlers}, - * the log record will be passed to the parent's handlers. + * Returns the handlers currently registered for this Logger. When a log + * record has been deemed as being loggable, it will be passed to all + * registered handlers for publication. In addition, if the logger uses parent + * handlers (see {@link #getUseParentHandlers() getUseParentHandlers} and + * {@link #setUseParentHandlers(boolean) setUseParentHandlers}, the log + * record will be passed to the parent's handlers. */ - public synchronized Handler[] getHandlers() + public Handler[] getHandlers() { - /* We cannot return our internal handlers array - * because we do not have any guarantee that the - * caller would not change the array entries. - */ - return (Handler[]) handlerList.toArray(new Handler[handlerList.size()]); + synchronized (lock) + { + /* + * We cannot return our internal handlers array because we do not have + * any guarantee that the caller would not change the array entries. + */ + return (Handler[]) handlerList.toArray(new Handler[handlerList.size()]); + } } - /** - * Returns whether or not this Logger forwards log records to - * handlers registered for its parent loggers. - * - * @return <code>false</code> if this Logger sends log records - * merely to Handlers registered with itself; - * <code>true</code> if this Logger sends log records - * not only to Handlers registered with itself, but also - * to those Handlers registered with parent loggers. + * Returns whether or not this Logger forwards log records to handlers + * registered for its parent loggers. + * + * @return <code>false</code> if this Logger sends log records merely to + * Handlers registered with itself; <code>true</code> if this Logger + * sends log records not only to Handlers registered with itself, but + * also to those Handlers registered with parent loggers. */ - public synchronized boolean getUseParentHandlers() + public boolean getUseParentHandlers() { - return useParentHandlers; + synchronized (lock) + { + return useParentHandlers; + } } - /** - * Sets whether or not this Logger forwards log records to - * handlers registered for its parent loggers. - * - * @param useParentHandlers <code>false</code> to let this - * Logger send log records merely to Handlers registered - * with itself; <code>true</code> to let this Logger - * send log records not only to Handlers registered - * with itself, but also to those Handlers registered with - * parent loggers. - * - * @throws SecurityException if this logger is not anonymous, a - * security manager exists, and the caller is not granted - * the permission to control the logging infrastructure by - * having LoggingPermission("control"). Untrusted code can - * obtain an anonymous logger through the static factory method - * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. - * + * Sets whether or not this Logger forwards log records to handlers registered + * for its parent loggers. + * + * @param useParentHandlers <code>false</code> to let this Logger send log + * records merely to Handlers registered with itself; + * <code>true</code> to let this Logger send log records not only + * to Handlers registered with itself, but also to those Handlers + * registered with parent loggers. + * @throws SecurityException if this logger is not anonymous, a security + * manager exists, and the caller is not granted the permission to + * control the logging infrastructure by having + * LoggingPermission("control"). Untrusted code can obtain an + * anonymous logger through the static factory method + * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. */ - public synchronized void setUseParentHandlers(boolean useParentHandlers) + public void setUseParentHandlers(boolean useParentHandlers) { - /* An application is allowed to control an anonymous logger - * without having the permission to control the logging - * infrastructure. - */ - if (!anonymous) - LogManager.getLogManager().checkAccess(); - - this.useParentHandlers = useParentHandlers; + synchronized (lock) + { + /* + * An application is allowed to control an anonymous logger without + * having the permission to control the logging infrastructure. + */ + if (! anonymous) + LogManager.getLogManager().checkAccess(); + + this.useParentHandlers = useParentHandlers; + } } - /** - * Returns the parent of this logger. By default, the parent is - * assigned by the LogManager by inspecting the logger's name. - * - * @return the parent of this logger (as detemined by the LogManager - * by inspecting logger names), the root logger if no other - * logger has a name which is a prefix of this logger's name, or - * <code>null</code> for the root logger. + * Returns the parent of this logger. By default, the parent is assigned by + * the LogManager by inspecting the logger's name. + * + * @return the parent of this logger (as detemined by the LogManager by + * inspecting logger names), the root logger if no other logger has a + * name which is a prefix of this logger's name, or <code>null</code> + * for the root logger. */ - public synchronized Logger getParent() + public Logger getParent() { - return parent; + synchronized (lock) + { + return parent; + } } - /** - * Sets the parent of this logger. Usually, applications do not - * call this method directly. Instead, the LogManager will ensure - * that the tree of loggers reflects the hierarchical logger - * namespace. Basically, this method should not be public at all, - * but the GNU implementation follows the API specification. - * - * @throws NullPointerException if <code>parent</code> is - * <code>null</code>. - * - * @throws SecurityException if this logger is not anonymous, a - * security manager exists, and the caller is not granted - * the permission to control the logging infrastructure by - * having LoggingPermission("control"). Untrusted code can - * obtain an anonymous logger through the static factory method - * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. + * Sets the parent of this logger. Usually, applications do not call this + * method directly. Instead, the LogManager will ensure that the tree of + * loggers reflects the hierarchical logger namespace. Basically, this method + * should not be public at all, but the GNU implementation follows the API + * specification. + * + * @throws NullPointerException if <code>parent</code> is <code>null</code>. + * @throws SecurityException if this logger is not anonymous, a security + * manager exists, and the caller is not granted the permission to + * control the logging infrastructure by having + * LoggingPermission("control"). Untrusted code can obtain an + * anonymous logger through the static factory method + * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}. */ - public synchronized void setParent(Logger parent) + public void setParent(Logger parent) { - if (parent == null) - throw new NullPointerException(); + synchronized (lock) + { + if (parent == null) + throw new NullPointerException(); - if (this == root) - throw new IllegalArgumentException( - "the root logger can only have a null parent"); + if (this == root) + throw new IllegalArgumentException( + "the root logger can only have a null parent"); - /* An application is allowed to control an anonymous logger - * without having the permission to control the logging - * infrastructure. - */ - if (!anonymous) - LogManager.getLogManager().checkAccess(); + /* + * An application is allowed to control an anonymous logger without + * having the permission to control the logging infrastructure. + */ + if (! anonymous) + LogManager.getLogManager().checkAccess(); - this.parent = parent; + this.parent = parent; + } } - + /** - * Gets the StackTraceElement of the first class that is not this class. - * That should be the initial caller of a logging method. + * Gets the StackTraceElement of the first class that is not this class. That + * should be the initial caller of a logging method. + * * @return caller of the initial logging method or null if unknown. */ private StackTraceElement getCallerStackFrame() @@ -1195,18 +1163,18 @@ public class Logger int index = 0; // skip to stackentries until this class - while(index < stackTrace.length - && !stackTrace[index].getClassName().equals(getClass().getName())) + while (index < stackTrace.length + && ! stackTrace[index].getClassName().equals(getClass().getName())) index++; // skip the stackentries of this class - while(index < stackTrace.length - && stackTrace[index].getClassName().equals(getClass().getName())) + while (index < stackTrace.length + && stackTrace[index].getClassName().equals(getClass().getName())) index++; return index < stackTrace.length ? stackTrace[index] : null; } - + /** * Reset and close handlers attached to this logger. This function is package * private because it must only be available to the LogManager. diff --git a/libjava/classpath/java/util/zip/ZipEntry.java b/libjava/classpath/java/util/zip/ZipEntry.java index 9b7afa00045..893f043746d 100644 --- a/libjava/classpath/java/util/zip/ZipEntry.java +++ b/libjava/classpath/java/util/zip/ZipEntry.java @@ -357,7 +357,7 @@ public class ZipEntry implements ZipConstants, Cloneable | (extra[pos+2] & 0xff) << 8 | (extra[pos+3] & 0xff) << 16 | (extra[pos+4] & 0xff) << 24); - setTime(time); + setTime(time*1000); } } pos += len; |