Merged gcj-eclipse branch to trunk.
From-SVN: r120621
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1291,32 +1252,6 @@ public class File implements Serializable, Comparable
|
||||
return path.compareToIgnoreCase (other.path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>.
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -134,6 +134,16 @@ public class InputStreamReader extends Reader
|
||||
private char savedSurrogate;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,38 +1218,69 @@ public class ObjectOutputStream extends OutputStream
|
||||
{
|
||||
ObjectStreamField[] fields = osc.fields;
|
||||
boolean oldmode = setBlockDataMode(false);
|
||||
String field_name;
|
||||
Class type;
|
||||
|
||||
try
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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 ()));
|
||||
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());
|
||||
}
|
||||
}
|
||||
setBlockDataMode(oldmode);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
ClassLoader l = cl.getClassLoader();
|
||||
return
|
||||
( l == null /* boot loader */ )
|
||||
|| (l == ClassLoader.getSystemClassLoader() /* application loader */);
|
||||
}
|
||||
|
||||
static Hashtable methodCache = new Hashtable();
|
||||
|
||||
static final Class[] readObjectSignature = { ObjectInputStream.class };
|
||||
static final Class[] writeObjectSignature = { ObjectOutputStream.class };
|
||||
|
||||
private void cacheMethods()
|
||||
{
|
||||
Method[] methods = forClass().getDeclaredMethods();
|
||||
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);
|
||||
|
||||
readObjectMethod = findMethod(methods, "readObject",
|
||||
new Class[] { ObjectInputStream.class },
|
||||
Void.TYPE, true);
|
||||
writeObjectMethod = findMethod(methods, "writeObject",
|
||||
new Class[] { ObjectOutputStream.class },
|
||||
Void.TYPE, true);
|
||||
|
||||
// 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());
|
||||
// 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)
|
||||
{
|
||||
long result = 0;
|
||||
Long cache = (Long) uidCache.get(cl);
|
||||
if (cache != null)
|
||||
result = cache.longValue();
|
||||
else
|
||||
{
|
||||
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));
|
||||
}
|
||||
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)
|
||||
return suid.getLong(null);
|
||||
}
|
||||
catch (NoSuchFieldException ignore)
|
||||
{
|
||||
// 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
|
||||
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
|
||||
{
|
||||
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;
|
||||
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");
|
||||
}
|
||||
catch (IOException ioe)
|
||||
|
||||
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())
|
||||
{
|
||||
throw new RuntimeException(ioe);
|
||||
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();
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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>.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user