aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/java/io
diff options
context:
space:
mode:
authorTom Tromey <tromey@gcc.gnu.org>2007-01-09 19:58:05 +0000
committerTom Tromey <tromey@gcc.gnu.org>2007-01-09 19:58:05 +0000
commit97b8365cafc3a344a22d3980b8ed885f5c6d8357 (patch)
tree996a5f57d4a68c53473382e45cb22f574cb3e4db /libjava/classpath/java/io
parentc648dedbde727ca3f883bb5fd773aa4af70d3369 (diff)
downloadgcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.zip
gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.gz
gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.bz2
Merged gcj-eclipse branch to trunk.
From-SVN: r120621
Diffstat (limited to 'libjava/classpath/java/io')
-rw-r--r--libjava/classpath/java/io/CharArrayWriter.java6
-rw-r--r--libjava/classpath/java/io/DeleteFileHelper.java13
-rw-r--r--libjava/classpath/java/io/File.java107
-rw-r--r--libjava/classpath/java/io/FileDescriptor.java7
-rw-r--r--libjava/classpath/java/io/FileInputStream.java20
-rw-r--r--libjava/classpath/java/io/FileOutputStream.java26
-rw-r--r--libjava/classpath/java/io/InputStreamReader.java62
-rw-r--r--libjava/classpath/java/io/ObjectInputStream.java136
-rw-r--r--libjava/classpath/java/io/ObjectOutputStream.java365
-rw-r--r--libjava/classpath/java/io/ObjectStreamClass.java463
-rw-r--r--libjava/classpath/java/io/ObjectStreamField.java47
-rw-r--r--libjava/classpath/java/io/OutputStreamWriter.java6
-rw-r--r--libjava/classpath/java/io/PipedInputStream.java4
-rw-r--r--libjava/classpath/java/io/PipedReader.java4
-rw-r--r--libjava/classpath/java/io/PrintStream.java56
-rw-r--r--libjava/classpath/java/io/PrintWriter.java52
-rw-r--r--libjava/classpath/java/io/RandomAccessFile.java19
-rw-r--r--libjava/classpath/java/io/Reader.java19
-rw-r--r--libjava/classpath/java/io/SequenceInputStream.java26
-rw-r--r--libjava/classpath/java/io/StringWriter.java21
-rw-r--r--libjava/classpath/java/io/Writer.java23
-rw-r--r--libjava/classpath/java/io/class-dependencies.conf100
22 files changed, 897 insertions, 685 deletions
diff --git a/libjava/classpath/java/io/CharArrayWriter.java b/libjava/classpath/java/io/CharArrayWriter.java
index 68e693b..0eead3a 100644
--- a/libjava/classpath/java/io/CharArrayWriter.java
+++ b/libjava/classpath/java/io/CharArrayWriter.java
@@ -267,7 +267,7 @@ public class CharArrayWriter extends Writer
* sequence is wrapped around an input buffer, the results will
* depend on the current position and length of that buffer.
*
- * @param cs the character sequence to append. If cs is null,
+ * @param seq the character sequence to append. If seq is null,
* then the string "null" (the string representation of null)
* is appended.
* @return a reference to this object.
@@ -291,10 +291,10 @@ public class CharArrayWriter extends Writer
* output stream underlying this writer, starting and ending at the
* specified positions within the sequence. The behaviour of this
* method matches the behaviour of writing the result of
- * <code>append(cs.subSequence(start,end))</code> when the sequence
+ * <code>append(seq.subSequence(start,end))</code> when the sequence
* is not null.
*
- * @param cs the character sequence to append. If cs is null,
+ * @param seq the character sequence to append. If seq is null,
* then the string "null" (the string representation of null)
* is appended.
* @param start the index of the first Unicode character to use from
diff --git a/libjava/classpath/java/io/DeleteFileHelper.java b/libjava/classpath/java/io/DeleteFileHelper.java
index d73628c..6e33adc 100644
--- a/libjava/classpath/java/io/DeleteFileHelper.java
+++ b/libjava/classpath/java/io/DeleteFileHelper.java
@@ -1,5 +1,5 @@
/* DeleteFileHelper.java -- Helper class to delete files on VM exit
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,22 +40,22 @@ package java.io;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
-import java.util.Iterator;
/**
* @author Guilhem Lavaux (guilhem@kaffe.org)
* @author Jeroen Frijters (jeroen@sumatra.nl)
* @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
final class DeleteFileHelper extends Thread
{
- private static ArrayList filesToDelete;
+ private static ArrayList<File> filesToDelete;
static synchronized void add(File file)
{
if (filesToDelete == null)
{
- filesToDelete = new ArrayList();
+ filesToDelete = new ArrayList<File>();
AccessController.doPrivileged(new PrivilegedAction()
{
@@ -81,13 +81,10 @@ final class DeleteFileHelper extends Thread
private static synchronized void deleteFiles()
{
- Iterator it = filesToDelete.iterator();
-
- while (it.hasNext())
+ for (File file : filesToDelete)
{
try
{
- File file = (File) it.next();
file.delete();
}
catch (Exception e)
diff --git a/libjava/classpath/java/io/File.java b/libjava/classpath/java/io/File.java
index ce56876..5d1b3ec 100644
--- a/libjava/classpath/java/io/File.java
+++ b/libjava/classpath/java/io/File.java
@@ -60,7 +60,7 @@ import java.net.URL;
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
*/
-public class File implements Serializable, Comparable
+public class File implements Serializable, Comparable<File>
{
private static final long serialVersionUID = 301077366599181567L;
@@ -286,7 +286,8 @@ public class File implements Serializable, Comparable
// example, is a valid and minimal path).
if (plen > 1 && p.charAt (plen - 1) == separatorChar)
{
- if (! (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':'))
+ if (! (separatorChar == '\\' && ((plen == 3 && p.charAt(1) == ':')
+ || (plen == 2 && p.charAt(0) == separatorChar))))
return p.substring (0, plen - 1);
}
else
@@ -303,7 +304,16 @@ public class File implements Serializable, Comparable
{
dupIndex++;
if (dupIndex == plen)
- return newpath.toString();
+ {
+ if ((separatorChar == '\\'
+ && newpath.length() == 2
+ && newpath.charAt(1) == ':')
+ || (separatorChar != '\\' && newpath.length() == 0))
+ {
+ newpath.append(separatorChar);
+ }
+ return newpath.toString();
+ }
}
newpath.append(separatorChar);
last = dupIndex;
@@ -315,7 +325,9 @@ public class File implements Serializable, Comparable
int end;
if (plen > 1 && p.charAt (plen - 1) == separatorChar)
{
- if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')
+ if (separatorChar == '\\'
+ && ((plen == 3 && p.charAt(1) == ':')
+ || (plen == 2 && p.charAt(0) == separatorChar)))
end = plen;
else
end = plen - 1;
@@ -427,45 +439,8 @@ public class File implements Serializable, Comparable
{
if (isAbsolute())
return path;
- else if (separatorChar == '\\'
- && path.length() > 0 && path.charAt (0) == '\\')
- {
- // On Windows, even if the path starts with a '\\' it is not
- // really absolute until we prefix the drive specifier from
- // the current working directory to it.
- return System.getProperty ("user.dir").substring (0, 2) + path;
- }
- else if (separatorChar == '\\'
- && path.length() > 1 && path.charAt (1) == ':'
- && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
- || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')))
- {
- // On Windows, a process has a current working directory for
- // each drive and a path like "G:foo\bar" would mean the
- // absolute path "G:\wombat\foo\bar" if "\wombat" is the
- // working directory on the G drive.
- String drvDir = null;
- try
- {
- drvDir = new File (path.substring (0, 2)).getCanonicalPath();
- }
- catch (IOException e)
- {
- drvDir = path.substring (0, 2) + "\\";
- }
-
- // Note: this would return "C:\\." for the path "C:.", if "\"
- // is the working folder on the C drive, but this is
- // consistent with what Sun's JRE 1.4.1.01 actually returns!
- if (path.length() > 2)
- return drvDir + '\\' + path.substring (2, path.length());
- else
- return drvDir;
- }
- else if (path.equals(""))
- return System.getProperty ("user.dir");
else
- return System.getProperty ("user.dir") + separatorChar + path;
+ return VMFile.getAbsolutePath(path);
}
/**
@@ -657,15 +632,7 @@ public class File implements Serializable, Comparable
*/
public boolean isAbsolute()
{
- if (separatorChar == '\\')
- return path.startsWith(dupSeparator) ||
- (path.length() > 2 &&
- ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') ||
- (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) &&
- path.charAt(1) == ':' &&
- path.charAt(2) == '\\');
- else
- return path.startsWith(separator);
+ return VMFile.isAbsolute(path);
}
/**
@@ -787,8 +754,9 @@ public class File implements Serializable, Comparable
String files[] = VMFile.list(path);
// Check if an error occured in listInternal().
+ // This is an unreadable directory, pretend there is nothing inside.
if (files == null)
- return null;
+ return new String[0];
if (filter == null)
return files;
@@ -998,14 +966,7 @@ public class File implements Serializable, Comparable
*/
public URL toURL() throws MalformedURLException
{
- // On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt",
- // while on UNIX, it returns URLs of the form "file:/foo/bar.txt".
- if (separatorChar == '\\')
- return new URL ("file:/" + getAbsolutePath().replace ('\\', '/')
- + (isDirectory() ? "/" : ""));
- else
- return new URL ("file:" + getAbsolutePath()
- + (isDirectory() ? "/" : ""));
+ return VMFile.toURL(this);
}
@@ -1292,32 +1253,6 @@ public class File implements Serializable, Comparable
}
/**
- * This method compares the specified <code>Object</code> to this one
- * to test for equality. It does this by comparing the canonical path names
- * of the files. This method is identical to <code>compareTo(File)</code>
- * except that if the <code>Object</code> passed to it is not a
- * <code>File</code>, it throws a <code>ClassCastException</code>
- * <p>
- * The canonical paths of the files are determined by calling the
- * <code>getCanonicalPath</code> method on each object.
- * <p>
- * This method returns a 0 if the specified <code>Object</code> is equal
- * to this one, a negative value if it is less than this one
- * a positive value if it is greater than this one.
- *
- * @return An integer as described above
- *
- * @exception ClassCastException If the passed <code>Object</code> is
- * not a <code>File</code>
- *
- * @since 1.2
- */
- public int compareTo(Object obj)
- {
- return compareTo((File) obj);
- }
-
- /**
* This method renames the file represented by this object to the path
* of the file represented by the argument <code>File</code>.
*
diff --git a/libjava/classpath/java/io/FileDescriptor.java b/libjava/classpath/java/io/FileDescriptor.java
index d300c9c..cf9ff20 100644
--- a/libjava/classpath/java/io/FileDescriptor.java
+++ b/libjava/classpath/java/io/FileDescriptor.java
@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
import java.nio.channels.ByteChannel;
import java.nio.channels.FileChannel;
@@ -133,7 +133,8 @@ public final class FileDescriptor
* native file handle, <code>false</code> otherwise
*/
public boolean valid ()
- {
- return channel != null && channel.isOpen();
+ {
+ ByteChannel c = channel;
+ return (c != null) && (c.isOpen());
}
}
diff --git a/libjava/classpath/java/io/FileInputStream.java b/libjava/classpath/java/io/FileInputStream.java
index 8ca38b0..8217668 100644
--- a/libjava/classpath/java/io/FileInputStream.java
+++ b/libjava/classpath/java/io/FileInputStream.java
@@ -38,8 +38,9 @@ exception statement from your version. */
package java.io;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
+import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
@@ -107,7 +108,20 @@ public class FileInputStream extends InputStream
if (s != null)
s.checkRead(file.getPath());
- ch = FileChannelImpl.create(file, FileChannelImpl.READ);
+ try
+ {
+ ch = FileChannelImpl.create(file, FileChannelImpl.READ);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ throw fnfe;
+ }
+ catch (IOException ioe)
+ {
+ FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
+ fnfe.initCause(ioe);
+ throw fnfe;
+ }
}
/**
@@ -266,7 +280,7 @@ public class FileInputStream extends InputStream
|| offset + len > buf.length)
throw new ArrayIndexOutOfBoundsException();
- return ch.read(buf, offset, len);
+ return ch.read(ByteBuffer.wrap(buf, offset, len));
}
/**
diff --git a/libjava/classpath/java/io/FileOutputStream.java b/libjava/classpath/java/io/FileOutputStream.java
index 10ea6b5..d7561a9 100644
--- a/libjava/classpath/java/io/FileOutputStream.java
+++ b/libjava/classpath/java/io/FileOutputStream.java
@@ -38,8 +38,9 @@ exception statement from your version. */
package java.io;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
+import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
@@ -155,10 +156,23 @@ public class FileOutputStream extends OutputStream
if (s != null)
s.checkWrite(file.getPath());
- ch = FileChannelImpl.create(file, (append
- ? FileChannelImpl.WRITE
- | FileChannelImpl.APPEND
- : FileChannelImpl.WRITE));
+ try
+ {
+ ch = FileChannelImpl.create(file, (append
+ ? FileChannelImpl.WRITE
+ | FileChannelImpl.APPEND
+ : FileChannelImpl.WRITE));
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ throw fnfe;
+ }
+ catch (IOException ioe)
+ {
+ FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
+ fnfe.initCause(ioe);
+ throw fnfe;
+ }
}
/**
@@ -266,7 +280,7 @@ public class FileOutputStream extends OutputStream
|| offset + len > buf.length)
throw new ArrayIndexOutOfBoundsException ();
- ch.write (buf, offset, len);
+ ch.write(ByteBuffer.wrap(buf, offset, len));
}
/**
diff --git a/libjava/classpath/java/io/InputStreamReader.java b/libjava/classpath/java/io/InputStreamReader.java
index 936a03c..6c5297f 100644
--- a/libjava/classpath/java/io/InputStreamReader.java
+++ b/libjava/classpath/java/io/InputStreamReader.java
@@ -135,6 +135,16 @@ public class InputStreamReader extends Reader
private boolean hasSavedSurrogate = false;
/**
+ * A byte array to be reused in read(byte[], int, int).
+ */
+ private byte[] bytesCache;
+
+ /**
+ * Locks the bytesCache above in read(byte[], int, int).
+ */
+ private Object cacheLock = new Object();
+
+ /**
* This method initializes a new instance of <code>InputStreamReader</code>
* to read from the specified stream using the default encoding.
*
@@ -355,9 +365,21 @@ public class InputStreamReader extends Reader
throw new IOException("Reader has been closed");
if (isDone)
return -1;
- if(decoder != null){
- int totalBytes = (int)((double)length * maxBytesPerChar);
- byte[] bytes = new byte[totalBytes];
+ if(decoder != null)
+ {
+ int totalBytes = (int)((double) length * maxBytesPerChar);
+ if (byteBuffer != null)
+ totalBytes = Math.max(totalBytes, byteBuffer.remaining());
+ byte[] bytes;
+ // Fetch cached bytes array if available and big enough.
+ synchronized(cacheLock)
+ {
+ bytes = bytesCache;
+ if (bytes == null || bytes.length < totalBytes)
+ bytes = new byte[totalBytes];
+ else
+ bytesCache = null;
+ }
int remaining = 0;
if(byteBuffer != null)
@@ -410,12 +432,40 @@ public class InputStreamReader extends Reader
byteBuffer = null;
read = cb.position() - startPos;
- return (read <= 0) ? -1 : read;
- } else {
- byte[] bytes = new byte[length];
+
+ // Put cached bytes array back if we are finished and the cache
+ // is null or smaller than the used bytes array.
+ synchronized (cacheLock)
+ {
+ if (byteBuffer == null
+ && (bytesCache == null || bytesCache.length < bytes.length))
+ bytesCache = bytes;
+ }
+ return (read <= 0) ? -1 : read;
+ }
+ else
+ {
+ byte[] bytes;
+ // Fetch cached bytes array if available and big enough.
+ synchronized (cacheLock)
+ {
+ bytes = bytesCache;
+ if (bytes == null || length < bytes.length)
+ bytes = new byte[length];
+ else
+ bytesCache = null;
+ }
+
int read = in.read(bytes);
for(int i=0;i<read;i++)
buf[offset+i] = (char)(bytes[i]&0xFF);
+
+ // Put back byte array into cache if appropriate.
+ synchronized (cacheLock)
+ {
+ if (bytesCache == null || bytesCache.length < bytes.length)
+ bytesCache = bytes;
+ }
return read;
}
}
diff --git a/libjava/classpath/java/io/ObjectInputStream.java b/libjava/classpath/java/io/ObjectInputStream.java
index a37ad73..d6c1406 100644
--- a/libjava/classpath/java/io/ObjectInputStream.java
+++ b/libjava/classpath/java/io/ObjectInputStream.java
@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
-import gnu.java.io.ObjectIdentityWrapper;
+import gnu.classpath.VMStackWalker;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
@@ -55,6 +55,13 @@ import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
public class ObjectInputStream extends InputStream
implements ObjectInput, ObjectStreamConstants
{
@@ -97,8 +104,8 @@ public class ObjectInputStream extends InputStream
this.blockDataInput = new DataInputStream(this);
this.realInputStream = new DataInputStream(in);
this.nextOID = baseWireHandle;
- this.objectLookupTable = new Hashtable();
- this.classLookupTable = new Hashtable();
+ this.objectLookupTable = new Vector<Object>();
+ this.classLookupTable = new Hashtable<Class,ObjectStreamClass>();
setBlockDataMode(true);
readStreamHeader();
}
@@ -197,10 +204,9 @@ public class ObjectInputStream extends InputStream
case TC_REFERENCE:
{
if(dump) dumpElement("REFERENCE ");
- Integer oid = new Integer(this.realInputStream.readInt());
- if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
- ret_val = ((ObjectIdentityWrapper)
- this.objectLookupTable.get(oid)).object;
+ int oid = realInputStream.readInt();
+ if(dump) dumpElementln(Integer.toHexString(oid));
+ ret_val = lookupHandle(oid);
break;
}
@@ -348,12 +354,12 @@ public class ObjectInputStream extends InputStream
int handle = assignNewHandle(obj);
Object prevObject = this.currentObject;
ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
- TreeSet prevObjectValidators = this.currentObjectValidators;
+ TreeSet<ValidatorAndPriority> prevObjectValidators =
+ this.currentObjectValidators;
this.currentObject = obj;
this.currentObjectValidators = null;
- ObjectStreamClass[] hierarchy =
- inputGetObjectStreamClasses(clazz);
+ ObjectStreamClass[] hierarchy = hierarchy(clazz);
for (int i = 0; i < hierarchy.length; i++)
{
@@ -539,8 +545,6 @@ public class ObjectInputStream extends InputStream
flags, fields);
assignNewHandle(osc);
- ClassLoader callersClassLoader = currentLoader();
-
for (int i = 0; i < field_count; i++)
{
if(dump) dumpElement(" TYPE CODE=");
@@ -560,12 +564,17 @@ public class ObjectInputStream extends InputStream
class_name = String.valueOf(type_code);
fields[i] =
- new ObjectStreamField(field_name, class_name, callersClassLoader);
+ new ObjectStreamField(field_name, class_name);
}
/* Now that fields have been read we may resolve the class
* (and read annotation if needed). */
Class clazz = resolveClass(osc);
+ ClassLoader loader = clazz.getClassLoader();
+ for (int i = 0; i < field_count; i++)
+ {
+ fields[i].resolveType(loader);
+ }
boolean oldmode = setBlockDataMode(true);
osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
classLookupTable.put(clazz, osc);
@@ -753,7 +762,7 @@ public class ObjectInputStream extends InputStream
+ "ObjectInputValidation object");
if (currentObjectValidators == null)
- currentObjectValidators = new TreeSet();
+ currentObjectValidators = new TreeSet<ValidatorAndPriority>();
currentObjectValidators.add(new ValidatorAndPriority(validator, priority));
}
@@ -775,7 +784,7 @@ public class ObjectInputStream extends InputStream
*
* @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
*/
- protected Class resolveClass(ObjectStreamClass osc)
+ protected Class<?> resolveClass(ObjectStreamClass osc)
throws ClassNotFoundException, IOException
{
String name = osc.getName();
@@ -814,7 +823,7 @@ public class ObjectInputStream extends InputStream
*/
private ClassLoader currentLoader()
{
- return VMObjectInputStream.currentClassLoader();
+ return VMStackWalker.firstNonNullClassLoader();
}
/**
@@ -842,41 +851,20 @@ public class ObjectInputStream extends InputStream
}
/**
- * Reconstruct class hierarchy the same way
- * {@link java.io.ObjectStreamClass#getObjectStreamClasses(Class)} does
- * but using lookupClass instead of ObjectStreamClass.lookup. This
- * dup is necessary localize the lookup table. Hopefully some future
- * rewritings will be able to prevent this.
+ * Reconstruct class hierarchy the same way {@link
+ * java.io.ObjectStreamClass#hierarchy} does but using lookupClass
+ * instead of ObjectStreamClass.lookup.
*
* @param clazz This is the class for which we want the hierarchy.
*
* @return An array of valid {@link java.io.ObjectStreamClass} instances which
* represent the class hierarchy for clazz.
*/
- private ObjectStreamClass[] inputGetObjectStreamClasses(Class clazz)
- {
+ private ObjectStreamClass[] hierarchy(Class clazz)
+ {
ObjectStreamClass osc = lookupClass(clazz);
- if (osc == null)
- return new ObjectStreamClass[0];
- else
- {
- Vector oscs = new Vector();
-
- while (osc != null)
- {
- oscs.addElement(osc);
- osc = osc.getSuper();
- }
-
- int count = oscs.size();
- ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[count];
-
- for (int i = count - 1; i >= 0; i--)
- sorted_oscs[count - i - 1] = (ObjectStreamClass) oscs.elementAt(i);
-
- return sorted_oscs;
- }
+ return osc == null ? new ObjectStreamClass[0] : osc.hierarchy();
}
/**
@@ -898,12 +886,12 @@ public class ObjectInputStream extends InputStream
}
- protected Class resolveProxyClass(String[] intfs)
+ protected Class<?> resolveProxyClass(String[] intfs)
throws IOException, ClassNotFoundException
{
ClassLoader cl = currentLoader();
- Class[] clss = new Class[intfs.length];
+ Class<?>[] clss = new Class<?>[intfs.length];
if(cl == null)
{
for (int i = 0; i < intfs.length; i++)
@@ -1560,9 +1548,47 @@ public class ObjectInputStream extends InputStream
*/
private int assignNewHandle(Object obj)
{
- this.objectLookupTable.put(new Integer(this.nextOID),
- new ObjectIdentityWrapper(obj));
- return this.nextOID++;
+ int handle = this.nextOID;
+ this.nextOID = handle + 1;
+ rememberHandle(obj,handle);
+ return handle;
+ }
+
+ /**
+ * Remember the object associated with the given handle.
+ *
+ * @param obj an object
+ *
+ * @param handle a handle, must be >= baseWireHandle
+ *
+ * @see #lookupHandle
+ */
+ private void rememberHandle(Object obj, int handle)
+ {
+ Vector olt = this.objectLookupTable;
+ handle = handle - baseWireHandle;
+
+ if (olt.size() <= handle)
+ olt.setSize(handle + 1);
+
+ olt.set(handle, obj);
+ }
+
+ /**
+ * Look up the object associated with a given handle.
+ *
+ * @param handle a handle, must be >= baseWireHandle
+ *
+ * @return the object remembered for handle or null if none.
+ *
+ * @see #rememberHandle
+ */
+ private Object lookupHandle(int handle)
+ {
+ Vector olt = this.objectLookupTable;
+ handle = handle - baseWireHandle;
+ Object result = handle < olt.size() ? olt.get(handle) : null;
+ return result;
}
private Object processResolution(ObjectStreamClass osc, Object obj, int handle)
@@ -1596,9 +1622,7 @@ public class ObjectInputStream extends InputStream
if (this.resolveEnabled)
obj = resolveObject(obj);
- this.objectLookupTable.put(new Integer(handle),
- new ObjectIdentityWrapper(obj));
-
+ rememberHandle(obj, handle);
return obj;
}
@@ -1875,10 +1899,10 @@ public class ObjectInputStream extends InputStream
{
try
{
- Iterator it = currentObjectValidators.iterator();
+ Iterator<ValidatorAndPriority> it = currentObjectValidators.iterator();
while(it.hasNext())
{
- ValidatorAndPriority vap = (ValidatorAndPriority) it.next();
+ ValidatorAndPriority vap = it.next();
ObjectInputValidation validator = vap.validator;
validator.validateObject();
}
@@ -1931,13 +1955,13 @@ public class ObjectInputStream extends InputStream
private boolean useSubclassMethod;
private int nextOID;
private boolean resolveEnabled;
- private Hashtable objectLookupTable;
+ private Vector<Object> objectLookupTable;
private Object currentObject;
private ObjectStreamClass currentObjectStreamClass;
- private TreeSet currentObjectValidators;
+ private TreeSet<ValidatorAndPriority> currentObjectValidators;
private boolean readDataFromBlock;
private boolean fieldsAlreadyRead;
- private Hashtable classLookupTable;
+ private Hashtable<Class,ObjectStreamClass> classLookupTable;
private GetField prereadFields;
private static boolean dump;
diff --git a/libjava/classpath/java/io/ObjectOutputStream.java b/libjava/classpath/java/io/ObjectOutputStream.java
index 80d196b..c3c3df9 100644
--- a/libjava/classpath/java/io/ObjectOutputStream.java
+++ b/libjava/classpath/java/io/ObjectOutputStream.java
@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
-import gnu.java.io.ObjectIdentityWrapper;
+import gnu.java.io.ObjectIdentityMap2Int;
import gnu.java.lang.reflect.TypeSignature;
import gnu.java.security.action.SetAccessibleAction;
@@ -47,8 +47,7 @@ import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.util.Hashtable;
+
/**
* An <code>ObjectOutputStream</code> can be used to write objects
@@ -115,6 +114,11 @@ import java.util.Hashtable;
* @see java.io.Externalizable
* @see java.io.ObjectInputStream
* @see java.io.Serializable
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
public class ObjectOutputStream extends OutputStream
implements ObjectOutput, ObjectStreamConstants
@@ -140,7 +144,7 @@ public class ObjectOutputStream extends OutputStream
replacementEnabled = false;
isSerializing = false;
nextOID = baseWireHandle;
- OIDLookupTable = new Hashtable();
+ OIDLookupTable = new ObjectIdentityMap2Int();
protocolVersion = defaultProtocolVersion;
useSubclassMethod = false;
writeStreamHeader();
@@ -207,11 +211,11 @@ public class ObjectOutputStream extends OutputStream
break;
}
- Integer handle = findHandle(obj);
- if (handle != null)
+ int handle = findHandle(obj);
+ if (handle >= 0)
{
realOutput.writeByte(TC_REFERENCE);
- realOutput.writeInt(handle.intValue());
+ realOutput.writeInt(handle);
break;
}
@@ -225,7 +229,7 @@ public class ObjectOutputStream extends OutputStream
writeObject (osc);
}
else
- {
+ {System.err.println("1");
realOutput.writeByte(TC_PROXYCLASSDESC);
Class[] intfs = cl.getInterfaces();
realOutput.writeInt(intfs.length);
@@ -338,8 +342,7 @@ public class ObjectOutputStream extends OutputStream
Object prevObject = this.currentObject;
ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
currentObject = obj;
- ObjectStreamClass[] hierarchy =
- ObjectStreamClass.getObjectStreamClasses(clazz);
+ ObjectStreamClass[] hierarchy = osc.hierarchy();
for (int i = 0; i < hierarchy.length; i++)
{
@@ -604,11 +607,11 @@ public class ObjectOutputStream extends OutputStream
*
* @see ObjectInputStream#resolveClass(java.io.ObjectStreamClass)
*/
- protected void annotateClass(Class cl) throws IOException
+ protected void annotateClass(Class<?> cl) throws IOException
{
}
- protected void annotateProxyClass(Class cl) throws IOException
+ protected void annotateProxyClass(Class<?> cl) throws IOException
{
}
@@ -1104,17 +1107,16 @@ public class ObjectOutputStream extends OutputStream
// lookup the handle for OBJ, return null if OBJ doesn't have a
// handle yet
- private Integer findHandle(Object obj)
+ private int findHandle(Object obj)
{
- return (Integer)OIDLookupTable.get(new ObjectIdentityWrapper(obj));
+ return OIDLookupTable.get(obj);
}
// assigns the next availible handle to OBJ
private int assignNewHandle(Object obj)
{
- OIDLookupTable.put(new ObjectIdentityWrapper(obj),
- new Integer(nextOID));
+ OIDLookupTable.put(obj, nextOID);
return nextOID++;
}
@@ -1216,39 +1218,70 @@ public class ObjectOutputStream extends OutputStream
{
ObjectStreamField[] fields = osc.fields;
boolean oldmode = setBlockDataMode(false);
- String field_name;
- Class type;
- for (int i = 0; i < fields.length; i++)
+ try
{
- field_name = fields[i].getName();
- type = fields[i].getType();
-
- if (dump)
- dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);
-
- if (type == Boolean.TYPE)
- realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
- else if (type == Byte.TYPE)
- realOutput.writeByte(getByteField(obj, osc.forClass(), field_name));
- else if (type == Character.TYPE)
- realOutput.writeChar(getCharField(obj, osc.forClass(), field_name));
- else if (type == Double.TYPE)
- realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name));
- else if (type == Float.TYPE)
- realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name));
- else if (type == Integer.TYPE)
- realOutput.writeInt(getIntField(obj, osc.forClass(), field_name));
- else if (type == Long.TYPE)
- realOutput.writeLong(getLongField(obj, osc.forClass(), field_name));
- else if (type == Short.TYPE)
- realOutput.writeShort(getShortField(obj, osc.forClass(), field_name));
- else
- writeObject(getObjectField(obj, osc.forClass(), field_name,
- fields[i].getTypeString ()));
+ writeFields(obj,fields);
+ }
+ catch (IllegalArgumentException _)
+ {
+ InvalidClassException e = new InvalidClassException
+ ("writing fields of class " + osc.forClass().getName());
+ e.initCause(_);
+ throw e;
}
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ IOException e = new IOException("Unexpected exception " + _);
+ e.initCause(_);
+ throw(e);
+ }
+
setBlockDataMode(oldmode);
}
+
+
+ /**
+ * Helper function for writeFields(Object,ObjectStreamClass): write
+ * fields from given fields array. Pass exception on.
+ *
+ * @param obj the object to be written
+ *
+ * @param fields the fields of obj to be written.
+ */
+ private void writeFields(Object obj, ObjectStreamField[] fields)
+ throws
+ IllegalArgumentException, IllegalAccessException, IOException
+ {
+ for (int i = 0; i < fields.length; i++)
+ {
+ ObjectStreamField osf = fields[i];
+ Field field = osf.field;
+
+ if (DEBUG && dump)
+ dumpElementln ("WRITE FIELD: " + osf.getName() + " type=" + osf.getType());
+
+ switch (osf.getTypeCode())
+ {
+ case 'Z': realOutput.writeBoolean(field.getBoolean(obj)); break;
+ case 'B': realOutput.writeByte (field.getByte (obj)); break;
+ case 'S': realOutput.writeShort (field.getShort (obj)); break;
+ case 'C': realOutput.writeChar (field.getChar (obj)); break;
+ case 'I': realOutput.writeInt (field.getInt (obj)); break;
+ case 'F': realOutput.writeFloat (field.getFloat (obj)); break;
+ case 'J': realOutput.writeLong (field.getLong (obj)); break;
+ case 'D': realOutput.writeDouble (field.getDouble (obj)); break;
+ case 'L':
+ case '[': writeObject (field.get (obj)); break;
+ default:
+ throw new IOException("Unexpected type code " + osf.getTypeCode());
+ }
+ }
+ }
// Toggles writing primitive data to block-data buffer.
@@ -1307,248 +1340,6 @@ public class ObjectOutputStream extends OutputStream
}
}
- private boolean getBooleanField(Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField(klass, field_name);
- boolean b = f.getBoolean(obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private byte getByteField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- byte b = f.getByte (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private char getCharField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- char b = f.getChar (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private double getDoubleField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- double b = f.getDouble (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private float getFloatField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- float b = f.getFloat (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private int getIntField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- int b = f.getInt (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private long getLongField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- long b = f.getLong (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private short getShortField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- short b = f.getShort (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private Object getObjectField (Object obj, Class klass, String field_name,
- String type_code) throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType());
-
- /* if of is primitive something went wrong
- * in the check for primitive classes in writeFields.
- */
- if (of.isPrimitive())
- throw new InvalidClassException
- ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field is primitive");
-
- if (!of.getTypeString().equals(type_code))
- throw new InvalidClassException
- ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field " + of + " has type string " + of.getTypeString() + " instead of " + type_code);
-
- Object o = f.get (obj);
- // FIXME: We should check the type_code here
- return o;
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new IOException ();
- }
- }
-
- private Field getField (Class klass, String name)
- throws java.io.InvalidClassException
- {
- try
- {
- final Field f = klass.getDeclaredField(name);
- setAccessible.setMember(f);
- AccessController.doPrivileged(setAccessible);
- return f;
- }
- catch (java.lang.NoSuchFieldException e)
- {
- throw new InvalidClassException
- ("no field called " + name + " in class " + klass.getName());
- }
- }
-
private void dumpElementln (String msg)
{
for (int i = 0; i < depth; i++)
@@ -1576,7 +1367,7 @@ public class ObjectOutputStream extends OutputStream
private boolean replacementEnabled;
private boolean isSerializing;
private int nextOID;
- private Hashtable OIDLookupTable;
+ private ObjectIdentityMap2Int OIDLookupTable;
private int protocolVersion;
private boolean useSubclassMethod;
private SetAccessibleAction setAccessible = new SetAccessibleAction();
diff --git a/libjava/classpath/java/io/ObjectStreamClass.java b/libjava/classpath/java/io/ObjectStreamClass.java
index abb26d8..52a1ad4 100644
--- a/libjava/classpath/java/io/ObjectStreamClass.java
+++ b/libjava/classpath/java/io/ObjectStreamClass.java
@@ -1,6 +1,6 @@
/* ObjectStreamClass.java -- Class used to write class information
about serialized objects.
- Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -59,8 +59,14 @@ import java.security.Security;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Hashtable;
-import java.util.Vector;
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
public class ObjectStreamClass implements Serializable
{
static final ObjectStreamField[] INVALID_FIELDS = new ObjectStreamField[0];
@@ -80,7 +86,7 @@ public class ObjectStreamClass implements Serializable
*
* @see java.io.Serializable
*/
- public static ObjectStreamClass lookup(Class cl)
+ public static ObjectStreamClass lookup(Class<?> cl)
{
if (cl == null)
return null;
@@ -132,7 +138,7 @@ public class ObjectStreamClass implements Serializable
*
* @see java.io.ObjectInputStream
*/
- public Class forClass()
+ public Class<?> forClass()
{
return clazz;
}
@@ -235,37 +241,45 @@ public class ObjectStreamClass implements Serializable
return superClass;
}
-
- // returns an array of ObjectStreamClasses that represent the super
- // classes of CLAZZ and CLAZZ itself in order from most super to
- // CLAZZ. ObjectStreamClass[0] is the highest superclass of CLAZZ
- // that is serializable.
- static ObjectStreamClass[] getObjectStreamClasses(Class clazz)
+ /**
+ * returns an array of ObjectStreamClasses that represent the super
+ * classes of the class represented by this and the class
+ * represented by this itself in order from most super to this.
+ * ObjectStreamClass[0] is the highest superclass of this that is
+ * serializable.
+ *
+ * The result of consecutive calls this hierarchy() will be the same
+ * array instance.
+ *
+ * @return an array of ObjectStreamClass representing the
+ * super-class hierarchy of serializable classes.
+ */
+ ObjectStreamClass[] hierarchy()
{
- ObjectStreamClass osc = ObjectStreamClass.lookup(clazz);
-
- if (osc == null)
- return new ObjectStreamClass[0];
- else
- {
- Vector oscs = new Vector();
-
- while (osc != null)
- {
- oscs.addElement (osc);
- osc = osc.getSuper();
- }
-
- int count = oscs.size();
- ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[ count ];
-
- for (int i = count - 1; i >= 0; i--)
- sorted_oscs[ count - i - 1 ] = (ObjectStreamClass) oscs.elementAt(i);
-
- return sorted_oscs;
+ ObjectStreamClass[] result = hierarchy;
+ if (result == null)
+ {
+ int d = 0;
+
+ for(ObjectStreamClass osc = this; osc != null; osc = osc.getSuper())
+ d++;
+
+ result = new ObjectStreamClass[d];
+
+ for (ObjectStreamClass osc = this; osc != null; osc = osc.getSuper())
+ {
+ result[--d] = osc;
+ }
+
+ hierarchy = result;
}
+ return result;
}
+ /**
+ * Cache for hierarchy() result.
+ */
+ private ObjectStreamClass[] hierarchy = null;
// Returns an integer that consists of bit-flags that indicate
// properties of the class represented by this ObjectStreamClass.
@@ -298,7 +312,7 @@ public class ObjectStreamClass implements Serializable
* already set UID is found.
*/
void setClass(Class cl, ObjectStreamClass superClass) throws InvalidClassException
- {
+ {hierarchy = null;
this.clazz = cl;
cacheMethods();
@@ -309,8 +323,8 @@ public class ObjectStreamClass implements Serializable
else
{
// Check that the actual UID of the resolved class matches the UID from
- // the stream.
- if (uid != class_uid)
+ // the stream. Mismatches for array classes are ignored.
+ if (!cl.isArray() && uid != class_uid)
{
String msg = cl +
": Local class not compatible: stream serialVersionUID="
@@ -425,6 +439,7 @@ public class ObjectStreamClass implements Serializable
void setSuperclass (ObjectStreamClass osc)
{
superClass = osc;
+ hierarchy = null;
}
void calculateOffsets()
@@ -547,21 +562,62 @@ outer:
return null;
}
- private void cacheMethods()
+ /**
+ * Helper routine to check if a class was loaded by boot or
+ * application class loader. Classes for which this is not the case
+ * should not be cached since caching prevent class file garbage
+ * collection.
+ *
+ * @param cl a class
+ *
+ * @return true if cl was loaded by boot or application class loader,
+ * false if cl was loaded by a user class loader.
+ */
+ private static boolean loadedByBootOrApplicationClassLoader(Class cl)
{
- Method[] methods = forClass().getDeclaredMethods();
+ ClassLoader l = cl.getClassLoader();
+ return
+ ( l == null /* boot loader */ )
+ || (l == ClassLoader.getSystemClassLoader() /* application loader */);
+ }
- readObjectMethod = findMethod(methods, "readObject",
- new Class[] { ObjectInputStream.class },
- Void.TYPE, true);
- writeObjectMethod = findMethod(methods, "writeObject",
- new Class[] { ObjectOutputStream.class },
- Void.TYPE, true);
+ static Hashtable methodCache = new Hashtable();
+
+ static final Class[] readObjectSignature = { ObjectInputStream.class };
+ static final Class[] writeObjectSignature = { ObjectOutputStream.class };
- // readResolve and writeReplace can be in parent classes, as long as they
- // are accessible from this class.
- readResolveMethod = findAccessibleMethod("readResolve", forClass());
- writeReplaceMethod = findAccessibleMethod("writeReplace", forClass());
+ private void cacheMethods()
+ {
+ Class cl = forClass();
+ Method[] cached = (Method[]) methodCache.get(cl);
+ if (cached == null)
+ {
+ cached = new Method[4];
+ Method[] methods = cl.getDeclaredMethods();
+
+ cached[0] = findMethod(methods, "readObject",
+ readObjectSignature,
+ Void.TYPE, true);
+ cached[1] = findMethod(methods, "writeObject",
+ writeObjectSignature,
+ Void.TYPE, true);
+
+ // readResolve and writeReplace can be in parent classes, as long as they
+ // are accessible from this class.
+ cached[2] = findAccessibleMethod("readResolve", cl);
+ cached[3] = findAccessibleMethod("writeReplace", cl);
+
+ /* put in cache if classes not loaded by user class loader.
+ * For a user class loader, the cache may otherwise grow
+ * without limit.
+ */
+ if (loadedByBootOrApplicationClassLoader(cl))
+ methodCache.put(cl,cached);
+ }
+ readObjectMethod = cached[0];
+ writeObjectMethod = cached[1];
+ readResolveMethod = cached[2];
+ writeReplaceMethod = cached[3];
}
private ObjectStreamClass(Class cl)
@@ -713,152 +769,208 @@ outer:
calculateOffsets();
}
+ static Hashtable uidCache = new Hashtable();
+
// Returns the serial version UID defined by class, or if that
// isn't present, calculates value of serial version UID.
private long getClassUID(Class cl)
{
- try
+ long result = 0;
+ Long cache = (Long) uidCache.get(cl);
+ if (cache != null)
+ result = cache.longValue();
+ else
{
- // Use getDeclaredField rather than getField, since serialVersionUID
- // may not be public AND we only want the serialVersionUID of this
- // class, not a superclass or interface.
- final Field suid = cl.getDeclaredField("serialVersionUID");
- SetAccessibleAction setAccessible = new SetAccessibleAction(suid);
- AccessController.doPrivileged(setAccessible);
- int modifiers = suid.getModifiers();
-
- if (Modifier.isStatic(modifiers)
- && Modifier.isFinal(modifiers)
- && suid.getType() == Long.TYPE)
- return suid.getLong(null);
+ try
+ {
+ result = getClassUIDFromField(cl);
+ }
+ catch (NoSuchFieldException ignore)
+ {
+ try
+ {
+ result = calculateClassUID(cl);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException
+ ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
+ + cl.getName(), e);
+ }
+ catch (IOException ioe)
+ {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ if (loadedByBootOrApplicationClassLoader(cl))
+ uidCache.put(cl,new Long(result));
}
- catch (NoSuchFieldException ignore)
+ return result;
+ }
+
+ /**
+ * Search for a serialVersionUID field in the given class and read
+ * its value.
+ *
+ * @return the contents of the serialVersionUID field
+ *
+ * @throws NoSuchFieldException if such a field does not exist or is
+ * not static, not final, not of type Long or not accessible.
+ */
+ long getClassUIDFromField(Class cl)
+ throws NoSuchFieldException
+ {
+ long result;
+
+ try
{
+ // Use getDeclaredField rather than getField, since serialVersionUID
+ // may not be public AND we only want the serialVersionUID of this
+ // class, not a superclass or interface.
+ final Field suid = cl.getDeclaredField("serialVersionUID");
+ SetAccessibleAction setAccessible = new SetAccessibleAction(suid);
+ AccessController.doPrivileged(setAccessible);
+ int modifiers = suid.getModifiers();
+
+ if (Modifier.isStatic(modifiers)
+ && Modifier.isFinal(modifiers)
+ && suid.getType() == Long.TYPE)
+ result = suid.getLong(null);
+ else
+ throw new NoSuchFieldException();
}
catch (IllegalAccessException ignore)
{
+ throw new NoSuchFieldException();
}
- // cl didn't define serialVersionUID, so we have to compute it
- try
- {
- MessageDigest md;
- try
- {
- md = MessageDigest.getInstance("SHA");
- }
- catch (NoSuchAlgorithmException e)
- {
- // If a provider already provides SHA, use it; otherwise, use this.
- Gnu gnuProvider = new Gnu();
- Security.addProvider(gnuProvider);
- md = MessageDigest.getInstance("SHA");
- }
-
- DigestOutputStream digest_out =
- new DigestOutputStream(nullOutputStream, md);
- DataOutputStream data_out = new DataOutputStream(digest_out);
-
- data_out.writeUTF(cl.getName());
-
- int modifiers = cl.getModifiers();
- // just look at interesting bits
- modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
- | Modifier.INTERFACE | Modifier.PUBLIC);
- data_out.writeInt(modifiers);
-
- // Pretend that an array has no interfaces, because when array
- // serialization was defined (JDK 1.1), arrays didn't have it.
- if (! cl.isArray())
- {
- Class[] interfaces = cl.getInterfaces();
- Arrays.sort(interfaces, interfaceComparator);
- for (int i = 0; i < interfaces.length; i++)
- data_out.writeUTF(interfaces[i].getName());
- }
-
- Field field;
- Field[] fields = cl.getDeclaredFields();
- Arrays.sort(fields, memberComparator);
- for (int i = 0; i < fields.length; i++)
- {
- field = fields[i];
- modifiers = field.getModifiers();
- if (Modifier.isPrivate(modifiers)
- && (Modifier.isStatic(modifiers)
- || Modifier.isTransient(modifiers)))
- continue;
-
- data_out.writeUTF(field.getName());
- data_out.writeInt(modifiers);
- data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
- }
-
- // write class initializer method if present
- if (VMObjectStreamClass.hasClassInitializer(cl))
- {
- data_out.writeUTF("<clinit>");
- data_out.writeInt(Modifier.STATIC);
- data_out.writeUTF("()V");
- }
-
- Constructor constructor;
- Constructor[] constructors = cl.getDeclaredConstructors();
- Arrays.sort (constructors, memberComparator);
- for (int i = 0; i < constructors.length; i++)
- {
- constructor = constructors[i];
- modifiers = constructor.getModifiers();
- if (Modifier.isPrivate(modifiers))
- continue;
-
- data_out.writeUTF("<init>");
- data_out.writeInt(modifiers);
-
- // the replacement of '/' with '.' was needed to make computed
- // SUID's agree with those computed by JDK
- data_out.writeUTF
- (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
- }
-
- Method method;
- Method[] methods = cl.getDeclaredMethods();
- Arrays.sort(methods, memberComparator);
- for (int i = 0; i < methods.length; i++)
- {
- method = methods[i];
- modifiers = method.getModifiers();
- if (Modifier.isPrivate(modifiers))
- continue;
-
- data_out.writeUTF(method.getName());
- data_out.writeInt(modifiers);
-
- // the replacement of '/' with '.' was needed to make computed
- // SUID's agree with those computed by JDK
- data_out.writeUTF
- (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
- }
-
- data_out.close();
- byte[] sha = md.digest();
- long result = 0;
- int len = sha.length < 8 ? sha.length : 8;
- for (int i = 0; i < len; i++)
- result += (long) (sha[i] & 0xFF) << (8 * i);
+ return result;
+ }
- return result;
+ /**
+ * Calculate class serial version UID for a class that does not
+ * define serialVersionUID:
+ *
+ * @param cl a class
+ *
+ * @return the calculated serial varsion UID.
+ *
+ * @throws NoSuchAlgorithmException if SHA algorithm not found
+ *
+ * @throws IOException if writing to the DigestOutputStream causes
+ * an IOException.
+ */
+ long calculateClassUID(Class cl)
+ throws NoSuchAlgorithmException, IOException
+ {
+ long result;
+ MessageDigest md;
+ try
+ {
+ md = MessageDigest.getInstance("SHA");
}
catch (NoSuchAlgorithmException e)
{
- throw new RuntimeException
- ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
- + cl.getName(), e);
+ // If a provider already provides SHA, use it; otherwise, use this.
+ Gnu gnuProvider = new Gnu();
+ Security.addProvider(gnuProvider);
+ md = MessageDigest.getInstance("SHA");
+ }
+
+ DigestOutputStream digest_out =
+ new DigestOutputStream(nullOutputStream, md);
+ DataOutputStream data_out = new DataOutputStream(digest_out);
+
+ data_out.writeUTF(cl.getName());
+
+ int modifiers = cl.getModifiers();
+ // just look at interesting bits
+ modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
+ | Modifier.INTERFACE | Modifier.PUBLIC);
+ data_out.writeInt(modifiers);
+
+ // Pretend that an array has no interfaces, because when array
+ // serialization was defined (JDK 1.1), arrays didn't have it.
+ if (! cl.isArray())
+ {
+ Class[] interfaces = cl.getInterfaces();
+ Arrays.sort(interfaces, interfaceComparator);
+ for (int i = 0; i < interfaces.length; i++)
+ data_out.writeUTF(interfaces[i].getName());
+ }
+
+ Field field;
+ Field[] fields = cl.getDeclaredFields();
+ Arrays.sort(fields, memberComparator);
+ for (int i = 0; i < fields.length; i++)
+ {
+ field = fields[i];
+ modifiers = field.getModifiers();
+ if (Modifier.isPrivate(modifiers)
+ && (Modifier.isStatic(modifiers)
+ || Modifier.isTransient(modifiers)))
+ continue;
+
+ data_out.writeUTF(field.getName());
+ data_out.writeInt(modifiers);
+ data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
+ }
+
+ // write class initializer method if present
+ if (VMObjectStreamClass.hasClassInitializer(cl))
+ {
+ data_out.writeUTF("<clinit>");
+ data_out.writeInt(Modifier.STATIC);
+ data_out.writeUTF("()V");
}
- catch (IOException ioe)
+
+ Constructor constructor;
+ Constructor[] constructors = cl.getDeclaredConstructors();
+ Arrays.sort (constructors, memberComparator);
+ for (int i = 0; i < constructors.length; i++)
+ {
+ constructor = constructors[i];
+ modifiers = constructor.getModifiers();
+ if (Modifier.isPrivate(modifiers))
+ continue;
+
+ data_out.writeUTF("<init>");
+ data_out.writeInt(modifiers);
+
+ // the replacement of '/' with '.' was needed to make computed
+ // SUID's agree with those computed by JDK
+ data_out.writeUTF
+ (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
+ }
+
+ Method method;
+ Method[] methods = cl.getDeclaredMethods();
+ Arrays.sort(methods, memberComparator);
+ for (int i = 0; i < methods.length; i++)
{
- throw new RuntimeException(ioe);
+ method = methods[i];
+ modifiers = method.getModifiers();
+ if (Modifier.isPrivate(modifiers))
+ continue;
+
+ data_out.writeUTF(method.getName());
+ data_out.writeInt(modifiers);
+
+ // the replacement of '/' with '.' was needed to make computed
+ // SUID's agree with those computed by JDK
+ data_out.writeUTF
+ (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
}
+
+ data_out.close();
+ byte[] sha = md.digest();
+ result = 0;
+ int len = sha.length < 8 ? sha.length : 8;
+ for (int i = 0; i < len; i++)
+ result += (long) (sha[i] & 0xFF) << (8 * i);
+
+ return result;
}
/**
@@ -948,7 +1060,8 @@ outer:
public static final ObjectStreamField[] NO_FIELDS = {};
- private static Hashtable classLookupTable = new Hashtable();
+ private static Hashtable<Class,ObjectStreamClass> classLookupTable
+ = new Hashtable<Class,ObjectStreamClass>();
private static final NullOutputStream nullOutputStream = new NullOutputStream();
private static final Comparator interfaceComparator = new InterfaceComparator();
private static final Comparator memberComparator = new MemberComparator();
@@ -956,7 +1069,7 @@ outer:
Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };
private ObjectStreamClass superClass;
- private Class clazz;
+ private Class<?> clazz;
private String name;
private long uid;
private byte flags;
diff --git a/libjava/classpath/java/io/ObjectStreamField.java b/libjava/classpath/java/io/ObjectStreamField.java
index 61ccdc7..91f5578 100644
--- a/libjava/classpath/java/io/ObjectStreamField.java
+++ b/libjava/classpath/java/io/ObjectStreamField.java
@@ -1,5 +1,5 @@
/* ObjectStreamField.java -- Class used to store name and class of fields
- Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -48,17 +48,24 @@ import java.security.PrivilegedAction;
* This class intends to describe the field of a class for the serialization
* subsystem. Serializable fields in a serializable class can be explicitly
* exported using an array of ObjectStreamFields.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
-public class ObjectStreamField implements Comparable
+public class ObjectStreamField
+ implements Comparable<Object>
{
private String name;
- private Class type;
+ private Class<?> type;
private String typename;
private int offset = -1; // XXX make sure this is correct
private boolean unshared;
private boolean persistent = false;
private boolean toset = true;
- private Field field;
+ Field field;
ObjectStreamField (Field field)
{
@@ -74,7 +81,7 @@ public class ObjectStreamField implements Comparable
* @param name Name of the field to export.
* @param type Type of the field in the concerned class.
*/
- public ObjectStreamField (String name, Class type)
+ public ObjectStreamField (String name, Class<?> type)
{
this (name, type, false);
}
@@ -88,7 +95,7 @@ public class ObjectStreamField implements Comparable
* @param type Type of the field in the concerned class.
* @param unshared true if field will be unshared, false otherwise.
*/
- public ObjectStreamField (String name, Class type, boolean unshared)
+ public ObjectStreamField (String name, Class<?> type, boolean unshared)
{
if (name == null)
throw new NullPointerException();
@@ -111,28 +118,10 @@ public class ObjectStreamField implements Comparable
{
this.name = name;
this.typename = typename;
- try
- {
- type = TypeSignature.getClassForEncoding(typename);
- }
- catch(ClassNotFoundException e)
- {
- }
}
-
- /**
- * There are many cases you can not get java.lang.Class from typename
- * if your context class loader cann not load it, then use typename to
- * construct the field.
- *
- * @param name Name of the field to export.
- * @param typename The coded name of the type for this field.
- * @param loader The class loader to use to resolve class names.
- */
- ObjectStreamField (String name, String typename, ClassLoader loader)
+
+ void resolveType(ClassLoader loader)
{
- this.name = name;
- this.typename = typename;
try
{
type = TypeSignature.getClassForEncoding(typename, true, loader);
@@ -141,7 +130,7 @@ public class ObjectStreamField implements Comparable
{
}
}
-
+
/**
* This method returns the name of the field represented by the
* ObjectStreamField instance.
@@ -159,7 +148,7 @@ public class ObjectStreamField implements Comparable
*
* @return A class representing the type of the field.
*/
- public Class getType ()
+ public Class<?> getType ()
{
return type;
}
@@ -347,7 +336,7 @@ public class ObjectStreamField implements Comparable
*/
void checkFieldType() throws InvalidClassException
{
- Class ftype = field.getType();
+ Class<?> ftype = field.getType();
if (!ftype.isAssignableFrom(type))
throw new InvalidClassException
diff --git a/libjava/classpath/java/io/OutputStreamWriter.java b/libjava/classpath/java/io/OutputStreamWriter.java
index 5726838..2636340 100644
--- a/libjava/classpath/java/io/OutputStreamWriter.java
+++ b/libjava/classpath/java/io/OutputStreamWriter.java
@@ -223,6 +223,7 @@ public class OutputStreamWriter extends Writer
encoder.onMalformedInput(CodingErrorAction.REPLACE);
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
+ encodingName = EncodingHelper.getOldCanonical(cs.name());
}
/**
@@ -240,6 +241,11 @@ public class OutputStreamWriter extends Writer
this.out = out;
encoder = enc;
outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
+ Charset cs = enc.charset();
+ if (cs == null)
+ encodingName = "US-ASCII";
+ else
+ encodingName = EncodingHelper.getOldCanonical(cs.name());
}
/**
diff --git a/libjava/classpath/java/io/PipedInputStream.java b/libjava/classpath/java/io/PipedInputStream.java
index 523ae2c..c0396d2 100644
--- a/libjava/classpath/java/io/PipedInputStream.java
+++ b/libjava/classpath/java/io/PipedInputStream.java
@@ -279,6 +279,10 @@ public class PipedInputStream extends InputStream
if (closed)
throw new IOException ("Pipe closed");
+ // Don't block if nothing was requested.
+ if (len == 0)
+ return 0;
+
// If the buffer is empty, wait until there is something in the pipe
// to read.
try
diff --git a/libjava/classpath/java/io/PipedReader.java b/libjava/classpath/java/io/PipedReader.java
index 90fc10f..8a3363a 100644
--- a/libjava/classpath/java/io/PipedReader.java
+++ b/libjava/classpath/java/io/PipedReader.java
@@ -261,6 +261,10 @@ public class PipedReader extends Reader
if (closed)
throw new IOException ("Pipe closed");
+ // Don't block if nothing was requested.
+ if (len == 0)
+ return 0;
+
// If the buffer is empty, wait until there is something in the pipe
// to read.
try
diff --git a/libjava/classpath/java/io/PrintStream.java b/libjava/classpath/java/io/PrintStream.java
index 98461db..2d747c8 100644
--- a/libjava/classpath/java/io/PrintStream.java
+++ b/libjava/classpath/java/io/PrintStream.java
@@ -39,6 +39,9 @@ exception statement from your version. */
package java.io;
+import java.util.Locale;
+import java.util.Formatter;
+
import gnu.classpath.SystemProperties;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
@@ -58,8 +61,9 @@ import gnu.classpath.SystemProperties;
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
-public class PrintStream extends FilterOutputStream
+public class PrintStream extends FilterOutputStream implements Appendable
{
/* Notice the implementation is quite similar to OutputStreamWriter.
* This leads to some minor duplication, because neither inherits
@@ -67,7 +71,7 @@ public class PrintStream extends FilterOutputStream
// Line separator string.
private static final char[] line_separator
- = SystemProperties.getProperty("line.separator").toCharArray();
+ = SystemProperties.getProperty("line.separator", "\n").toCharArray();
/**
* Encoding name
@@ -620,5 +624,51 @@ public class PrintStream extends FilterOutputStream
setError ();
}
}
-} // class PrintStream
+ /** @since 1.5 */
+ public PrintStream append(char c)
+ {
+ print(c);
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintStream append(CharSequence cs)
+ {
+ print(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintStream append(CharSequence cs, int start, int end)
+ {
+ print(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintStream printf(String format, Object... args)
+ {
+ return format(format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintStream printf(Locale locale, String format, Object... args)
+ {
+ return format(locale, format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintStream format(String format, Object... args)
+ {
+ return format(Locale.getDefault(), format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintStream format(Locale locale, String format, Object... args)
+ {
+ Formatter f = new Formatter(this, locale);
+ f.format(format, args);
+ return this;
+ }
+} // class PrintStream
diff --git a/libjava/classpath/java/io/PrintWriter.java b/libjava/classpath/java/io/PrintWriter.java
index 5667e70..5b4294c 100644
--- a/libjava/classpath/java/io/PrintWriter.java
+++ b/libjava/classpath/java/io/PrintWriter.java
@@ -1,5 +1,5 @@
/* PrintWriter.java -- prints primitive values and objects to a stream as text
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
+ Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,6 +37,9 @@ exception statement from your version. */
package java.io;
+import java.util.Locale;
+import java.util.Formatter;
+
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
@@ -636,5 +639,52 @@ public class PrintWriter extends Writer
{
write(str, 0, str.length());
}
+
+ /** @since 1.5 */
+ public PrintWriter append(char c)
+ {
+ write(c);
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintWriter append(CharSequence cs)
+ {
+ write(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintWriter append(CharSequence cs, int start, int end)
+ {
+ write(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintWriter printf(String format, Object... args)
+ {
+ return format(format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintWriter printf(Locale locale, String format, Object... args)
+ {
+ return format(locale, format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintWriter format(String format, Object... args)
+ {
+ return format(Locale.getDefault(), format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintWriter format(Locale locale, String format, Object... args)
+ {
+ Formatter f = new Formatter(this, locale);
+ f.format(format, args);
+ return this;
+ }
}
diff --git a/libjava/classpath/java/io/RandomAccessFile.java b/libjava/classpath/java/io/RandomAccessFile.java
index 84ee5de..036fc8c 100644
--- a/libjava/classpath/java/io/RandomAccessFile.java
+++ b/libjava/classpath/java/io/RandomAccessFile.java
@@ -38,7 +38,7 @@ exception statement from your version. */
package java.io;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
import java.nio.channels.FileChannel;
@@ -58,7 +58,7 @@ import java.nio.channels.FileChannel;
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
*/
-public class RandomAccessFile implements DataOutput, DataInput
+public class RandomAccessFile implements DataOutput, DataInput, Closeable
{
// The underlying file.
@@ -122,7 +122,20 @@ public class RandomAccessFile implements DataOutput, DataInput
s.checkWrite(fileName);
}
- ch = FileChannelImpl.create(file, fdmode);
+ try
+ {
+ ch = FileChannelImpl.create(file, fdmode);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ throw fnfe;
+ }
+ catch (IOException ioe)
+ {
+ FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
+ fnfe.initCause(ioe);
+ throw fnfe;
+ }
fd = new FileDescriptor(ch);
if ((fdmode & FileChannelImpl.WRITE) != 0)
out = new DataOutputStream (new FileOutputStream (fd));
diff --git a/libjava/classpath/java/io/Reader.java b/libjava/classpath/java/io/Reader.java
index 7970d9a..6da1813 100644
--- a/libjava/classpath/java/io/Reader.java
+++ b/libjava/classpath/java/io/Reader.java
@@ -1,5 +1,5 @@
/* Reader.java -- base class of classes that read input as a stream of chars
- Copyright (C) 1998, 1999, 2000, 2003 Free Software Foundation
+ Copyright (C) 1998, 1999, 2000, 2003, 2004, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,6 +37,8 @@ exception statement from your version. */
package java.io;
+import java.nio.CharBuffer;
+
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
@@ -53,7 +55,7 @@ package java.io;
* @date April 21, 1998.
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
-public abstract class Reader
+public abstract class Reader implements Closeable, Readable
{
/**
* This is the <code>Object</code> used for synchronizing critical code
@@ -152,6 +154,19 @@ public abstract class Reader
return count > 0 ? buf[0] : -1;
}
+ /** @since 1.5 */
+ public int read(CharBuffer buffer) throws IOException
+ {
+ // We want to call put(), so we don't manipulate the CharBuffer
+ // directly.
+ int rem = buffer.remaining();
+ char[] buf = new char[rem];
+ int result = read(buf, 0, rem);
+ if (result != -1)
+ buffer.put(buf, 0, result);
+ return result;
+ }
+
/**
* Closes the stream. Any futher attempts to read from the
* stream may generate an <code>IOException</code>.
diff --git a/libjava/classpath/java/io/SequenceInputStream.java b/libjava/classpath/java/io/SequenceInputStream.java
index 7fefe24..5ff85e9 100644
--- a/libjava/classpath/java/io/SequenceInputStream.java
+++ b/libjava/classpath/java/io/SequenceInputStream.java
@@ -1,5 +1,5 @@
/* SequenceInputStream.java -- Reads multiple input streams in sequence
- Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -71,8 +71,11 @@ public class SequenceInputStream extends InputStream
/** Secondary input stream; not used if constructed w/ enumeration. */
private InputStream in2;
- /** The enumeration handle; not used if constructed w/ 2 explicit input streams. */
- private Enumeration e;
+ /**
+ * The enumeration handle; not used if constructed w/ 2 explicit
+ * input streams.
+ */
+ private Enumeration<? extends InputStream> e;
/**
* This method creates a new <code>SequenceInputStream</code> that obtains
@@ -82,10 +85,10 @@ public class SequenceInputStream extends InputStream
* @param e An <code>Enumeration</code> that will return a list of
* <code>InputStream</code>s to read in sequence
*/
- public SequenceInputStream(Enumeration e)
+ public SequenceInputStream(Enumeration<? extends InputStream> e)
{
this.e = e;
- in = (InputStream) e.nextElement();
+ in = e.nextElement();
in2 = null;
}
@@ -207,14 +210,13 @@ public class SequenceInputStream extends InputStream
if (e != null)
{
if (e.hasMoreElements())
- nextIn = (InputStream) e.nextElement();
+ nextIn = e.nextElement();
+ }
+ else if (in2 != null)
+ {
+ nextIn = in2;
+ in2 = null;
}
- else
- if (in2 != null)
- {
- nextIn = in2;
- in2 = null;
- }
return nextIn;
}
diff --git a/libjava/classpath/java/io/StringWriter.java b/libjava/classpath/java/io/StringWriter.java
index a1e9aeb..5a16e63 100644
--- a/libjava/classpath/java/io/StringWriter.java
+++ b/libjava/classpath/java/io/StringWriter.java
@@ -183,6 +183,27 @@ public class StringWriter extends Writer
buffer.append(str.substring(offset, offset + len));
}
+ /** @since 1.5 */
+ public StringWriter append(char c)
+ {
+ write(c);
+ return this;
+ }
+
+ /** @since 1.5 */
+ public StringWriter append(CharSequence cs)
+ {
+ write(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public StringWriter append(CharSequence cs, int start, int end)
+ {
+ write(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
+
/**
* This is the <code>StringBuffer</code> that we use to store bytes that
* are written.
diff --git a/libjava/classpath/java/io/Writer.java b/libjava/classpath/java/io/Writer.java
index f153e31..660b690 100644
--- a/libjava/classpath/java/io/Writer.java
+++ b/libjava/classpath/java/io/Writer.java
@@ -53,7 +53,7 @@ package java.io;
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Per Bothner (bothner@cygnus.com)
*/
-public abstract class Writer
+public abstract class Writer implements Appendable, Closeable, Flushable
{
/**
* This is the object used to synchronize criticial code sections for
@@ -188,5 +188,24 @@ public abstract class Writer
write(buf, 0, len);
}
-} // class Writer
+ /** @since 1.5 */
+ public Writer append(char c) throws IOException
+ {
+ write(c);
+ return this;
+ }
+ /** @since 1.5 */
+ public Writer append(CharSequence cs) throws IOException
+ {
+ write(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public Writer append(CharSequence cs, int start, int end) throws IOException
+ {
+ write(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
+}
diff --git a/libjava/classpath/java/io/class-dependencies.conf b/libjava/classpath/java/io/class-dependencies.conf
new file mode 100644
index 0000000..633bb17
--- /dev/null
+++ b/libjava/classpath/java/io/class-dependencies.conf
@@ -0,0 +1,100 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+java/io/File: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/FileDescriptor: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+java/io/FileInputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V
+
+java/io/FileOutputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+java/io/ObjectInputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/ObjectOutputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/RandomAccessFile: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+# end of file