aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/java/util
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/util')
-rw-r--r--libjava/classpath/java/util/AbstractCollection.java16
-rw-r--r--libjava/classpath/java/util/ResourceBundle.java6
-rw-r--r--libjava/classpath/java/util/jar/Attributes.java5
-rw-r--r--libjava/classpath/java/util/logging/FileHandler.java2
-rw-r--r--libjava/classpath/java/util/logging/LogManager.java53
-rw-r--r--libjava/classpath/java/util/logging/SimpleFormatter.java10
-rw-r--r--libjava/classpath/java/util/prefs/AbstractPreferences.java184
-rw-r--r--libjava/classpath/java/util/prefs/NodeChangeEvent.java22
-rw-r--r--libjava/classpath/java/util/prefs/PreferenceChangeEvent.java22
-rw-r--r--libjava/classpath/java/util/prefs/Preferences.java36
-rw-r--r--libjava/classpath/java/util/regex/MatchResult.java81
-rw-r--r--libjava/classpath/java/util/regex/Matcher.java25
-rw-r--r--libjava/classpath/java/util/regex/PatternSyntaxException.java1
-rw-r--r--libjava/classpath/java/util/zip/ZipConstants.java10
-rw-r--r--libjava/classpath/java/util/zip/ZipFile.java397
-rw-r--r--libjava/classpath/java/util/zip/ZipOutputStream.java12
16 files changed, 606 insertions, 276 deletions
diff --git a/libjava/classpath/java/util/AbstractCollection.java b/libjava/classpath/java/util/AbstractCollection.java
index 00ee23e..3ae98e0 100644
--- a/libjava/classpath/java/util/AbstractCollection.java
+++ b/libjava/classpath/java/util/AbstractCollection.java
@@ -423,7 +423,9 @@ public abstract class AbstractCollection implements Collection
* of the form "[a, b, ...]" where a and b etc are the results of calling
* toString on the elements of the collection. This implementation obtains an
* Iterator over the Collection and adds each element to a StringBuffer as it
- * is returned by the iterator.
+ * is returned by the iterator. "<this>" is inserted when the collection
+ * contains itself (only works for direct containment, not for collections
+ * inside collections).
*
* @return a String representation of the Collection
*/
@@ -431,10 +433,16 @@ public abstract class AbstractCollection implements Collection
{
Iterator itr = iterator();
StringBuffer r = new StringBuffer("[");
- for (int pos = size(); pos > 0; pos--)
+ boolean hasNext = itr.hasNext();
+ while (hasNext)
{
- r.append(itr.next());
- if (pos > 1)
+ Object o = itr.next();
+ if (o == this)
+ r.append("<this>");
+ else
+ r.append(o);
+ hasNext = itr.hasNext();
+ if (hasNext)
r.append(", ");
}
r.append("]");
diff --git a/libjava/classpath/java/util/ResourceBundle.java b/libjava/classpath/java/util/ResourceBundle.java
index 6aea673..4dcb9ad 100644
--- a/libjava/classpath/java/util/ResourceBundle.java
+++ b/libjava/classpath/java/util/ResourceBundle.java
@@ -1,5 +1,5 @@
/* ResourceBundle -- aids in loading resource bundles
- Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -476,9 +476,7 @@ public abstract class ResourceBundle
if (ResourceBundle.class.isAssignableFrom(rbClass))
bundle = (ResourceBundle) rbClass.newInstance();
}
- catch (IllegalAccessException ex) {}
- catch (InstantiationException ex) {}
- catch (ClassNotFoundException ex) {}
+ catch (Exception ex) {}
if (bundle == null)
{
diff --git a/libjava/classpath/java/util/jar/Attributes.java b/libjava/classpath/java/util/jar/Attributes.java
index 4db2c72..c8babdd 100644
--- a/libjava/classpath/java/util/jar/Attributes.java
+++ b/libjava/classpath/java/util/jar/Attributes.java
@@ -427,16 +427,13 @@ public class Attributes implements Cloneable, Map
* Attributes map.
* When the name already exists the value is replaced and the old value
* is returned.
- * <p>
- * I don't know why there is no public method with this signature. I think
- * there should be one.
*
* @param name the attribite name to add/replace
* @param value the (new) value of the attribute name
* @returns the old value of the attribute name or null if it didn't exist
* yet
*/
- String putValue(Name name, String value)
+ public String putValue(Name name, String value)
{
return (String) put(name, value);
}
diff --git a/libjava/classpath/java/util/logging/FileHandler.java b/libjava/classpath/java/util/logging/FileHandler.java
index b03df97..cde8619 100644
--- a/libjava/classpath/java/util/logging/FileHandler.java
+++ b/libjava/classpath/java/util/logging/FileHandler.java
@@ -115,7 +115,7 @@ import java.util.ListIterator;
*
* <li><code>%h</code> - replaced by the location of the home
* directory of the current user. This value is taken from the
- * system property <code>file.separator</code>.</li>
+ * system property <code>user.home</code>.</li>
*
* <li><code>%g</code> - replaced by a generation number for
* distinguisthing the individual items in the rotating set
diff --git a/libjava/classpath/java/util/logging/LogManager.java b/libjava/classpath/java/util/logging/LogManager.java
index b62292f..73eb9bc 100644
--- a/libjava/classpath/java/util/logging/LogManager.java
+++ b/libjava/classpath/java/util/logging/LogManager.java
@@ -41,6 +41,7 @@ package java.util.logging;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
@@ -295,6 +296,28 @@ public class LogManager
if (parent != logger.getParent())
logger.setParent(parent);
+ // The level of the newly added logger must be specified.
+ // The easiest case is if there is a level for exactly this logger
+ // in the properties. If no such level exists the level needs to be
+ // searched along the hirachy. So if there is a new logger 'foo.blah.blub'
+ // and an existing parent logger 'foo' the properties 'foo.blah.blub.level'
+ // and 'foo.blah.level' need to be checked. If both do not exist in the
+ // properties the level of the new logger is set to 'null' (i.e. it uses the
+ // level of its parent 'foo').
+ Level logLevel = logger.getLevel();
+ String searchName = name;
+ String parentName = parent != null ? parent.getName() : "";
+ while (logLevel == null && ! searchName.equals(parentName))
+ {
+ logLevel = getLevelProperty(searchName + ".level", logLevel);
+ int index = searchName.lastIndexOf('.');
+ if(index > -1)
+ searchName = searchName.substring(0,index);
+ else
+ searchName = "";
+ }
+ logger.setLevel(logLevel);
+
/* It can happen that existing loggers should be children of
* the newly added logger. For example, assume that there
* already exist loggers under the names "", "foo", and "foo.bar.baz".
@@ -488,23 +511,37 @@ public class LogManager
path = System.getProperty("java.util.logging.config.file");
if ((path == null) || (path.length() == 0))
{
- String url = (System.getProperty("gnu.classpath.home.url")
- + "/logging.properties");
- inputStream = new URL(url).openStream();
+ String url = (System.getProperty("gnu.classpath.home.url")
+ + "/logging.properties");
+ try
+ {
+ inputStream = new URL(url).openStream();
+ }
+ catch (Exception e)
+ {
+ inputStream=null;
+ }
+
+ // If no config file could be found use a default configuration.
+ if(inputStream == null)
+ {
+ String defaultConfig = "handlers = java.util.logging.ConsoleHandler \n"
+ + ".level=INFO \n";
+ inputStream = new ByteArrayInputStream(defaultConfig.getBytes());
+ }
}
else
inputStream = new java.io.FileInputStream(path);
try
{
- readConfiguration(inputStream);
+ readConfiguration(inputStream);
}
finally
{
- /* Close the stream in order to save
- * resources such as file descriptors.
- */
- inputStream.close();
+ // Close the stream in order to save
+ // resources such as file descriptors.
+ inputStream.close();
}
}
diff --git a/libjava/classpath/java/util/logging/SimpleFormatter.java b/libjava/classpath/java/util/logging/SimpleFormatter.java
index ff53db8..2ebb1a1 100644
--- a/libjava/classpath/java/util/logging/SimpleFormatter.java
+++ b/libjava/classpath/java/util/logging/SimpleFormatter.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package java.util.logging;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.text.DateFormat;
import java.util.Date;
@@ -114,6 +116,14 @@ public class SimpleFormatter
buf.append(lineSep);
+ Throwable throwable = record.getThrown();
+ if (throwable != null)
+ {
+ StringWriter sink = new StringWriter();
+ throwable.printStackTrace(new PrintWriter(sink, true));
+ buf.append(sink.toString());
+ }
+
return buf.toString();
}
}
diff --git a/libjava/classpath/java/util/prefs/AbstractPreferences.java b/libjava/classpath/java/util/prefs/AbstractPreferences.java
index 3f70400..e676dc3 100644
--- a/libjava/classpath/java/util/prefs/AbstractPreferences.java
+++ b/libjava/classpath/java/util/prefs/AbstractPreferences.java
@@ -1,5 +1,5 @@
/* AbstractPreferences -- Partial implementation of a Preference node
- Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,11 +38,13 @@ exception statement from your version. */
package java.util.prefs;
+import gnu.java.util.prefs.EventDispatcher;
import gnu.java.util.prefs.NodeWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeSet;
@@ -68,7 +70,7 @@ public abstract class AbstractPreferences extends Preferences {
/**
* Set to true in the contructor if the node did not exist in the backing
* store when this preference node object was created. Should be set in
- * the contructor of a subclass. Defaults to false. Used to fire node
+ * the constructor of a subclass. Defaults to false. Used to fire node
* changed events.
*/
protected boolean newNode = false;
@@ -97,6 +99,16 @@ public abstract class AbstractPreferences extends Preferences {
*/
private HashMap childCache = new HashMap();
+ /**
+ * A list of all the registered NodeChangeListener objects.
+ */
+ private ArrayList nodeListeners;
+
+ /**
+ * A list of all the registered PreferenceChangeListener objects.
+ */
+ private ArrayList preferenceListeners;
+
// constructor
/**
@@ -256,7 +268,7 @@ public abstract class AbstractPreferences extends Preferences {
* @exception IllegalArgumentException if the path contains two or more
* consecutive '/' characters, ends with a '/' charactor and is not the
* string "/" (indicating the root node) or any name on the path is more
- * then 80 characters long
+ * than 80 characters long
*/
public Preferences node(String path) {
synchronized(lock) {
@@ -325,8 +337,9 @@ public abstract class AbstractPreferences extends Preferences {
// Not in childCache yet so create a new sub node
child = childSpi(childName);
- // XXX - check if node is new
childCache.put(childName, child);
+ if (child.newNode && nodeListeners != null)
+ fire(new NodeChangeEvent(this, child), true);
}
// Lock the child and go down
@@ -477,9 +490,7 @@ public abstract class AbstractPreferences extends Preferences {
// export methods
- /**
- * XXX
- */
+ // Inherit javadoc.
public void exportNode(OutputStream os)
throws BackingStoreException,
IOException
@@ -488,9 +499,7 @@ public abstract class AbstractPreferences extends Preferences {
nodeWriter.writePrefs();
}
- /**
- * XXX
- */
+ // Inherit javadoc.
public void exportSubtree(OutputStream os)
throws BackingStoreException,
IOException
@@ -765,8 +774,8 @@ public abstract class AbstractPreferences extends Preferences {
* Key and value cannot be null, the key cannot exceed 80 characters
* and the value cannot exceed 8192 characters.
* <p>
- * The result will be immediatly visible in this VM, but may not be
- * immediatly written to the backing store.
+ * The result will be immediately visible in this VM, but may not be
+ * immediately written to the backing store.
* <p>
* Checks that key and value are valid, locks this node, and checks that
* the node has not been removed. Then it calls <code>putSpi()</code>.
@@ -789,7 +798,8 @@ public abstract class AbstractPreferences extends Preferences {
putSpi(key, value);
- // XXX - fire events
+ if (preferenceListeners != null)
+ fire(new PreferenceChangeEvent(this, key, value));
}
}
@@ -804,9 +814,7 @@ public abstract class AbstractPreferences extends Preferences {
* @exception IllegalStateException when this node has been removed
*/
public void putBoolean(String key, boolean value) {
- put(key, String.valueOf(value));
- // XXX - Use when using 1.4 compatible Boolean
- // put(key, Boolean.toString(value));
+ put(key, Boolean.toString(value));
}
/**
@@ -935,8 +943,8 @@ public abstract class AbstractPreferences extends Preferences {
/**
* Removes the preferences entry from this preferences node.
* <p>
- * The result will be immediatly visible in this VM, but may not be
- * immediatly written to the backing store.
+ * The result will be immediately visible in this VM, but may not be
+ * immediately written to the backing store.
* <p>
* This implementation checks that the key is not larger then 80
* characters, gets the lock of this node, checks that the node has
@@ -955,6 +963,9 @@ public abstract class AbstractPreferences extends Preferences {
throw new IllegalStateException("Node removed");
removeSpi(key);
+
+ if (preferenceListeners != null)
+ fire(new PreferenceChangeEvent(this, key, null));
}
}
@@ -962,7 +973,7 @@ public abstract class AbstractPreferences extends Preferences {
* Removes all entries from this preferences node. May need access to the
* backing store to get and clear all entries.
* <p>
- * The result will be immediatly visible in this VM, but may not be
+ * The result will be immediately visible in this VM, but may not be
* immediatly written to the backing store.
* <p>
* This implementation locks this node, checks that the node has not been
@@ -1049,7 +1060,7 @@ public abstract class AbstractPreferences extends Preferences {
for (int i = 0; i < keys.length; i++) {
// Have to lock this node again to access the childCache
AbstractPreferences subNode;
- synchronized(this) {
+ synchronized(lock) {
subNode = (AbstractPreferences) childCache.get(keys[i]);
}
@@ -1087,8 +1098,8 @@ public abstract class AbstractPreferences extends Preferences {
if (parent == null)
throw new UnsupportedOperationException("Cannot remove root node");
- synchronized(parent) {
- synchronized(this) {
+ synchronized (parent.lock) {
+ synchronized(this.lock) {
if (isRemoved())
throw new IllegalStateException("Node Removed");
@@ -1122,7 +1133,7 @@ public abstract class AbstractPreferences extends Preferences {
Iterator i = childCache.values().iterator();
while (i.hasNext()) {
AbstractPreferences node = (AbstractPreferences) i.next();
- synchronized(node) {
+ synchronized(node.lock) {
node.purge();
}
}
@@ -1134,30 +1145,131 @@ public abstract class AbstractPreferences extends Preferences {
removeNodeSpi();
removed = true;
- // XXX - check for listeners
+ if (nodeListeners != null)
+ fire(new NodeChangeEvent(parent, this), false);
}
// listener methods
/**
- * XXX
+ * Add a listener which is notified when a sub-node of this node
+ * is added or removed.
+ * @param listener the listener to add
*/
- public void addNodeChangeListener(NodeChangeListener listener) {
- // XXX
+ public void addNodeChangeListener(NodeChangeListener listener)
+ {
+ synchronized (lock)
+ {
+ if (isRemoved())
+ throw new IllegalStateException("node has been removed");
+ if (listener == null)
+ throw new NullPointerException("listener is null");
+ if (nodeListeners == null)
+ nodeListeners = new ArrayList();
+ nodeListeners.add(listener);
+ }
}
- public void addPreferenceChangeListener(PreferenceChangeListener listener) {
- // XXX
+ /**
+ * Add a listener which is notified when a value in this node
+ * is added, changed, or removed.
+ * @param listener the listener to add
+ */
+ public void addPreferenceChangeListener(PreferenceChangeListener listener)
+ {
+ synchronized (lock)
+ {
+ if (isRemoved())
+ throw new IllegalStateException("node has been removed");
+ if (listener == null)
+ throw new NullPointerException("listener is null");
+ if (preferenceListeners == null)
+ preferenceListeners = new ArrayList();
+ preferenceListeners.add(listener);
+ }
}
- public void removeNodeChangeListener(NodeChangeListener listener) {
- // XXX
+ /**
+ * Remove the indicated node change listener from the list of
+ * listeners to notify.
+ * @param listener the listener to remove
+ */
+ public void removeNodeChangeListener(NodeChangeListener listener)
+ {
+ synchronized (lock)
+ {
+ if (isRemoved())
+ throw new IllegalStateException("node has been removed");
+ if (listener == null)
+ throw new NullPointerException("listener is null");
+ if (nodeListeners != null)
+ nodeListeners.remove(listener);
+ }
}
- public void removePreferenceChangeListener
- (PreferenceChangeListener listener)
+ /**
+ * Remove the indicated preference change listener from the list of
+ * listeners to notify.
+ * @param listener the listener to remove
+ */
+ public void removePreferenceChangeListener (PreferenceChangeListener listener)
{
- // XXX
+ synchronized (lock)
+ {
+ if (isRemoved())
+ throw new IllegalStateException("node has been removed");
+ if (listener == null)
+ throw new NullPointerException("listener is null");
+ if (preferenceListeners != null)
+ preferenceListeners.remove(listener);
+ }
+ }
+
+ /**
+ * Send a preference change event to all listeners. Note that
+ * the caller is responsible for holding the node's lock, and
+ * for checking that the list of listeners is not null.
+ * @param event the event to send
+ */
+ private void fire(final PreferenceChangeEvent event)
+ {
+ Iterator it = preferenceListeners.iterator();
+ while (it.hasNext())
+ {
+ final PreferenceChangeListener l = (PreferenceChangeListener) it.next();
+ EventDispatcher.dispatch(new Runnable()
+ {
+ public void run()
+ {
+ l.preferenceChange(event);
+ }
+ });
+ }
+ }
+
+ /**
+ * Send a node change event to all listeners. Note that
+ * the caller is responsible for holding the node's lock, and
+ * for checking that the list of listeners is not null.
+ * @param event the event to send
+ */
+ private void fire(final NodeChangeEvent event, final boolean added)
+ {
+ Iterator it = nodeListeners.iterator();
+ while (it.hasNext())
+ {
+ final NodeChangeListener l = (NodeChangeListener) it.next();
+ EventDispatcher.dispatch(new Runnable()
+ {
+ public void run()
+ {
+ if (added)
+ l.childAdded(event);
+ else
+ l.childRemoved(event);
+ }
+ });
+ }
}
// abstract spi methods
@@ -1214,7 +1326,7 @@ public abstract class AbstractPreferences extends Preferences {
/**
* Sets the value of the given preferences entry for this node.
* The implementation is not required to propagate the change to the
- * backing store immediatly. It may not throw an exception when it tries
+ * backing store immediately. It may not throw an exception when it tries
* to write to the backing store and that operation fails, the failure
* should be registered so a later invocation of <code>flush()</code>
* or <code>sync()</code> can signal the failure.
@@ -1227,7 +1339,7 @@ public abstract class AbstractPreferences extends Preferences {
/**
* Removes the given key entry from this preferences node.
* The implementation is not required to propagate the change to the
- * backing store immediatly. It may not throw an exception when it tries
+ * backing store immediately. It may not throw an exception when it tries
* to write to the backing store and that operation fails, the failure
* should be registered so a later invocation of <code>flush()</code>
* or <code>sync()</code> can signal the failure.
diff --git a/libjava/classpath/java/util/prefs/NodeChangeEvent.java b/libjava/classpath/java/util/prefs/NodeChangeEvent.java
index 89986db..8c48fb2 100644
--- a/libjava/classpath/java/util/prefs/NodeChangeEvent.java
+++ b/libjava/classpath/java/util/prefs/NodeChangeEvent.java
@@ -1,5 +1,5 @@
/* NodeChangeEvent - ObjectEvent fired when a Preference node is added/removed
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,6 +37,10 @@ exception statement from your version. */
package java.util.prefs;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.util.EventObject;
/**
@@ -44,12 +48,16 @@ import java.util.EventObject;
* This event is only generated when a new subnode is added or a subnode is
* removed from a preference node. Changes in the entries of a preference node
* are indicated with a <code>PreferenceChangeEvent</code>.
+ * <p>
+ * Note that although this class is marked as serializable, attempts to
+ * serialize it will fail with NotSerializableException.
*
* @since 1.4
* @author Mark Wielaard (mark@klomp.org)
*/
public class NodeChangeEvent extends EventObject {
+ // We have this to placate the compiler.
private static final long serialVersionUID =8068949086596572957L;
/**
@@ -88,4 +96,16 @@ public class NodeChangeEvent extends EventObject {
public Preferences getChild() {
return child;
}
+
+ private void readObject(ObjectInputStream ois)
+ throws IOException
+ {
+ throw new NotSerializableException("LineEvent is not serializable");
+ }
+
+ private void writeObject(ObjectOutputStream oos)
+ throws IOException
+ {
+ throw new NotSerializableException("LineEvent is not serializable");
+ }
}
diff --git a/libjava/classpath/java/util/prefs/PreferenceChangeEvent.java b/libjava/classpath/java/util/prefs/PreferenceChangeEvent.java
index fe371f1..41c3a47 100644
--- a/libjava/classpath/java/util/prefs/PreferenceChangeEvent.java
+++ b/libjava/classpath/java/util/prefs/PreferenceChangeEvent.java
@@ -1,5 +1,5 @@
/* PreferenceChangeEvent - ObjectEvent fired when a Preferences entry changes
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,6 +37,10 @@ exception statement from your version. */
package java.util.prefs;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.util.EventObject;
/**
@@ -47,12 +51,16 @@ import java.util.EventObject;
* Preference change events are only generated for entries in one particular
* preference node. Notification of subnode addition/removal is given by a
* <code>NodeChangeEvent</code>.
+ * <p>
+ * Note that although this class is marked as serializable, attempts to
+ * serialize it will fail with NotSerializableException.
*
* @since 1.4
* @author Mark Wielaard (mark@klomp.org)
*/
public class PreferenceChangeEvent extends EventObject {
+ // We have this to placate the compiler.
private static final long serialVersionUID = 793724513368024975L;
/**
@@ -102,4 +110,16 @@ public class PreferenceChangeEvent extends EventObject {
public String getNewValue() {
return newValue;
}
+
+ private void readObject(ObjectInputStream ois)
+ throws IOException
+ {
+ throw new NotSerializableException("LineEvent is not serializable");
+ }
+
+ private void writeObject(ObjectOutputStream oos)
+ throws IOException
+ {
+ throw new NotSerializableException("LineEvent is not serializable");
+ }
}
diff --git a/libjava/classpath/java/util/prefs/Preferences.java b/libjava/classpath/java/util/prefs/Preferences.java
index 3fee1c5..a78381b 100644
--- a/libjava/classpath/java/util/prefs/Preferences.java
+++ b/libjava/classpath/java/util/prefs/Preferences.java
@@ -1,5 +1,5 @@
/* Preferences -- Preference node containing key value entries and subnodes
- Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -90,12 +90,9 @@ public abstract class Preferences {
/**
* Default PreferencesFactory class used when the system property
* "java.util.prefs.PreferencesFactory" is not set.
- * <p>
- * XXX - Currently set to MemoryBasedFactory, should be changed
- * when FileBasedPreferences backend works.
*/
private static final String defaultFactoryClass
- = "gnu.java.util.prefs.MemoryBasedFactory";
+ = "gnu.java.util.prefs.FileBasedFactory";
/** Permission needed to access system or user root. */
private static final Permission prefsPermission
@@ -219,8 +216,7 @@ public abstract class Preferences {
catch (Exception e)
{
throw new RuntimeException ("Couldn't load default factory"
- + " '"+ defaultFactoryClass +"'");
- // XXX - when using 1.4 compatible throwables add cause
+ + " '"+ defaultFactoryClass +"'", e);
}
}
@@ -288,7 +284,13 @@ public abstract class Preferences {
}
/**
- * XXX
+ * Import preferences from the given input stream. This expects
+ * preferences to be represented in XML as emitted by
+ * {@link #exportNode(OutputStream)} and
+ * {@link #exportSubtree(OutputStream)}.
+ * @throws IOException if there is an error while reading
+ * @throws InvalidPreferencesFormatException if the XML is not properly
+ * formatted
*/
public static void importPreferences(InputStream is)
throws InvalidPreferencesFormatException,
@@ -385,14 +387,28 @@ public abstract class Preferences {
// abstract methods (export)
/**
- * XXX
+ * Export this node, but not its descendants, as XML to the
+ * indicated output stream. The XML will be encoded using UTF-8
+ * and will use a specified document type:<br>
+ * <code>&lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</code><br>
+ * @param os the output stream to which the XML is sent
+ * @throws BackingStoreException if preference data cannot be read
+ * @throws IOException if an error occurs while writing the XML
+ * @throws IllegalStateException if this node or an ancestor has been removed
*/
public abstract void exportNode(OutputStream os)
throws BackingStoreException,
IOException;
/**
- * XXX
+ * Export this node and all its descendants as XML to the
+ * indicated output stream. The XML will be encoded using UTF-8
+ * and will use a specified document type:<br>
+ * <code>&lt;!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd"&gt;</code><br>
+ * @param os the output stream to which the XML is sent
+ * @throws BackingStoreException if preference data cannot be read
+ * @throws IOException if an error occurs while writing the XML
+ * @throws IllegalStateException if this node or an ancestor has been removed
*/
public abstract void exportSubtree(OutputStream os)
throws BackingStoreException,
diff --git a/libjava/classpath/java/util/regex/MatchResult.java b/libjava/classpath/java/util/regex/MatchResult.java
new file mode 100644
index 0000000..c82d8cc
--- /dev/null
+++ b/libjava/classpath/java/util/regex/MatchResult.java
@@ -0,0 +1,81 @@
+/* MatchResult.java -- Result of a regular expression match.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.regex;
+
+/**
+ * This interface represents the result of a regular expression match.
+ * It can be used to query the contents of the match, but not to modify
+ * them.
+ * @since 1.5
+ */
+public interface MatchResult
+{
+ /** Returns the index just after the last matched character. */
+ int end();
+
+ /**
+ * Returns the index just after the last matched character of the
+ * given sub-match group.
+ * @param group the sub-match group
+ */
+ int end(int group);
+
+ /** Returns the substring of the input which was matched. */
+ String group();
+
+ /**
+ * Returns the substring of the input which was matched by the
+ * given sub-match group.
+ * @param group the sub-match group
+ */
+ String group(int group);
+
+ /** Returns the number of sub-match groups in the matching pattern. */
+ int groupCount();
+
+ /** Returns the index of the first character of the match. */
+ int start();
+
+ /**
+ * Returns the index of the first character of the given sub-match
+ * group.
+ * @param group the sub-match group
+ */
+ int start(int group);
+}
diff --git a/libjava/classpath/java/util/regex/Matcher.java b/libjava/classpath/java/util/regex/Matcher.java
index 5d04bdb..98086bf 100644
--- a/libjava/classpath/java/util/regex/Matcher.java
+++ b/libjava/classpath/java/util/regex/Matcher.java
@@ -1,5 +1,5 @@
/* Matcher.java -- Instance of a regular expression applied to a char sequence.
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +38,7 @@ exception statement from your version. */
package java.util.regex;
+import gnu.regexp.RE;
import gnu.regexp.REMatch;
/**
@@ -45,7 +46,7 @@ import gnu.regexp.REMatch;
*
* @since 1.4
*/
-public final class Matcher
+public final class Matcher implements MatchResult
{
private Pattern pattern;
private CharSequence input;
@@ -74,7 +75,8 @@ public final class Matcher
assertMatchOp();
sb.append(input.subSequence(appendPosition,
match.getStartIndex()).toString());
- sb.append(match.substituteInto(replacement));
+ sb.append(RE.getReplacement(replacement, match,
+ RE.REG_REPLACE_USE_BACKSLASHESCAPE));
appendPosition = match.getEndIndex();
return this;
}
@@ -189,7 +191,8 @@ public final class Matcher
{
reset();
// Semantics might not quite match
- return pattern.getRE().substitute(input, replacement, position);
+ return pattern.getRE().substitute(input, replacement, position,
+ RE.REG_REPLACE_USE_BACKSLASHESCAPE);
}
/**
@@ -198,7 +201,8 @@ public final class Matcher
public String replaceAll (String replacement)
{
reset();
- return pattern.getRE().substituteAll(input, replacement, position);
+ return pattern.getRE().substituteAll(input, replacement, position,
+ RE.REG_REPLACE_USE_BACKSLASHESCAPE);
}
public int groupCount ()
@@ -233,10 +237,15 @@ public final class Matcher
*/
public boolean matches ()
{
- if (lookingAt())
+ match = pattern.getRE().getMatch(input, 0, RE.REG_TRY_ENTIRE_MATCH);
+ if (match != null)
{
- if (position == input.length())
- return true;
+ if (match.getStartIndex() == 0)
+ {
+ position = match.getEndIndex();
+ if (position == input.length())
+ return true;
+ }
match = null;
}
return false;
diff --git a/libjava/classpath/java/util/regex/PatternSyntaxException.java b/libjava/classpath/java/util/regex/PatternSyntaxException.java
index 0c80e11..41e650d 100644
--- a/libjava/classpath/java/util/regex/PatternSyntaxException.java
+++ b/libjava/classpath/java/util/regex/PatternSyntaxException.java
@@ -41,6 +41,7 @@ package java.util.regex;
* Indicates illegal pattern for regular expression.
* Includes state to inspect the pattern and what and where the expression
* was not valid regular expression.
+ * @since 1.4
*/
public class PatternSyntaxException extends IllegalArgumentException
{
diff --git a/libjava/classpath/java/util/zip/ZipConstants.java b/libjava/classpath/java/util/zip/ZipConstants.java
index 952a44d..6d66419 100644
--- a/libjava/classpath/java/util/zip/ZipConstants.java
+++ b/libjava/classpath/java/util/zip/ZipConstants.java
@@ -1,5 +1,5 @@
/* java.util.zip.ZipConstants
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,7 +41,7 @@ interface ZipConstants
{
/* The local file header */
int LOCHDR = 30;
- int LOCSIG = 'P'|('K'<<8)|(3<<16)|(4<<24);
+ long LOCSIG = 'P'|('K'<<8)|(3<<16)|(4<<24);
int LOCVER = 4;
int LOCFLG = 6;
@@ -54,7 +54,7 @@ interface ZipConstants
int LOCEXT = 28;
/* The Data descriptor */
- int EXTSIG = 'P'|('K'<<8)|(7<<16)|(8<<24);
+ long EXTSIG = 'P'|('K'<<8)|(7<<16)|(8<<24);
int EXTHDR = 16;
int EXTCRC = 4;
@@ -62,7 +62,7 @@ interface ZipConstants
int EXTLEN = 12;
/* The central directory file header */
- int CENSIG = 'P'|('K'<<8)|(1<<16)|(2<<24);
+ long CENSIG = 'P'|('K'<<8)|(1<<16)|(2<<24);
int CENHDR = 46;
int CENVEM = 4;
@@ -82,7 +82,7 @@ interface ZipConstants
int CENOFF = 42;
/* The entries in the end of central directory */
- int ENDSIG = 'P'|('K'<<8)|(5<<16)|(6<<24);
+ long ENDSIG = 'P'|('K'<<8)|(5<<16)|(6<<24);
int ENDHDR = 22;
/* The following two fields are missing in SUN JDK */
diff --git a/libjava/classpath/java/util/zip/ZipFile.java b/libjava/classpath/java/util/zip/ZipFile.java
index 4be845e..7307ee9 100644
--- a/libjava/classpath/java/util/zip/ZipFile.java
+++ b/libjava/classpath/java/util/zip/ZipFile.java
@@ -1,5 +1,5 @@
/* ZipFile.java --
- Copyright (C) 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,8 +41,6 @@ package java.util.zip;
import gnu.java.util.EmptyEnumeration;
-import java.io.BufferedInputStream;
-import java.io.DataInput;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
@@ -141,23 +139,33 @@ public class ZipFile implements ZipConstants
checkZipFile();
}
- private void checkZipFile() throws IOException, ZipException
+ private void checkZipFile() throws ZipException
{
- byte[] magicBuf = new byte[4];
- boolean validRead = true;
+ boolean valid = false;
try
{
- raf.readFully(magicBuf);
- }
- catch (EOFException eof)
+ byte[] buf = new byte[4];
+ raf.readFully(buf);
+ int sig = buf[0] & 0xFF
+ | ((buf[1] & 0xFF) << 8)
+ | ((buf[2] & 0xFF) << 16)
+ | ((buf[3] & 0xFF) << 24);
+ valid = sig == LOCSIG;
+ }
+ catch (IOException _)
{
- validRead = false;
}
- if (validRead == false || readLeInt(magicBuf, 0) != LOCSIG)
+ if (!valid)
{
- raf.close();
+ try
+ {
+ raf.close();
+ }
+ catch (IOException _)
+ {
+ }
throw new ZipException("Not a valid zip file");
}
}
@@ -172,69 +180,6 @@ public class ZipFile implements ZipConstants
}
/**
- * Read an unsigned short in little endian byte order from the given
- * DataInput stream using the given byte buffer.
- *
- * @param di DataInput stream to read from.
- * @param b the byte buffer to read in (must be at least 2 bytes long).
- * @return The value read.
- *
- * @exception IOException if a i/o error occured.
- * @exception EOFException if the file ends prematurely
- */
- private int readLeShort(DataInput di, byte[] b) throws IOException
- {
- di.readFully(b, 0, 2);
- return (b[0] & 0xff) | (b[1] & 0xff) << 8;
- }
-
- /**
- * Read an int in little endian byte order from the given
- * DataInput stream using the given byte buffer.
- *
- * @param di DataInput stream to read from.
- * @param b the byte buffer to read in (must be at least 4 bytes long).
- * @return The value read.
- *
- * @exception IOException if a i/o error occured.
- * @exception EOFException if the file ends prematurely
- */
- private int readLeInt(DataInput di, byte[] b) throws IOException
- {
- di.readFully(b, 0, 4);
- return ((b[0] & 0xff) | (b[1] & 0xff) << 8)
- | ((b[2] & 0xff) | (b[3] & 0xff) << 8) << 16;
- }
-
- /**
- * Read an unsigned short in little endian byte order from the given
- * byte buffer at the given offset.
- *
- * @param b the byte array to read from.
- * @param off the offset to read from.
- * @return The value read.
- */
- private int readLeShort(byte[] b, int off)
- {
- return (b[off] & 0xff) | (b[off+1] & 0xff) << 8;
- }
-
- /**
- * Read an int in little endian byte order from the given
- * byte buffer at the given offset.
- *
- * @param b the byte array to read from.
- * @param off the offset to read from.
- * @return The value read.
- */
- private int readLeInt(byte[] b, int off)
- {
- return ((b[off] & 0xff) | (b[off+1] & 0xff) << 8)
- | ((b[off+2] & 0xff) | (b[off+3] & 0xff) << 8) << 16;
- }
-
-
- /**
* Read the central directory of a zip file and fill the entries
* array. This is called exactly once when first needed. It is called
* while holding the lock on <code>raf</code>.
@@ -246,63 +191,48 @@ public class ZipFile implements ZipConstants
{
/* Search for the End Of Central Directory. When a zip comment is
* present the directory may start earlier.
- * FIXME: This searches the whole file in a very slow manner if the
- * file isn't a zip file.
+ * Note that a comment has a maximum length of 64K, so that is the
+ * maximum we search backwards.
*/
+ PartialInputStream inp = new PartialInputStream(raf, 4096);
long pos = raf.length() - ENDHDR;
- byte[] ebs = new byte[CENHDR];
-
+ long top = Math.max(0, pos - 65536);
do
{
- if (pos < 0)
+ if (pos < top)
throw new ZipException
("central directory not found, probably not a zip file: " + name);
- raf.seek(pos--);
+ inp.seek(pos--);
}
- while (readLeInt(raf, ebs) != ENDSIG);
+ while (inp.readLeInt() != ENDSIG);
- if (raf.skipBytes(ENDTOT - ENDNRD) != ENDTOT - ENDNRD)
+ if (inp.skip(ENDTOT - ENDNRD) != ENDTOT - ENDNRD)
throw new EOFException(name);
- int count = readLeShort(raf, ebs);
- if (raf.skipBytes(ENDOFF - ENDSIZ) != ENDOFF - ENDSIZ)
+ int count = inp.readLeShort();
+ if (inp.skip(ENDOFF - ENDSIZ) != ENDOFF - ENDSIZ)
throw new EOFException(name);
- int centralOffset = readLeInt(raf, ebs);
+ int centralOffset = inp.readLeInt();
entries = new HashMap(count+count/2);
- raf.seek(centralOffset);
+ inp.seek(centralOffset);
- byte[] buffer = new byte[16];
for (int i = 0; i < count; i++)
{
- raf.readFully(ebs);
- if (readLeInt(ebs, 0) != CENSIG)
+ if (inp.readLeInt() != CENSIG)
throw new ZipException("Wrong Central Directory signature: " + name);
- int method = readLeShort(ebs, CENHOW);
- int dostime = readLeInt(ebs, CENTIM);
- int crc = readLeInt(ebs, CENCRC);
- int csize = readLeInt(ebs, CENSIZ);
- int size = readLeInt(ebs, CENLEN);
- int nameLen = readLeShort(ebs, CENNAM);
- int extraLen = readLeShort(ebs, CENEXT);
- int commentLen = readLeShort(ebs, CENCOM);
-
- int offset = readLeInt(ebs, CENOFF);
-
- int needBuffer = Math.max(nameLen, commentLen);
- if (buffer.length < needBuffer)
- buffer = new byte[needBuffer];
-
- raf.readFully(buffer, 0, nameLen);
- String name;
- try
- {
- name = new String(buffer, 0, nameLen, "UTF-8");
- }
- catch (UnsupportedEncodingException uee)
- {
- throw new AssertionError(uee);
- }
+ inp.skip(6);
+ int method = inp.readLeShort();
+ int dostime = inp.readLeInt();
+ int crc = inp.readLeInt();
+ int csize = inp.readLeInt();
+ int size = inp.readLeInt();
+ int nameLen = inp.readLeShort();
+ int extraLen = inp.readLeShort();
+ int commentLen = inp.readLeShort();
+ inp.skip(8);
+ int offset = inp.readLeInt();
+ String name = inp.readString(nameLen);
ZipEntry entry = new ZipEntry(name);
entry.setMethod(method);
@@ -313,20 +243,12 @@ public class ZipFile implements ZipConstants
if (extraLen > 0)
{
byte[] extra = new byte[extraLen];
- raf.readFully(extra);
+ inp.readFully(extra);
entry.setExtra(extra);
}
if (commentLen > 0)
{
- raf.readFully(buffer, 0, commentLen);
- try
- {
- entry.setComment(new String(buffer, 0, commentLen, "UTF-8"));
- }
- catch (UnsupportedEncodingException uee)
- {
- throw new AssertionError(uee);
- }
+ entry.setComment(inp.readString(commentLen));
}
entry.offset = offset;
entries.put(name, entry);
@@ -429,42 +351,6 @@ public class ZipFile implements ZipConstants
}
}
-
- //access should be protected by synchronized(raf)
- private byte[] locBuf = new byte[LOCHDR];
-
- /**
- * Checks, if the local header of the entry at index i matches the
- * central directory, and returns the offset to the data.
- *
- * @param entry to check.
- * @return the start offset of the (compressed) data.
- *
- * @exception IOException if a i/o error occured.
- * @exception ZipException if the local header doesn't match the
- * central directory header
- */
- private long checkLocalHeader(ZipEntry entry) throws IOException
- {
- synchronized (raf)
- {
- raf.seek(entry.offset);
- raf.readFully(locBuf);
-
- if (readLeInt(locBuf, 0) != LOCSIG)
- throw new ZipException("Wrong Local header signature: " + name);
-
- if (entry.getMethod() != readLeShort(locBuf, LOCHOW))
- throw new ZipException("Compression method mismatch: " + name);
-
- if (entry.getName().length() != readLeShort(locBuf, LOCNAM))
- throw new ZipException("file name length mismatch: " + name);
-
- int extraLen = entry.getName().length() + readLeShort(locBuf, LOCEXT);
- return entry.offset + LOCHDR + extraLen;
- }
- }
-
/**
* Creates an input stream reading the given zip entry as
* uncompressed data. Normally zip entry should be an entry
@@ -497,16 +383,32 @@ public class ZipFile implements ZipConstants
if (zipEntry == null)
return null;
- long start = checkLocalHeader(zipEntry);
+ PartialInputStream inp = new PartialInputStream(raf, 1024);
+ inp.seek(zipEntry.offset);
+
+ if (inp.readLeInt() != LOCSIG)
+ throw new ZipException("Wrong Local header signature: " + name);
+
+ inp.skip(4);
+
+ if (zipEntry.getMethod() != inp.readLeShort())
+ throw new ZipException("Compression method mismatch: " + name);
+
+ inp.skip(16);
+
+ int nameLen = inp.readLeShort();
+ int extraLen = inp.readLeShort();
+ inp.skip(nameLen + extraLen);
+
+ inp.setLength(zipEntry.getCompressedSize());
+
int method = zipEntry.getMethod();
- InputStream is = new BufferedInputStream(new PartialInputStream
- (raf, start, zipEntry.getCompressedSize()));
switch (method)
{
case ZipOutputStream.STORED:
- return is;
+ return inp;
case ZipOutputStream.DEFLATED:
- return new InflaterInputStream(is, new Inflater(true));
+ return new InflaterInputStream(inp, new Inflater(true));
default:
throw new ZipException("Unknown compression method " + method);
}
@@ -562,21 +464,41 @@ public class ZipFile implements ZipConstants
}
}
- private static class PartialInputStream extends InputStream
+ private static final class PartialInputStream extends InputStream
{
private final RandomAccessFile raf;
- long filepos, end;
+ private final byte[] buffer;
+ private long bufferOffset;
+ private int pos;
+ private long end;
- public PartialInputStream(RandomAccessFile raf, long start, long len)
+ public PartialInputStream(RandomAccessFile raf, int bufferSize)
+ throws IOException
{
this.raf = raf;
- filepos = start;
- end = start + len;
+ buffer = new byte[bufferSize];
+ bufferOffset = -buffer.length;
+ pos = buffer.length;
+ end = raf.length();
+ }
+
+ void setLength(long length)
+ {
+ end = bufferOffset + pos + length;
+ }
+
+ private void fillBuffer() throws IOException
+ {
+ synchronized (raf)
+ {
+ raf.seek(bufferOffset);
+ raf.readFully(buffer, 0, (int) Math.min(buffer.length, end - bufferOffset));
+ }
}
public int available()
{
- long amount = end - filepos;
+ long amount = end - (bufferOffset + pos);
if (amount > Integer.MAX_VALUE)
return Integer.MAX_VALUE;
return (int) amount;
@@ -584,41 +506,130 @@ public class ZipFile implements ZipConstants
public int read() throws IOException
{
- if (filepos == end)
+ if (bufferOffset + pos >= end)
return -1;
- synchronized (raf)
- {
- raf.seek(filepos++);
- return raf.read();
- }
+ if (pos == buffer.length)
+ {
+ bufferOffset += buffer.length;
+ pos = 0;
+ fillBuffer();
+ }
+ return buffer[pos++] & 0xFF;
}
public int read(byte[] b, int off, int len) throws IOException
{
- if (len > end - filepos)
+ if (len > end - (bufferOffset + pos))
{
- len = (int) (end - filepos);
+ len = (int) (end - (bufferOffset + pos));
if (len == 0)
return -1;
}
- synchronized (raf)
- {
- raf.seek(filepos);
- int count = raf.read(b, off, len);
- if (count > 0)
- filepos += len;
- return count;
- }
+
+ int totalBytesRead = Math.min(buffer.length - pos, len);
+ System.arraycopy(buffer, pos, b, off, totalBytesRead);
+ pos += totalBytesRead;
+ off += totalBytesRead;
+ len -= totalBytesRead;
+
+ while (len > 0)
+ {
+ bufferOffset += buffer.length;
+ pos = 0;
+ fillBuffer();
+ int remain = Math.min(buffer.length, len);
+ System.arraycopy(buffer, pos, b, off, remain);
+ pos += remain;
+ off += remain;
+ len -= remain;
+ totalBytesRead += remain;
+ }
+
+ return totalBytesRead;
}
- public long skip(long amount)
+ public long skip(long amount) throws IOException
{
if (amount < 0)
- throw new IllegalArgumentException();
- if (amount > end - filepos)
- amount = end - filepos;
- filepos += amount;
+ return 0;
+ if (amount > end - (bufferOffset + pos))
+ amount = end - (bufferOffset + pos);
+ seek(bufferOffset + pos + amount);
return amount;
}
+
+ void seek(long newpos) throws IOException
+ {
+ long offset = newpos - bufferOffset;
+ if (offset >= 0 && offset <= buffer.length)
+ {
+ pos = (int) offset;
+ }
+ else
+ {
+ bufferOffset = newpos;
+ pos = 0;
+ fillBuffer();
+ }
+ }
+
+ void readFully(byte[] buf) throws IOException
+ {
+ if (read(buf, 0, buf.length) != buf.length)
+ throw new EOFException();
+ }
+
+ void readFully(byte[] buf, int off, int len) throws IOException
+ {
+ if (read(buf, off, len) != len)
+ throw new EOFException();
+ }
+
+ int readLeShort() throws IOException
+ {
+ int b0 = read();
+ int b1 = read();
+ if (b1 == -1)
+ throw new EOFException();
+ return (b0 & 0xff) | (b1 & 0xff) << 8;
+ }
+
+ int readLeInt() throws IOException
+ {
+ int b0 = read();
+ int b1 = read();
+ int b2 = read();
+ int b3 = read();
+ if (b3 == -1)
+ throw new EOFException();
+ return ((b0 & 0xff) | (b1 & 0xff) << 8)
+ | ((b2 & 0xff) | (b3 & 0xff) << 8) << 16;
+ }
+
+ String readString(int length) throws IOException
+ {
+ if (length > end - (bufferOffset + pos))
+ throw new EOFException();
+
+ try
+ {
+ if (buffer.length - pos >= length)
+ {
+ String s = new String(buffer, pos, length, "UTF-8");
+ pos += length;
+ return s;
+ }
+ else
+ {
+ byte[] b = new byte[length];
+ readFully(b);
+ return new String(b, 0, length, "UTF-8");
+ }
+ }
+ catch (UnsupportedEncodingException uee)
+ {
+ throw new AssertionError(uee);
+ }
+ }
}
}
diff --git a/libjava/classpath/java/util/zip/ZipOutputStream.java b/libjava/classpath/java/util/zip/ZipOutputStream.java
index 5c593b2..d292f7d 100644
--- a/libjava/classpath/java/util/zip/ZipOutputStream.java
+++ b/libjava/classpath/java/util/zip/ZipOutputStream.java
@@ -1,5 +1,5 @@
/* ZipOutputStream.java --
- Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -161,6 +161,16 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant
}
/**
+ * Write a long value as an int. Some of the zip constants
+ * are declared as longs even though they fit perfectly well
+ * into integers.
+ */
+ private void writeLeInt(long value) throws IOException
+ {
+ writeLeInt((int) value);
+ }
+
+ /**
* Starts a new Zip entry. It automatically closes the previous
* entry if present. If the compression method is stored, the entry
* must have a valid size and crc, otherwise all elements (except