You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/12/01 07:04:00 UTC
svn commit: r350181 [99/198] - in
/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/
depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/
depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/
depends/oss/win.I...
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamClass.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamClass.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamClass.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamClass.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,1062 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.util.WeakHashMap;
+
+import com.ibm.oti.util.PriviAction;
+import com.ibm.oti.util.Sorter;
+
+/**
+ * Instances of ObjectStreamClass are used to describe classes of objects used
+ * by serialization. When objects are saved, information about all its
+ * superclasses is also saved by the use of descriptors, instances of
+ * ObjectStreamClass.
+ *
+ * These descriptors carry information about the class they represent, such as
+ * - The name of the class - SUID of the class - Field names and types
+ *
+ * @see ObjectOutputStream
+ * @see ObjectInputStream
+ * @see java.lang.Class
+ */
+public class ObjectStreamClass implements Serializable {
+
+ // No need to compute the SUID for ObjectStreamClass, just use the value
+ // below
+ static final long serialVersionUID = -6120832682080437368L;
+
+ // Name of the field that contains the SUID value (if present)
+ private static final String UID_FIELD_NAME = "serialVersionUID"; //$NON-NLS-1$
+
+ private static final int CLASS_MODIFIERS_MASK;
+
+ private static final Class[] READ_PARAM_TYPES;
+
+ private static final Class[] WRITE_PARAM_TYPES;
+
+ static final Class[] EMPTY_CONSTRUCTOR_PARAM_TYPES;
+
+ private static final Class VOID_CLASS;
+
+ static final Class[] UNSHARED_PARAM_TYPES;
+
+ private static native void oneTimeInitialization();
+
+ static {
+ oneTimeInitialization();
+
+ CLASS_MODIFIERS_MASK = Modifier.PUBLIC | Modifier.FINAL
+ | Modifier.INTERFACE | Modifier.ABSTRACT;
+ READ_PARAM_TYPES = new Class[1];
+ WRITE_PARAM_TYPES = new Class[1];
+ READ_PARAM_TYPES[0] = java.io.ObjectInputStream.class;
+ WRITE_PARAM_TYPES[0] = java.io.ObjectOutputStream.class;
+ EMPTY_CONSTRUCTOR_PARAM_TYPES = new Class[0];
+ VOID_CLASS = Void.TYPE;
+ UNSHARED_PARAM_TYPES = new Class[1];
+ UNSHARED_PARAM_TYPES[0] = Object.class;
+ }
+
+ /**
+ * A value that indicates the class has no Serializable fields
+ */
+ public static final ObjectStreamField[] NO_FIELDS = new ObjectStreamField[0];
+
+ static final Class ARRAY_OF_FIELDS; // used to fetch field
+ // serialPersistentFields and checking
+ // its type
+ static {
+ try {
+ ARRAY_OF_FIELDS = Class.forName("[Ljava.io.ObjectStreamField;"); //$NON-NLS-1$
+ } catch (ClassNotFoundException e) {
+ // This should not happen
+ throw new RuntimeException();
+ }
+ }
+
+ private static final String CLINIT_NAME = "<clinit>"; //$NON-NLS-1$
+
+ private static final int CLINIT_MODIFIERS = Modifier.STATIC;
+
+ private static final String CLINIT_SIGNATURE = "()V"; //$NON-NLS-1$
+
+ // Used to determine if an object is Serializable or Externalizable
+ private static final Class SERIALIZABLE = java.io.Serializable.class;
+
+ private static final Class EXTERNALIZABLE = java.io.Externalizable.class;
+
+ // Used to test if the object is a String or a class.
+ static final Class STRINGCLASS = java.lang.String.class;
+
+ static final Class CLASSCLASS = java.lang.Class.class;
+
+ static final Class OBJECTSTREAMCLASSCLASS = java.io.ObjectStreamClass.class;
+
+ // Table mapping instances of java.lang.Class to to corresponding instances
+ // of ObjectStreamClass
+ private static final WeakHashMap classesAndDescriptors = new WeakHashMap();
+
+ // ClassDesc
+ private String className; // Name of the class this descriptor represents
+
+ private WeakReference resolvedClass; // Corresponding loaded class with
+ // the name above
+
+ private long svUID; // Serial version UID of the class the descriptor
+ // represents
+
+ // ClassDescInfo
+ private byte flags; // Any combination of SC_WRITE_METHOD, SC_SERIALIZABLE
+ // and SC_EXTERNALIZABLE (see ObjectStreamConstants)
+
+ private ObjectStreamClass superclass; // Descriptor for the superclass of
+ // the class associated with this
+ // descriptor
+
+ private ObjectStreamField[] fields; // Array of ObjectStreamField (see
+ // below) describing the fields of this
+ // class
+
+ private ObjectStreamField[] loadFields; // Array of ObjectStreamField
+ // describing the serialized fields
+ // of this class
+
+ // If an ObjectStreamClass describes an Externalizable class, it (the
+ // descriptor) should not have
+ // field descriptors (ObjectStreamField) at all. The ObjectStreamClass that
+ // gets saved should simply
+ // have no field info. This is a footnote in page 1511 (class Serializable)
+ // of
+ // "The Java Class Libraries, Second Edition, Vol I".
+
+ /**
+ * Constructs a new instance of this class.
+ */
+ ObjectStreamClass() {
+ super();
+ }
+
+ /**
+ * Add an extra entry mapping a given class <code>cl</code> to its class
+ * descriptor, which will be computed (an ObjectStreamClass). If
+ * <code>computeSUID</code> is true, this method will compute the SUID for
+ * this class.
+ *
+ * @param cl
+ * a java.langClass for which to compute the corresponding
+ * descriptor
+ * @param computeSUID
+ * a boolean indicating if SUID should be computed or not.
+ * @return the computer class descriptor
+ */
+ private static ObjectStreamClass addToCache(Class cl, boolean computeSUID) {
+
+ ObjectStreamClass result = new ObjectStreamClass();
+ classesAndDescriptors.put(cl, result);
+
+ // Now we fill in the values
+ result.setName(cl.getName());
+ result.setClass(cl);
+ Class superclass = cl.getSuperclass();
+ if (superclass != null)
+ result.setSuperclass(lookup(superclass));
+
+ Field[] declaredFields = null;
+ if (computeSUID) {
+ declaredFields = cl.getDeclaredFields(); // Lazy computation, to
+ // save speed&space
+ result.setSerialVersionUID(computeSerialVersionUID(cl,
+ declaredFields));
+ }
+
+ boolean serializable = isSerializable(cl);
+ // Serializables need field descriptors
+ if (serializable && !cl.isArray()) {
+ if (declaredFields == null)
+ declaredFields = cl.getDeclaredFields(); // Lazy computation,
+ // to save
+ // speed&space
+ result.buildFieldDescriptors(declaredFields);
+ } else {
+ // Externalizables or arrays do not need FieldDesc info
+ result.setFields(new ObjectStreamField[0]);
+ }
+
+ byte flags = 0;
+ boolean externalizable = isExternalizable(cl);
+ if (externalizable)
+ flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
+ else if (serializable)
+ flags |= ObjectStreamConstants.SC_SERIALIZABLE;
+ if (getPrivateWriteObjectMethod(cl) != null)
+ flags |= ObjectStreamConstants.SC_WRITE_METHOD;
+ result.setFlags(flags);
+
+ return result;
+ }
+
+ /**
+ * Builds the collection of field descriptors for the receiver
+ *
+ * @param declaredFields
+ * collection of java.lang.reflect.Field for which to compute
+ * field descriptors
+ */
+ void buildFieldDescriptors(Field[] declaredFields) {
+ // We could find the field ourselves in the collection, but calling
+ // reflect is easier. Optimize if needed.
+ final Field f = ObjectStreamClass.fieldSerialPersistentFields(this
+ .forClass());
+ // If we could not find the emulated fields, we'll have to compute
+ // dumpable fields from reflect fields
+ boolean useReflectFields = f == null; // Assume we will compute the
+ // fields to dump based on the
+ // reflect fields
+
+ if (!useReflectFields) {
+ // The user declared a collection of emulated fields. Use them.
+ AccessController.doPrivileged(new PriviAction(f)); // We have to be
+ // able to fetch
+ // its value,
+ // even if it is
+ // private
+ try {
+ fields = (ObjectStreamField[]) f.get(null); // static field,
+ // pass null
+ } catch (IllegalAccessException ex) {
+ // WARNING - what should we do if we have no access ? This
+ // should not happen.
+ throw new RuntimeException();
+ }
+ } else {
+ // Compute collection of dumpable fields based on reflect fields
+ java.util.Vector serializableFields = new java.util.Vector(
+ declaredFields.length);
+ // Filter, we are only interested in fields that are serializable
+ for (int i = 0; i < declaredFields.length; i++) {
+ Field declaredField = declaredFields[i];
+ int modifiers = declaredField.getModifiers();
+ boolean shouldBeSerialized = !(Modifier.isStatic(modifiers) || Modifier
+ .isTransient(modifiers));
+ if (shouldBeSerialized) {
+ ObjectStreamField field = new ObjectStreamField(
+ declaredField.getName(), declaredField.getType());
+ serializableFields.addElement(field);
+ }
+ }
+
+ if (serializableFields.size() == 0) {
+ fields = NO_FIELDS; // If no serializable fields, share the
+ // special value so that users can test
+ } else {
+ // Now convert from Vector to array
+ fields = new ObjectStreamField[serializableFields.size()];
+ serializableFields.copyInto(fields);
+ }
+ }
+ ObjectStreamField.sortFields(fields);
+ // assign offsets
+ int primOffset = 0, objectOffset = 0;
+ for (int i = 0; i < fields.length; i++) {
+ Class type = fields[i].getType();
+ if (type.isPrimitive()) {
+ fields[i].offset = primOffset;
+ primOffset += primitiveSize(type);
+ } else {
+ fields[i].offset = objectOffset++;
+ }
+ }
+ }
+
+ /**
+ * Compute and return the Serial Version UID of the class <code>cl</code>.
+ * The value is computed based on the class name, superclass chain, field
+ * names, method names, modifiers, etc.
+ *
+ * @param cl
+ * a java.lang.Class for which to compute the SUID
+ * @param fields
+ * cl.getDeclaredFields(), pre-computed by the caller
+ * @return the value of SUID of this class
+ *
+ */
+ private static long computeSerialVersionUID(Class cl, Field[] fields) {
+ // First we should try to fetch the static slot
+ // 'static final long serialVersionUID'. If it is defined,
+ // return it. If not defined, we really need to compute SUID
+ // using SHAOutputStream
+
+ for (int i = 0; i < fields.length; i++) {
+ final Field field = fields[i];
+ if (Long.TYPE == field.getType()) {
+ int modifiers = field.getModifiers();
+ if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
+ if (UID_FIELD_NAME.equals(field.getName())) {
+ // We need to be able to see it even if we have no
+ // visibility.
+ // That is why we set accessible first (new API in
+ // reflect 1.2)
+ AccessController.doPrivileged(new PriviAction(field));
+ try {
+ return field.getLong(null); // Static field,
+ // parameter is ignored
+ } catch (IllegalAccessException iae) {
+ throw new RuntimeException(com.ibm.oti.util.Msg
+ .getString("K0071", iae.toString())); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+
+ java.security.MessageDigest digest;
+ try {
+ digest = java.security.MessageDigest.getInstance("SHA"); //$NON-NLS-1$
+ } catch (java.security.NoSuchAlgorithmException e) {
+ throw new Error(e.toString());
+ }
+ ByteArrayOutputStream sha = new ByteArrayOutputStream();
+ try {
+ DataOutputStream output = new DataOutputStream(sha);
+ output.writeUTF(cl.getName());
+ int classModifiers = CLASS_MODIFIERS_MASK & cl.getModifiers();
+ // Workaround for 1F9LOQO. Arrays are ABSTRACT in JDK, but that is
+ // not in the spec.
+ // Since we want to be compatible for X-loading, we have to pretend
+ // we have the same shape
+ boolean isArray = cl.isArray();
+ if (isArray) {
+ classModifiers |= Modifier.ABSTRACT;
+ }
+ // Required for JDK UID compatibility
+ if (cl.isInterface() && !Modifier.isPublic(classModifiers))
+ classModifiers &= ~Modifier.ABSTRACT;
+ output.writeInt(classModifiers);
+
+ // Workaround for 1F9LOQO. In JDK1.2 arrays implement Cloneable and
+ // Serializable
+ // but not in JDK 1.1.7. So, JDK 1.2 "pretends" arrays have no
+ // interfaces when
+ // computing SHA-1 to be compatible.
+ if (!isArray) {
+ // ------------------ Interface information
+ Class[] interfaces = cl.getInterfaces();
+ if (interfaces.length > 1) { // Only attempt to sort if
+ // really needed (saves object
+ // creation, etc)
+ // Sort them
+ Sorter.Comparator interfaceComparator = new Sorter.Comparator() {
+ public int compare(Object interface1, Object interface2) {
+ return ((Class) interface1).getName().compareTo(
+ ((Class) interface2).getName());
+ }
+ };
+ Sorter.sort(interfaces, interfaceComparator);
+ }
+
+ // Dump them
+ for (int i = 0; i < interfaces.length; i++)
+ output.writeUTF(interfaces[i].getName());
+ }
+
+ // ------------------ Field information
+
+ if (fields.length > 1) {// Only attempt to sort if really needed
+ // (saves object creation, etc)
+ // Sort them
+ Sorter.Comparator fieldComparator = new Sorter.Comparator() {
+ public int compare(Object field1, Object field2) {
+ return ((Field) field1).getName().compareTo(
+ ((Field) field2).getName());
+ }
+ };
+ Sorter.sort(fields, fieldComparator);
+ }
+
+ // Dump them
+ for (int i = 0; i < fields.length; i++) {
+ Field field = fields[i];
+ int modifiers = field.getModifiers();
+ boolean skip = Modifier.isPrivate(modifiers)
+ && (Modifier.isTransient(modifiers) || Modifier
+ .isStatic(modifiers));
+ if (!skip) {
+ // write name, modifier & "descriptor" of all but private
+ // static and private transient
+ output.writeUTF(field.getName());
+ output.writeInt(modifiers);
+ output
+ .writeUTF(descriptorForFieldSignature(getFieldSignature(field)));
+ }
+ }
+
+ // Normally constructors come before methods (because <init> <
+ // anyMethodName).
+ // However, <clinit> is an exception. Besides, reflect will not let
+ // us get to it.
+ if (hasClinit(cl)) {
+ // write name, modifier & "descriptor"
+ output.writeUTF(CLINIT_NAME);
+ output.writeInt(CLINIT_MODIFIERS);
+ output.writeUTF(CLINIT_SIGNATURE);
+ }
+
+ // ------------------ Constructor information
+ Constructor[] constructors = cl.getDeclaredConstructors();
+ if (constructors.length > 1) {// Only attempt to sort if really
+ // needed (saves object creation,
+ // etc)
+ // Sort them
+ Sorter.Comparator constructorComparator = new Sorter.Comparator() {
+ public int compare(Object constructor1, Object constructor2) {
+ // All constructors have same name, so we sort based on
+ // signature
+ return (getConstructorSignature((Constructor) constructor1)
+ .compareTo(getConstructorSignature((Constructor) constructor2)));
+ }
+ };
+ Sorter.sort(constructors, constructorComparator);
+ }
+
+ // Dump them
+ for (int i = 0; i < constructors.length; i++) {
+ Constructor constructor = constructors[i];
+ int modifiers = constructor.getModifiers();
+ boolean isPrivate = Modifier.isPrivate(modifiers);
+ if (!isPrivate) {
+ // write name, modifier & "descriptor" of all but private
+ // ones
+ output.writeUTF("<init>"); // constructor.getName() returns //$NON-NLS-1$
+ // the constructor name as
+ // typed, not the VM name
+ output.writeInt(modifiers);
+ output
+ .writeUTF(descriptorForSignature(getConstructorSignature(constructor)));
+ }
+ }
+
+ // ------------------ Method information
+ Method[] methods = cl.getDeclaredMethods();
+ if (methods.length > 1) {// Only attempt to sort if really needed
+ // (saves object creation, etc)
+ // Sort them
+ Sorter.Comparator methodComparator = new Sorter.Comparator() {
+ public int compare(Object method1, Object method2) {
+ int result = ((Method) method1).getName().compareTo(
+ ((Method) method2).getName());
+ if (result == 0) {
+ // same name, signature will tell which one comes
+ // first
+ return (getMethodSignature((Method) method1)
+ .compareTo(getMethodSignature((Method) method2)));
+ }
+ return result;
+ }
+ };
+ Sorter.sort(methods, methodComparator);
+ }
+
+ // Dump them
+ for (int i = 0; i < methods.length; i++) {
+ Method method = methods[i];
+ int modifiers = method.getModifiers();
+ boolean isPrivate = Modifier.isPrivate(modifiers);
+ if (!isPrivate) {
+ // write name, modifier & "descriptor" of all but private
+ // ones
+ output.writeUTF(method.getName());
+ output.writeInt(modifiers);
+ output
+ .writeUTF(descriptorForSignature(getMethodSignature(method)));
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(com.ibm.oti.util.Msg.getString("K0072", //$NON-NLS-1$
+ e.toString()));
+ }
+
+ // now compute the UID based on the SHA
+ byte[] hash = digest.digest(sha.toByteArray());
+ return littleEndianLongAt(hash, 0);
+
+ }
+
+ /**
+ * Return what the serializaton specification calls "descriptor" given a
+ * field signature. signature.
+ *
+ * @param signature
+ * a field signature
+ * @return containing the descriptor
+ *
+ */
+ private static String descriptorForFieldSignature(String signature) {
+ return signature.replace('.', '/');
+ }
+
+ /**
+ * Return what the serializaton specification calls "descriptor" given a
+ * method/constructor signature.
+ *
+ * @param signature
+ * a method or constructor signature
+ * @return containing the descriptor
+ *
+ */
+ private static String descriptorForSignature(String signature) {
+ return signature.substring(signature.indexOf("(")); //$NON-NLS-1$
+ }
+
+ /**
+ * Return the java.lang.reflect.Field <code>serialPersistentFields</code>
+ * if class <code>cl</code> implements it. Return null otherwise.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>java.lang.reflect.Field</code> if the class has
+ * serialPersistentFields <code>null</code> if the class does not
+ * have serialPersistentFields
+ */
+ static Field fieldSerialPersistentFields(Class cl) {
+ try {
+ Field f = cl.getDeclaredField("serialPersistentFields"); //$NON-NLS-1$
+ int modifiers = f.getModifiers();
+ if (Modifier.isStatic(modifiers) && Modifier.isPrivate(modifiers)
+ && Modifier.isFinal(modifiers))
+ if (f.getType() == ARRAY_OF_FIELDS)
+ return f;
+ } catch (NoSuchFieldException nsm) {
+ }
+ return null;
+ }
+
+ /**
+ * Return the class (java.lang.Class) that the receiver represents
+ *
+ * @return <code>null</code> if there is no corresponding class for the
+ * receiver <code>Class</code> The loaded class corresponding to
+ * the receiver
+ */
+ public Class forClass() {
+ if (resolvedClass != null) {
+ return (Class) resolvedClass.get();
+ }
+ return null;
+ }
+
+ /**
+ * Return a String representing the signature for a Constructor
+ * <code>c</code>.
+ *
+ * @param c
+ * a java.lang.reflect.Constructor for which to compute the
+ * signature
+ * @return the constructor's signature
+ *
+ */
+ static native String getConstructorSignature(Constructor c);
+
+ /**
+ * Answers a given field by name.
+ *
+ * @param name
+ * name of the desired field.
+ * @return a given field by name.
+ */
+
+ public ObjectStreamField getField(String name) {
+ ObjectStreamField[] allFields = fields();
+ for (int i = 0; i < allFields.length; i++) {
+ ObjectStreamField f = allFields[i];
+ if (f.getName().equals(name))
+ return f;
+ }
+ return null;
+ }
+
+ /**
+ * Answers the collection of field descriptors for the fields of the
+ * corresponding class
+ *
+ * @return the receiver's collection of declared fields for the class it
+ * represents
+ */
+
+ ObjectStreamField[] fields() {
+ if (fields == null) {
+ Class forCl = forClass();
+ if (forCl != null && isSerializable(forCl) && !forCl.isArray())
+ buildFieldDescriptors(forCl.getDeclaredFields());
+ else
+ // Externalizables or arrays do not need FieldDesc info
+ setFields(new ObjectStreamField[0]);
+ }
+ return fields;
+ }
+
+ /**
+ * Answers the collection of field descriptors for the fields of the
+ * corresponding class
+ *
+ * @return the receiver's collection of declared fields for the class it
+ * represents
+ */
+
+ public ObjectStreamField[] getFields() {
+ return (ObjectStreamField[]) fields().clone();
+ }
+
+ /**
+ * Answers the collection of field descriptors for the input fields of the
+ * corresponding class
+ *
+ * @return the receiver's collection of input fields for the class it
+ * represents
+ */
+
+ ObjectStreamField[] getLoadFields() {
+ return loadFields;
+ }
+
+ /**
+ * Return a String representing the signature for a field <code>f</code>.
+ *
+ * @param f
+ * a java.lang.reflect.Field for which to compute the signature
+ * @return the field's signature
+ *
+ */
+ private static native String getFieldSignature(Field f);
+
+ /**
+ * Answers the flags for this descriptor, where possible combined values are
+ *
+ * ObjectStreamConstants.SC_WRITE_METHOD
+ * ObjectStreamConstants.SC_SERIALIZABLE
+ * ObjectStreamConstants.SC_EXTERNALIZABLE
+ *
+ * @return byte the receiver's flags for the class it represents
+ */
+ byte getFlags() {
+ return flags;
+ }
+
+ /**
+ * Return a String representing the signature for a method <code>m</code>.
+ *
+ * @param m
+ * a java.lang.reflect.Method for which to compute the signature
+ * @return the method's signature
+ *
+ */
+ static native String getMethodSignature(Method m);
+
+ /**
+ * Answers the name of the class represented by the receiver
+ *
+ * @return fully qualified name of the class the receiver represents
+ */
+ public String getName() {
+ return className;
+ }
+
+ /**
+ * Answers the Serial Version User ID of the class represented by the
+ * receiver
+ *
+ * @return SUID for the class represented by the receiver
+ */
+ public long getSerialVersionUID() {
+ return svUID;
+ }
+
+ /**
+ * Answers the descriptor (ObjectStreamClass) of the superclass of the class
+ * represented by the receiver.
+ *
+ * @return an ObjectStreamClass representing the superclass of the class
+ * represented by the receiver.
+ */
+ ObjectStreamClass getSuperclass() {
+ return superclass;
+ }
+
+ /**
+ * Return true if the given class <code>cl</code> has the
+ * compiler-generated method <code>clinit</code>. Even though it is
+ * compiler-generated, it is used by the serialization code to compute SUID.
+ * This is unfortunate, since it may depend on compiler optimizations in
+ * some cases.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>true</code> if the class has <clinit> <code>false</code>
+ * if the class does not have <clinit>
+ */
+ private static native boolean hasClinit(Class cl);
+
+ /**
+ * Return true if the given class <code>cl</code> implements private
+ * method <code>readObject()</code>.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>true</code> if the class implements readObject
+ * <code>false</code> if the class does not implement readObject
+ */
+ static Method getPrivateReadObjectMethod(Class cl) {
+ try {
+ Method method = cl
+ .getDeclaredMethod("readObject", READ_PARAM_TYPES); //$NON-NLS-1$
+ if (Modifier.isPrivate(method.getModifiers())
+ && method.getReturnType() == VOID_CLASS) {
+ return method;
+ }
+ } catch (NoSuchMethodException nsm) {
+ }
+ return null;
+ }
+
+ /**
+ * Return true if the given class <code>cl</code> implements private
+ * method <code>readObject()</code>.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>true</code> if the class implements readObject
+ * <code>false</code> if the class does not implement readObject
+ */
+ static Method getPrivateReadObjectNoDataMethod(Class cl) {
+ try {
+ Method method = cl.getDeclaredMethod("readObjectNoData", //$NON-NLS-1$
+ EMPTY_CONSTRUCTOR_PARAM_TYPES);
+ if (Modifier.isPrivate(method.getModifiers())
+ && method.getReturnType() == VOID_CLASS) {
+ return method;
+ }
+ } catch (NoSuchMethodException nsm) {
+ }
+ return null;
+ }
+
+ /**
+ * Return true if the given class <code>cl</code> implements private
+ * method <code>writeObject()</code>.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>true</code> if the class implements writeObject
+ * <code>false</code> if the class does not implement writeObject
+ */
+ static Method getPrivateWriteObjectMethod(Class cl) {
+ try {
+ Method method = cl.getDeclaredMethod("writeObject", //$NON-NLS-1$
+ WRITE_PARAM_TYPES);
+ if (Modifier.isPrivate(method.getModifiers())
+ && method.getReturnType() == VOID_CLASS) {
+ return method;
+ }
+ } catch (NoSuchMethodException nsm) {
+ }
+ return null;
+ }
+
+ /**
+ * Return true if instances of class <code>cl</code> are Externalizable,
+ * false otherwise.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>true</code> if instances of the class are Externalizable
+ * <code>false</code> if instances of the class are not
+ * Externalizable
+ *
+ * @see Object#hashCode
+ */
+ static boolean isExternalizable(Class cl) {
+ return EXTERNALIZABLE.isAssignableFrom(cl);
+ }
+
+ /**
+ * Return true if the typecode
+ * <code>typecode<code> describes a primitive type
+ *
+ * @param typecode a char describing the typecode
+ * @return <code>true</code> if the typecode represents a primitive type
+ * <code>false</code> if the typecode represents an Object type (including arrays)
+ *
+ * @see Object#hashCode
+ */
+ static boolean isPrimitiveType(char typecode) {
+ return !(typecode == '[' || typecode == 'L');
+ }
+
+ /**
+ * Return true if instances of class <code>cl</code> are Serializable,
+ * false otherwise.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>true</code> if instances of the class are Serializable
+ * <code>false</code> if instances of the class are not
+ * Serializable
+ *
+ * @see Object#hashCode
+ */
+ static boolean isSerializable(Class cl) {
+ return SERIALIZABLE.isAssignableFrom(cl);
+ }
+
+ /**
+ * Return a little endian long stored in a given position of the buffer
+ *
+ * @param buffer
+ * a byte array with the byte representation of the number
+ * @param position
+ * index where the number starts in the byte array
+ * @return the number that was stored in little endian format
+ */
+ private static long littleEndianLongAt(byte[] buffer, int position) {
+ long result = 0;
+ for (int i = position + 7; i >= position; i--)
+ result = (result << 8) + (buffer[i] & 0xff);
+ return result;
+ }
+
+ /**
+ * Return the descriptor (ObjectStreamClass) corresponding to the class
+ * <code>cl</code>. If the class is not Serializable or Externalizable,
+ * null is returned.
+ *
+ * @param cl
+ * a java.langClass for which to obtain the corresponding
+ * descriptor
+ * @return <code>null</code> if instances of the class <code>cl</code>
+ * are not Serializable or Externalizable
+ * <code>ObjectStreamClass</code> The corresponding descriptor if
+ * the class <code>cl</code> is Serializable or Externalizable
+ */
+ public static ObjectStreamClass lookup(Class cl) {
+ boolean serializable = isSerializable(cl);
+ boolean externalizable = isExternalizable(cl);
+
+ // Has to be either Serializable or Externalizable
+ if (!serializable && !externalizable)
+ return null;
+
+ return lookupStreamClass(cl, true);
+ }
+
+ /**
+ * Return the descriptor (ObjectStreamClass) corresponding to the class
+ * <code>cl</code>. Returns an ObjectStreamClass even if instances of the
+ * class cannot be serialized
+ *
+ * @param cl
+ * a java.langClass for which to obtain the corresponding
+ * descriptor
+ * @return the corresponding descriptor
+ */
+ static ObjectStreamClass lookupStreamClass(Class cl) {
+ return lookupStreamClass(cl, isSerializable(cl) || isExternalizable(cl));
+ }
+
+ /**
+ * Return the descriptor (ObjectStreamClass) corresponding to the class
+ * <code>cl</code>. Returns an ObjectStreamClass even if instances of the
+ * class cannot be serialized
+ *
+ * @param cl
+ * a <code>java.langClass</code> for which to obtain the
+ * corresponding descriptor
+ * @param computeSUID
+ * a boolean indicating if SUID should be computed or not.
+ * @return the corresponding descriptor
+ */
+ private static synchronized ObjectStreamClass lookupStreamClass(Class cl,
+ boolean computeSUID) {
+ // Synchronized because of the lookup table 'classesAndDescriptors'
+ ObjectStreamClass cachedValue = (ObjectStreamClass) classesAndDescriptors
+ .get(cl);
+ if (cachedValue != null)
+ return cachedValue;
+ return addToCache(cl, computeSUID);
+ }
+
+ /**
+ * Return the java.lang.reflect.Method <code>readResolve</code> if class
+ * <code>cl</code> implements it. Return null otherwise.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>java.lang.reflect.Method</code> if the class implements
+ * readResolve <code>null</code> if the class does not implement
+ * readResolve
+ */
+ static Method methodReadResolve(Class cl) {
+ Class search = cl;
+ while (search != null) {
+ try {
+ Method method = search.getDeclaredMethod("readResolve", null); //$NON-NLS-1$
+ if (search == cl
+ || (method.getModifiers() & Modifier.PRIVATE) == 0)
+ return method;
+ return null;
+ } catch (NoSuchMethodException nsm) {
+ }
+ search = search.getSuperclass();
+ }
+ return null;
+ }
+
+ /**
+ * Return the java.lang.reflect.Method <code>writeReplace</code> if class
+ * <code>cl</code> implements it. Return null otherwise.
+ *
+ * @param cl
+ * a java.lang.Class which to test
+ * @return <code>java.lang.reflect.Method</code> if the class implements
+ * writeReplace <code>null</code> if the class does not implement
+ * writeReplace
+ */
+ static Method methodWriteReplace(Class cl) {
+ Class search = cl;
+ while (search != null) {
+ try {
+ Method method = search.getDeclaredMethod("writeReplace", null); //$NON-NLS-1$
+ if (search == cl
+ || (method.getModifiers() & Modifier.PRIVATE) == 0)
+ return method;
+ return null;
+ } catch (NoSuchMethodException nsm) {
+ }
+ search = search.getSuperclass();
+ }
+ return null;
+ }
+
+ /**
+ * Set the class (java.lang.Class) that the receiver represents
+ *
+ * @param c
+ * aClass, the new class that the receiver describes
+ */
+ void setClass(Class c) {
+ resolvedClass = new WeakReference(c);
+ }
+
+ /**
+ * Set the collection of field descriptors for the fields of the
+ * corresponding class
+ *
+ * @param f
+ * ObjectStreamField[], the receiver's new collection of declared
+ * fields for the class it represents
+ */
+ void setFields(ObjectStreamField[] f) {
+ fields = f;
+ }
+
+ /**
+ * Set the collection of field descriptors for the input fields of the
+ * corresponding class
+ *
+ * @param f
+ * ObjectStreamField[], the receiver's new collection of input
+ * fields for the class it represents
+ */
+ void setLoadFields(ObjectStreamField[] f) {
+ loadFields = f;
+ }
+
+ /**
+ * Set the flags for this descriptor, where possible combined values are
+ *
+ * ObjectStreamConstants.SC_WRITE_METHOD
+ * ObjectStreamConstants.SC_SERIALIZABLE
+ * ObjectStreamConstants.SC_EXTERNALIZABLE
+ *
+ * @param b
+ * byte, the receiver's new flags for the class it represents
+ */
+ void setFlags(byte b) {
+ flags = b;
+ }
+
+ /**
+ * Set the name of the class represented by the receiver
+ *
+ * @param newName
+ * a String, the new fully qualified name of the class the
+ * receiver represents
+ */
+ void setName(String newName) {
+ className = newName;
+ }
+
+ /**
+ * Set the Serial Version User ID of the class represented by the receiver
+ *
+ * @param l
+ * a long, the new SUID for the class represented by the receiver
+ */
+ void setSerialVersionUID(long l) {
+ svUID = l;
+ }
+
+ /**
+ * Set the descriptor for the superclass of the class described by the
+ * receiver
+ *
+ * @param c
+ * an ObjectStreamClass, the new ObjectStreamClass for the
+ * superclass of the class represented by the receiver
+ */
+ void setSuperclass(ObjectStreamClass c) {
+ superclass = c;
+ }
+
+ private int primitiveSize(Class type) {
+ if (type == Byte.TYPE || type == Boolean.TYPE)
+ return 1;
+ if (type == Short.TYPE || type == Character.TYPE)
+ return 2;
+ if (type == Integer.TYPE || type == Float.TYPE)
+ return 4;
+ if (type == Long.TYPE || type == Double.TYPE)
+ return 8;
+ return 0;
+ }
+
+ /**
+ * Answers a string containing a concise, human-readable description of the
+ * receiver.
+ *
+ * @return a printable representation for the receiver.
+ */
+ public String toString() {
+ return getName() + ": static final long serialVersionUID =" //$NON-NLS-1$
+ + getSerialVersionUID() + "L;"; //$NON-NLS-1$
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamConstants.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamConstants.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamConstants.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamConstants.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,94 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+
+/**
+ * Helper interface with constants used by the serialization implementation.
+ *
+ */
+
+public abstract interface ObjectStreamConstants {
+
+ /**
+ * Used for the stream header
+ */
+ public static final short STREAM_MAGIC = (short) 0xaced;
+
+ /**
+ * Used for the stream header
+ */
+ public static final short STREAM_VERSION = 5;
+
+ // These are tags to indicate the stream contents
+ public static final byte TC_BASE = 0x70;
+
+ public static final byte TC_NULL = (byte) 0x70;
+
+ public static final byte TC_REFERENCE = (byte) 0x71;
+
+ public static final byte TC_CLASSDESC = (byte) 0x72;
+
+ public static final byte TC_OBJECT = (byte) 0x73;
+
+ public static final byte TC_STRING = (byte) 0x74;
+
+ public static final byte TC_ARRAY = (byte) 0x75;
+
+ public static final byte TC_CLASS = (byte) 0x76;
+
+ public static final byte TC_BLOCKDATA = (byte) 0x77;
+
+ public static final byte TC_ENDBLOCKDATA = (byte) 0x78;
+
+ public static final byte TC_RESET = (byte) 0x79;
+
+ public static final byte TC_BLOCKDATALONG = (byte) 0x7A;
+
+ public static final byte TC_EXCEPTION = (byte) 0x7B;
+
+ public static final byte TC_LONGSTRING = (byte) 0x7C;
+
+ public static final byte TC_PROXYCLASSDESC = (byte) 0x7D;
+
+ public static final byte TC_MAX = 0x7D;
+
+ /**
+ * The first object dumped gets assigned this handle/ID
+ */
+ public static final int baseWireHandle = 0x007e0000;
+
+ public static final int PROTOCOL_VERSION_1 = 1;
+
+ public static final int PROTOCOL_VERSION_2 = 2;
+
+ public static final SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION = new SerializablePermission(
+ "enableSubclassImplementation"); //$NON-NLS-1$
+
+ public static final SerializablePermission SUBSTITUTION_PERMISSION = new SerializablePermission(
+ "enableSubstitution"); //$NON-NLS-1$
+
+ // Flags that indicate if the object was serializable, externalizable
+ // and had a writeObject method when dumped.
+ public static final byte SC_WRITE_METHOD = 0x01; // If SC_SERIALIZABLE
+
+ public static final byte SC_SERIALIZABLE = 0x02;
+
+ public static final byte SC_EXTERNALIZABLE = 0x04;
+
+ public static final byte SC_BLOCK_DATA = 0x08; // If SC_EXTERNALIZABLE
+
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,55 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+
+/**
+ * This is the superclass of all exceptions that can happen when serializing or
+ * deserialing objects. The state of the stream is unknown when one of these
+ * serialization-related exceptions are thrown.
+ *
+ * @see InvalidObjectException
+ * @see NotActiveException
+ * @see NotSerializableException
+ * @see OptionalDataException
+ * @see StreamCorruptedException
+ * @see WriteAbortedException
+ *
+ */
+public abstract class ObjectStreamException extends IOException {
+
+ static final long serialVersionUID = 7260898174833392607L;
+
+ /**
+ * Constructs a new instance of this class with its walkback filled in.
+ *
+ */
+ protected ObjectStreamException() {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of this class with its walkback and message
+ * filled in.
+ *
+ * @param detailMessage
+ * The detail message for the exception.
+ */
+ protected ObjectStreamException(String detailMessage) {
+ super(detailMessage);
+ }
+
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamField.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamField.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamField.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/ObjectStreamField.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,339 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+
+import java.lang.ref.WeakReference;
+
+import com.ibm.oti.util.Sorter;
+
+/**
+ * This class represents object fields that are saved to the stream, by
+ * serialization. Classes can define the collection of fields to be dumped,
+ * which can differ from the actual object's declared fields.
+ *
+ * @see ObjectOutputStream#writeFields()
+ * @see ObjectInputStream#readFields()
+ *
+ */
+public class ObjectStreamField extends Object implements Comparable {
+ private String name; // Declared name of the field
+
+ private Object type; // Declared type of the field
+
+ int offset; // offset of this field in the object
+
+ private String typeString; // Cached version of intern'ed type String.
+
+ private boolean unshared = false;
+
+ /**
+ * Constructs an ObjectStreamField with the given name and the given type
+ *
+ * @param name
+ * a String, the name of the field
+ * @param cl
+ * A Class object representing the type of the field
+ */
+ public ObjectStreamField(String name, Class cl) {
+ if (name != null && cl != null) {
+ this.name = name;
+ this.type = new WeakReference(cl);
+ } else
+ throw new NullPointerException();
+ }
+
+ /**
+ * Constructs an ObjectStreamField with the given name and the given type
+ *
+ * @param name
+ * a String, the name of the field
+ * @param cl
+ * A Class object representing the type of the field
+ * @param unshared
+ * write and read the field unshared
+ */
+ public ObjectStreamField(String name, Class cl, boolean unshared) {
+ if (name != null && cl != null) {
+ this.name = name;
+ if (cl.getClassLoader() == null) {
+ this.type = cl;
+ } else {
+ this.type = new WeakReference(cl);
+ }
+ this.unshared = unshared;
+ } else
+ throw new NullPointerException();
+ }
+
+ /**
+ * Constructs an ObjectStreamField with the given name and the given type.
+ * The type may be null.
+ *
+ * @param signature
+ * A String representing the type of the field
+ * @param name
+ * a String, the name of the field, or null
+ */
+ ObjectStreamField(String signature, String name) {
+ if (name != null) {
+ this.name = name;
+ this.typeString = signature.replace('.', '/');
+ } else
+ throw new NullPointerException();
+ }
+
+ /**
+ * Comparing the receiver to the parameter, according to the Comparable
+ * interface.
+ *
+ * @param o
+ * The object to compare against
+ *
+ * @return -1 if the receiver is "smaller" than the parameter. 0 if the
+ * receiver is "equal" to the parameter. 1 if the receiver is
+ * "greater" than the parameter.
+ *
+ */
+ public int compareTo(Object o) {
+ ObjectStreamField f = (ObjectStreamField) o;
+ boolean thisPrimitive = this.isPrimitive();
+ boolean fPrimitive = f.isPrimitive();
+
+ // If one is primitive and the other isn't, we have enough info to
+ // compare
+ if (thisPrimitive != fPrimitive)
+ return thisPrimitive ? -1 : 1;
+
+ // Either both primitives or both not primitives. Compare based on name.
+ return this.getName().compareTo(f.getName());
+ }
+
+ /**
+ * Return the name of the field the receiver represents
+ *
+ * @return a String, the name of the field
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Return the offset of this field in the object
+ *
+ * @return an int, the offset
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ /**
+ * Return the type of the field the receiver represents
+ *
+ * @return A Class object representing the type of the field
+ */
+ public Class getType() {
+ if (type instanceof WeakReference) {
+ return (Class) ((WeakReference) type).get();
+ }
+ return (Class) type;
+ }
+
+ /**
+ * Return the type code that corresponds to the class the receiver
+ * represents
+ *
+ * @return A char, the typecode of the class
+ */
+ public char getTypeCode() {
+ Class t = getType();
+ if (t == Integer.TYPE)
+ return 'I';
+ if (t == Byte.TYPE)
+ return 'B';
+ if (t == Character.TYPE)
+ return 'C';
+ if (t == Short.TYPE)
+ return 'S';
+ if (t == Boolean.TYPE)
+ return 'Z';
+ if (t == Long.TYPE)
+ return 'J';
+ if (t == Float.TYPE)
+ return 'F';
+ if (t == Double.TYPE)
+ return 'D';
+ if (t.isArray())
+ return '[';
+ return 'L';
+ }
+
+ /**
+ * Return the type signature used by the VM to represent the type for this
+ * field.
+ *
+ * @return A String, the signature for the class of this field.
+ */
+ public String getTypeString() {
+ if (typeString == null)
+ typeString = computeTypeString().intern();
+ return typeString;
+ }
+
+ /**
+ * Return the type signature used by the VM to represent the type for this
+ * field.
+ *
+ * @return A String, the signature for the class of this field.
+ */
+ private String computeTypeString() {
+ // NOTE: this is very similar to Class.getSignature(). Unfortunately
+ // we can't call that due to visibility restrictions.
+
+ Class t = getType();
+ if (t.isArray())
+ return t.getName().replace('.', '/');
+
+ if (isPrimitive()) {
+ // Special cases for each base type.
+ // NOTE: In how many places do we find this same pattern in java ?
+ // getTypeCode() return character, here we return String.
+ if (t == Integer.TYPE)
+ return "I"; //$NON-NLS-1$
+ if (t == Byte.TYPE)
+ return "B"; //$NON-NLS-1$
+ if (t == Character.TYPE)
+ return "C"; //$NON-NLS-1$
+ if (t == Short.TYPE)
+ return "S"; //$NON-NLS-1$
+ if (t == Boolean.TYPE)
+ return "Z"; //$NON-NLS-1$
+ if (t == Long.TYPE)
+ return "J"; //$NON-NLS-1$
+ if (t == Float.TYPE)
+ return "F"; //$NON-NLS-1$
+ if (t == Double.TYPE)
+ return "D"; //$NON-NLS-1$
+ throw new RuntimeException();
+ }
+
+ // General case.
+ return ("L" + t.getName() + ';').replace('.', '/'); //$NON-NLS-1$
+ }
+
+ /**
+ * Return a boolean indicating whether the class of this field is a
+ * primitive type or not
+ *
+ * @return true if the type of this field is a primitive type false if the
+ * type of this field is a regular class.
+ */
+ public boolean isPrimitive() {
+ Class t = getType();
+ return t != null && t.isPrimitive();
+ }
+
+ /**
+ * Set the offset this field represents in the object
+ *
+ * @param newValue
+ * an int, the offset
+ */
+ protected void setOffset(int newValue) {
+ this.offset = newValue;
+ }
+
+ /**
+ * Answers a string containing a concise, human-readable description of the
+ * receiver.
+ *
+ * @return a printable representation for the receiver.
+ */
+ public String toString() {
+ return this.getClass().getName() + '(' + getName() + ':' + getType()
+ + ')';
+ }
+
+ /**
+ * Sorts the fields for dumping. Primitive types come first, then regular
+ * types.
+ *
+ * @param fields
+ * ObjectStreamField[] fields to be sorted
+ */
+ static void sortFields(ObjectStreamField[] fields) {
+ // Sort if necessary
+ if (fields.length > 1) {
+ Sorter.Comparator fieldDescComparator = new Sorter.Comparator() {
+ public int compare(Object o1, Object o2) {
+ ObjectStreamField f1 = (ObjectStreamField) o1;
+ ObjectStreamField f2 = (ObjectStreamField) o2;
+ return f1.compareTo(f2);
+ }
+ };
+ Sorter.sort(fields, fieldDescComparator);
+ }
+ }
+
+ void resolve(ClassLoader loader) {
+ if (typeString.length() == 1) {
+ switch (typeString.charAt(0)) {
+ case 'I':
+ type = Integer.TYPE;
+ return;
+ case 'B':
+ type = Byte.TYPE;
+ return;
+ case 'C':
+ type = Character.TYPE;
+ return;
+ case 'S':
+ type = Short.TYPE;
+ return;
+ case 'Z':
+ type = Boolean.TYPE;
+ return;
+ case 'J':
+ type = Long.TYPE;
+ return;
+ case 'F':
+ type = Float.TYPE;
+ return;
+ case 'D':
+ type = Double.TYPE;
+ return;
+ }
+ }
+ String className = typeString.replace('/', '.');
+ if (className.charAt(0) == 'L') {
+ // remove L and ;
+ className = className.substring(1, className.length() - 1);
+ }
+ try {
+ Class cl = Class.forName(className, false, loader);
+ if (cl.getClassLoader() == null) {
+ type = cl;
+ } else {
+ type = new WeakReference(cl);
+ }
+ } catch (ClassNotFoundException e) {
+ }
+ }
+
+ boolean getUnshared() {
+ return unshared;
+ }
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OptionalDataException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OptionalDataException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OptionalDataException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OptionalDataException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,57 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+/**
+ * When readObject() encounters primitive types (int, char, etc) instead of an
+ * object instance in the input stream, this type of exception will be thrown.
+ *
+ * @see ObjectInputStream#available()
+ * @see ObjectInputStream#readObject()
+ * @see ObjectInputStream#skipBytes(int)
+ */
+public class OptionalDataException extends ObjectStreamException {
+
+ static final long serialVersionUID = -8011121865681257820L;
+
+ /**
+ * If true it means there is no more primitive data available.
+ */
+ public boolean eof;
+
+ /**
+ * Number of bytes of primitive data (int, char, long, etc).
+ */
+ public int length;
+
+ /**
+ * Constructs a new instance of this class with its walkback filled in.
+ */
+ OptionalDataException() {
+ super();
+ }
+
+ /**
+ * Constructs a new instance of this class with its walkback and message
+ * filled in.
+ *
+ * @param detailMessage
+ * String The detail message for the exception.
+ */
+ OptionalDataException(String detailMessage) {
+ super(detailMessage);
+ }
+
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OutputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OutputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OutputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,118 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+
+/**
+ * OutputStream is an abstract class for all byte output streams. It provides
+ * basic method implementations for writing bytes to a stream.
+ *
+ * @see InputStream
+ */
+
+public abstract class OutputStream {
+ /**
+ * This constructor does nothing interesting. Provided for signature
+ * compatibility.
+ *
+ */
+
+ public OutputStream() {
+ /*empty*/
+ }
+
+ /**
+ * Close this OutputStream. Concrete implementations of this class should
+ * free any resources during close. This implementation does nothing.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this OutputStream.
+ */
+
+ public void close() throws IOException {
+ /*empty*/
+ }
+
+ /**
+ * Flush this OutputStream. Concrete implementations of this class should
+ * ensure any pending writes to the underlying stream are written out when
+ * this method is envoked. This implementation does nothing.
+ *
+ * @throws IOException
+ * If an error occurs attempting to flush this OutputStream.
+ */
+
+ public void flush() throws IOException {
+ /*empty */
+ }
+
+ /**
+ * Writes the entire contents of the byte array <code>buffer</code> to
+ * this OutputStream.
+ *
+ * @param buffer
+ * the buffer to be written
+ *
+ * @throws IOException
+ * If an error occurs attempting to write to this OutputStream.
+ */
+
+ public void write(byte buffer[]) throws IOException {
+ write(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Writes <code>count</code> <code>bytes</code> from the byte array
+ * <code>buffer</code> starting at <code>offset</code> to this
+ * OutputStream.
+ *
+ * @param buffer
+ * the buffer to be written
+ * @param offset
+ * offset in buffer to get bytes
+ * @param count
+ * number of bytes in buffer to write
+ *
+ * @throws IOException
+ * If an error occurs attempting to write to this OutputStream.
+ * @throws IndexOutOfBoundsException
+ * If offset or count are outside of bounds.
+ */
+
+ public void write(byte buffer[], int offset, int count) throws IOException {
+ // avoid int overflow, check null buffer
+ if (offset <= buffer.length && 0 <= offset && 0 <= count
+ && count <= buffer.length - offset) {
+ for (int i = offset; i < offset + count; i++)
+ write(buffer[i]);
+ } else
+ throw new ArrayIndexOutOfBoundsException(com.ibm.oti.util.Msg
+ .getString("K002f")); //$NON-NLS-1$
+ }
+
+ /**
+ * Writes the specified byte <code>oneByte</code> to this OutputStream.
+ * Only the low order byte of <code>oneByte</code> is written.
+ *
+ * @param oneByte
+ * the byte to be written
+ *
+ * @throws IOException
+ * If an error occurs attempting to write to this OutputStream.
+ */
+
+ public abstract void write(int oneByte) throws IOException;
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OutputStreamWriter.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OutputStreamWriter.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OutputStreamWriter.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/OutputStreamWriter.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,294 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.security.AccessController;
+
+import com.ibm.oti.util.PriviAction;
+
+/**
+ * OutputStreamWriter is a class for turning a character output stream into a
+ * byte output stream. The conversion of Unicode characters to their byte
+ * equivalents is determinded by the converter used. By default, the encoding is
+ * ISO8859_1 (ISO-Latin-1) but can be changed by calling the constructor which
+ * takes an encoding.
+ *
+ *
+ * @see InputStreamReader
+ */
+
+public class OutputStreamWriter extends Writer {
+ private OutputStream out;
+
+ private CharsetEncoder encoder;
+
+ private ByteBuffer bytes = ByteBuffer.allocate(8192);
+
+ /**
+ * Constructs a new OutputStreamWriter using <code>out</code> as the
+ * OutputStream to write converted characters to. The default character
+ * encoding is used (see class description).
+ *
+ * @param out
+ * the non-null OutputStream to write converted bytes to.
+ */
+
+ public OutputStreamWriter(OutputStream out) {
+ super(out);
+ this.out = out;
+ String encoding = (String) AccessController
+ .doPrivileged(new PriviAction("file.encoding", "ISO8859_1")); //$NON-NLS-1$ //$NON-NLS-2$
+ encoder = Charset.forName(encoding).newEncoder();
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ }
+
+ /**
+ * Constructs a new OutputStreamWriter using <code>out</code> as the
+ * OutputStream to write converted characters to and <code>end</code> as
+ * the character encoding. If the encoding cannot be found, an
+ * UnsupportedEncodingException error is thrown.
+ *
+ * @param out
+ * the non-null OutputStream to write converted bytes to.
+ * @param enc
+ * the non-null String describing the desired character encoding.
+ *
+ * @throws UnsupportedEncodingException
+ * if the encoding cannot be found.
+ */
+
+ public OutputStreamWriter(OutputStream out, final String enc)
+ throws UnsupportedEncodingException {
+ super(out);
+ enc.length();
+ this.out = out;
+ try {
+ encoder = Charset.forName(enc).newEncoder();
+ } catch (Exception e) {
+ throw new UnsupportedEncodingException(enc);
+ }
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ }
+
+ /**
+ * Constructs a new OutputStreamWriter using <code>out</code> as the
+ * OutputStream to write converted characters to and <code>cs</code> as
+ * the character encoding.
+ *
+ *
+ * @param out
+ * the non-null OutputStream to write converted bytes to.
+ * @param cs
+ * the non-null Charset which specify the character encoding.
+ */
+ public OutputStreamWriter(OutputStream out, Charset cs) {
+ super(out);
+ this.out = out;
+ encoder = cs.newEncoder();
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ }
+
+ /**
+ * Constructs a new OutputStreamWriter using <code>out</code> as the
+ * OutputStream to write converted characters to and <code>enc</code> as
+ * the character encoding.
+ *
+ *
+ * @param out
+ * the non-null OutputStream to write converted bytes to.
+ * @param enc
+ * the non-null CharsetEncoder which used to character encoding.
+ */
+ public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
+ super(out);
+ enc.charset();
+ this.out = out;
+ encoder = enc;
+ }
+
+ /**
+ * Close this OutputStreamWriter. This implementation first flushes the
+ * buffer and the target OutputStream. The OutputStream is then closed and
+ * the resources for the buffer and converter are freed.
+ * <p>
+ * Only the first invocation of this method has any effect. Subsequent calls
+ * do no work.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this
+ * OutputStreamWriter.
+ */
+ public void close() throws IOException {
+ synchronized (lock) {
+ if (encoder != null) {
+ flush();
+ out.flush();
+ out.close();
+ encoder = null;
+ bytes = null;
+ }
+ }
+ }
+
+ /**
+ * Flush this OutputStreamWriter. This implementation ensures all buffered
+ * bytes are written to the target OutputStream. After writing the bytes,
+ * the target OutputStream is then flushed.
+ *
+ * @throws IOException
+ * If an error occurs attempting to flush this
+ * OutputStreamWriter.
+ */
+
+ public void flush() throws IOException {
+ synchronized (lock) {
+ checkStatus();
+ int position;
+ if ((position = bytes.position()) > 0) {
+ bytes.flip();
+ out.write(bytes.array(), 0, position);
+ bytes.clear();
+ }
+ out.flush();
+ }
+ }
+
+ private void checkStatus() throws IOException {
+ if (encoder == null) {
+ throw new IOException("This writer has been closed!"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Answer the String which identifies the encoding used to convert
+ * characters to bytes. The value <code>null</code> is returned if this
+ * Writer has been closed.
+ *
+ * @return the String describing the converter or null if this Writer is
+ * closed.
+ */
+
+ public String getEncoding() {
+ return encoder.charset().name();
+ }
+
+ /**
+ * Writes <code>count</code> characters starting at <code>offset</code>
+ * in <code>buf</code> to this Writer. The characters are immediately
+ * converted to bytes by the character converter and stored in a local
+ * buffer. If the buffer becomes full as a result of this write, this Writer
+ * is flushed.
+ *
+ * @param buf
+ * the non-null array containing characters to write.
+ * @param offset
+ * offset in buf to retrieve characters
+ * @param count
+ * maximum number of characters to write
+ *
+ * @throws IOException
+ * If this OuputStreamWriter has already been closed or some
+ * other IOException occurs.
+ * @throws ArrayIndexOutOfBoundsException
+ * If offset or count are outside of bounds.
+ */
+ public void write(char[] buf, int offset, int count) throws IOException {
+ if (offset < 0 || count < 0 || offset + count > buf.length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ CharBuffer chars = CharBuffer.wrap(buf, offset, count);
+ convert(chars);
+ }
+
+ private void convert(CharBuffer chars) throws IOException {
+ synchronized (lock) {
+ checkStatus();
+ CoderResult result = encoder.encode(chars, bytes, true);
+ while (true) {
+ if (result.isError()) {
+ throw new IOException(result.toString());
+ } else if (result.isOverflow()) {
+ //flush the output buffer
+ flush();
+ result = encoder.encode(chars, bytes, true);
+ continue;
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Writes out the character <code>oneChar</code> to this Writer. The
+ * low-order 2 bytes are immediately converted to bytes by the character
+ * converter and stored in a local buffer. If the buffer becomes full as a
+ * result of this write, this Writer is flushed.
+ *
+ * @param oneChar
+ * the character to write
+ *
+ * @throws IOException
+ * If this OuputStreamWriter has already been closed or some
+ * other IOException occurs.
+ */
+ public void write(int oneChar) throws IOException {
+ synchronized (lock) {
+ checkStatus();
+ CharBuffer chars = CharBuffer.wrap(new char[] { (char) oneChar });
+ convert(chars);
+ }
+ }
+
+ /**
+ * Writes <code>count</code> characters starting at <code>offset</code>
+ * in <code>str</code> to this Writer. The characters are immediately
+ * converted to bytes by the character converter and stored in a local
+ * buffer. If the buffer becomes full as a result of this write, this Writer
+ * is flushed.
+ *
+ * @param str
+ * the non-null String containing characters to write.
+ * @param offset
+ * offset in str to retrieve characters
+ * @param count
+ * maximum number of characters to write
+ *
+ * @throws IOException
+ * If this OuputStreamWriter has already been closed or some
+ * other IOException occurs.
+ * @throws StringIndexOutOfBoundsException
+ * If offset or count are outside of bounds.
+ */
+ public void write(String str, int offset, int count) throws IOException {
+ // avoid int overflow
+ if (offset < 0 || count < 0 || offset + count > str.length()) {
+ throw new StringIndexOutOfBoundsException();
+ }
+ CharBuffer chars = CharBuffer.wrap(str, offset, count + offset);
+ convert(chars);
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/PipedInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/PipedInputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/PipedInputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/PipedInputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,337 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+
+/**
+ * PipedInputStream is a class which receives information on a communications
+ * pipe. When two threads want to pass data back and forth, one creates a piped
+ * output stream and the other creates a piped input stream.
+ *
+ * @see PipedOutputStream
+ */
+public class PipedInputStream extends InputStream {
+ private Thread lastReader, lastWriter;
+
+ private boolean isClosed = false;
+
+ /**
+ * The circular buffer through which data is passed.
+ */
+ protected byte buffer[];
+
+ /**
+ * The index in <code>buffer</code> where the next byte will be written.
+ */
+ protected int in = -1;
+
+ /**
+ * The index in <code>buffer</code> where the next byte will be read.
+ */
+ protected int out = 0;
+
+ /**
+ * The size of the default pipe in bytes
+ */
+ protected static final int PIPE_SIZE = 1024;
+
+ /**
+ * Indicates if this pipe is connected
+ */
+ boolean isConnected = false;
+
+ /**
+ * Constructs a new unconnected PipedInputStream. The resulting Stream must
+ * be connected to a PipedOutputStream before data may be read from it.
+ *
+ */
+ public PipedInputStream() {
+ /*empty*/
+ }
+
+ /**
+ * Constructs a new PipedInputStream connected to the PipedOutputStream
+ * <code>out</code>. Any data written to the output stream can be read
+ * from the this input stream.
+ *
+ * @param out
+ * the PipedOutputStream to connect to.
+ *
+ * @throws IOException
+ * if this or <code>out</code> are already connected.
+ */
+ public PipedInputStream(PipedOutputStream out) throws IOException {
+ connect(out);
+ }
+
+ /**
+ * Answers a int representing the number of bytes that are available before
+ * this PipedInputStream will block. This method returns the number of bytes
+ * written to the pipe but not read yet up to the size of the pipe.
+ *
+ * @return int the number of bytes available before blocking.
+ *
+ * @throws IOException
+ * If an error occurs in this stream.
+ */
+ public synchronized int available() throws IOException {
+ if (buffer == null || in == -1)
+ return 0;
+ return in <= out ? buffer.length - out + in : in - out;
+ }
+
+ /**
+ * Close this PipedInputStream. This implementation releases the buffer used
+ * for the pipe and notifies all threads waiting to read or write.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this stream.
+ */
+ public void close() throws IOException {
+ synchronized (this) {
+ /* No exception thrown if already closed */
+ if (buffer != null) {
+ /* Release buffer to indicate closed. */
+ buffer = null;
+ }
+ }
+ }
+
+ /**
+ * Connects this PipedInputStream to a PipedOutputStream. Any data written
+ * to the OutputStream becomes readable in this InputStream.
+ *
+ * @param src
+ * the source PipedOutputStream.
+ *
+ * @throws IOException
+ * If either stream is already connected.
+ */
+ public void connect(PipedOutputStream src) throws IOException {
+ src.connect(this);
+ }
+
+ /**
+ * Reads a single byte from this PipedInputStream and returns the result as
+ * an int. The low-order byte is returned or -1 of the end of stream was
+ * encountered. If there is no data in the pipe, this method blocks until
+ * there is data available. Separate threads should be used for the reader
+ * of the PipedInputStream and the PipedOutputStream. There may be
+ * undesirable results if more than one Thread interacts a input or output
+ * pipe.
+ *
+ * @return int The byte read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ public synchronized int read() throws IOException {
+ if (isConnected) {
+ if (buffer != null) {
+ /**
+ * Set the last thread to be reading on this PipedInputStream.
+ * If lastReader dies while someone is waiting to write an
+ * IOException of "Pipe broken" will be thrown in receive()
+ */
+ lastReader = Thread.currentThread();
+ try {
+ boolean first = true;
+ while (in == -1) {
+ // Are we at end of stream?
+ if (isClosed)
+ return -1;
+ if (!first && lastWriter != null
+ && !lastWriter.isAlive())
+ throw new IOException(com.ibm.oti.util.Msg
+ .getString("K0076")); //$NON-NLS-1$
+ first = false;
+ // Notify callers of receive()
+ notifyAll();
+ wait(1000);
+ }
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException();
+ }
+
+ byte result = buffer[out++];
+ if (out == buffer.length)
+ out = 0;
+ if (out == in) {
+ // empty buffer
+ in = -1;
+ out = 0;
+ }
+ return result & 0xff;
+ }
+ throw new IOException(com.ibm.oti.util.Msg.getString("K0075")); //$NON-NLS-1$
+ }
+ throw new IOException(com.ibm.oti.util.Msg.getString("K0074")); //$NON-NLS-1$
+ }
+
+ /**
+ * Reads at most <code>count</code> bytes from this PipedInputStream and
+ * stores them in byte array <code>buffer</code> starting at
+ * <code>offset</code>. Answer the number of bytes actually read or -1 if
+ * no bytes were read and end of stream was encountered. Separate threads
+ * should be used for the reader of the PipedInputStream and the
+ * PipedOutputStream. There may be undesirable results if more than one
+ * Thread interacts a input or output pipe.
+ *
+ * @param bytes
+ * the byte array in which to store the read bytes.
+ * @param offset
+ * the offset in <code>buffer</code> to store the read bytes.
+ * @param count
+ * the maximum number of bytes to store in <code>buffer</code>.
+ * @return the number of bytes actually read or -1 if end of stream.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ public synchronized int read(byte[] bytes, int offset, int count)
+ throws IOException {
+ if (bytes != null && 0 <= offset && offset <= bytes.length
+ && 0 <= count && count <= bytes.length - offset) {
+ if (count == 0)
+ return 0;
+ if (isConnected && buffer != null) {
+ /**
+ * Set the last thread to be reading on this PipedInputStream.
+ * If lastReader dies while someone is waiting to write an
+ * IOException of "Pipe broken" will be thrown in receive()
+ */
+ lastReader = Thread.currentThread();
+ try {
+ boolean first = true;
+ while (in == -1) {
+ // Are we at end of stream?
+ if (isClosed)
+ return -1;
+ if (!first && lastWriter != null
+ && !lastWriter.isAlive())
+ throw new IOException(com.ibm.oti.util.Msg
+ .getString("K0076")); //$NON-NLS-1$
+ first = false;
+ // Notify callers of receive()
+ notifyAll();
+ wait(1000);
+ }
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException();
+ }
+
+ int copyLength = 0;
+ /* Copy bytes from out to end of buffer first */
+ if (out >= in) {
+ copyLength = count > (buffer.length - out) ? buffer.length
+ - out : count;
+ System.arraycopy(buffer, out, bytes, offset, copyLength);
+ out += copyLength;
+ if (out == buffer.length)
+ out = 0;
+ if (out == in) {
+ // empty buffer
+ in = -1;
+ out = 0;
+ }
+ }
+
+ /*
+ * Did the read fully succeed in the previous copy or is the
+ * buffer empty?
+ */
+ if (copyLength == count || in == -1)
+ return copyLength;
+
+ int bytesCopied = copyLength;
+ /* Copy bytes from 0 to the number of available bytes */
+ copyLength = in - out > (count - bytesCopied) ? count
+ - bytesCopied : in - out;
+ System.arraycopy(buffer, out, bytes, offset + bytesCopied,
+ copyLength);
+ out += copyLength;
+ if (out == in) {
+ // empty buffer
+ in = -1;
+ out = 0;
+ }
+ return bytesCopied + copyLength;
+ }
+ if (!isConnected) {
+ throw new IOException(com.ibm.oti.util.Msg.getString("K0074")); //$NON-NLS-1$
+ }
+ throw new IOException(com.ibm.oti.util.Msg.getString("K0075")); //$NON-NLS-1$
+ }
+ if (bytes == null) {
+ throw new NullPointerException();
+ }
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Receives a byte and stores it into the PipedInputStream. This called by
+ * PipedOutputStream.write() when writes occur. The lowest-order byte is
+ * stored at index <code>in</code> in the <code>buffer</code>.
+ * <P>
+ * If the buffer is full and the thread sending #receive is interrupted, the
+ * InterruptedIOException will be thrown.
+ *
+ * @param oneByte
+ * the byte to store into the pipe.
+ *
+ * @throws IOException
+ * If the stream is already closed or another IOException
+ * occurs.
+ */
+ protected synchronized void receive(int oneByte) throws IOException {
+ if (buffer != null) {
+ /**
+ * Set the last thread to be writing on this PipedInputStream. If
+ * lastWriter dies while someone is waiting to read an IOException
+ * of "Pipe broken" will be thrown in read()
+ */
+ lastWriter = Thread.currentThread();
+ try {
+ while (buffer != null && out == in) {
+ notifyAll();
+ wait(1000);
+ if (lastReader != null && !lastReader.isAlive())
+ throw new IOException(com.ibm.oti.util.Msg
+ .getString("K0076")); //$NON-NLS-1$
+ }
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException();
+ }
+ if (buffer != null) {
+ if (in == -1)
+ in = 0;
+ buffer[in++] = (byte) oneByte;
+ if (in == buffer.length)
+ in = 0;
+ return;
+ }
+ }
+ throw new IOException(com.ibm.oti.util.Msg.getString("K0078")); //$NON-NLS-1$
+ }
+
+ synchronized void done() {
+ isClosed = true;
+ notifyAll();
+ }
+
+}
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/PipedOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/PipedOutputStream.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/PipedOutputStream.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/io/PipedOutputStream.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,168 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+
+/**
+ * PipedOutputStream is a class which places information on a communications
+ * pipe. When two threads want to pass data back and forth, one creates a piped
+ * output stream and the other creates a piped input stream.
+ *
+ * @see PipedInputStream
+ */
+public class PipedOutputStream extends OutputStream {
+
+ /**
+ * The destination PipedInputStream
+ */
+ private PipedInputStream dest;
+
+ /**
+ * Constructs a new unconnected PipedOutputStream. The resulting Stream must
+ * be connected to a PipedInputStream before data may be written to it.
+ */
+ public PipedOutputStream() {
+ super();
+ }
+
+ /**
+ * Constructs a new PipedOutputStream connected to the PipedInputStream
+ * <code>dest</code>. Any data written to this stream can be read from
+ * the <code>dest</code>.
+ *
+ * @param dest
+ * the PipedInputStream to connect to.
+ *
+ * @throws IOException
+ * if <code>dest</code> is already connected.
+ */
+ public PipedOutputStream(PipedInputStream dest) throws IOException {
+ super();
+ connect(dest);
+ }
+
+ /**
+ * Close this PipedOutputStream. Any data buffered in the corresponding
+ * PipedInputStream can be read, then -1 will be returned to the reader. If
+ * this OutputStream is not connected, this method does nothing.
+ *
+ * @throws IOException
+ * If an error occurs attempting to close this
+ * PipedOutputStream.
+ */
+ public void close() throws IOException {
+ if (dest != null) { // Is the pipe connected?
+ dest.done();
+ dest = null;
+ }
+ }
+
+ /**
+ * Connects this PipedOutputStream to a PipedInputStream. Any data written
+ * to this OutputStream becomes readable in the InputStream.
+ *
+ * @param stream
+ * the destination PipedInputStream.
+ *
+ * @throws IOException
+ * If this Stream or the dest is already connected.
+ */
+ public void connect(PipedInputStream stream) throws IOException {
+ if (this.dest == null) {
+ if (!stream.isConnected) {
+ stream.buffer = new byte[PipedInputStream.PIPE_SIZE];
+ stream.isConnected = true;
+ this.dest = stream;
+ } else
+ throw new IOException(com.ibm.oti.util.Msg.getString("K007a")); //$NON-NLS-1$
+ } else
+ throw new IOException(com.ibm.oti.util.Msg.getString("K0079")); //$NON-NLS-1$
+ }
+
+ /**
+ * Notifies the readers on the PipedInputStream that bytes can be read. This
+ * method does nothing if this Stream is not connected.
+ *
+ * @throws IOException
+ * If an IO error occurs during the flush.
+ */
+ public void flush() throws IOException {
+ if (dest != null) {
+ synchronized (dest) {
+ dest.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Writes <code>count</code> <code>bytes</code> from this byte array
+ * <code>buffer</code> starting at offset <code>index</code> to this
+ * PipedOutputStream. The written data can now be read from the destination
+ * PipedInputStream. Separate threads should be used for the reader of the
+ * PipedInputStream and the PipedOutputStream. There may be undesirable
+ * results if more than one Thread interacts a input or output pipe.
+ *
+ * @param buffer
+ * the buffer to be written
+ * @param offset
+ * offset in buffer to get bytes
+ * @param count
+ * number of bytes in buffer to write
+ *
+ * @throws IOException
+ * If the receiving thread was terminated without closing the
+ * pipe. This case is not currently handled correctly.
+ * @throws InterruptedIOException
+ * If the pipe is full and the current thread is interrupted
+ * waiting for space to write data. This case is not currently
+ * handled correctly.
+ * @throws NullPointerException
+ * If the receiver has not been connected yet.
+ * @throws IllegalArgumentException
+ * If any of the arguments are out of bounds.
+ */
+ public void write(byte buffer[], int offset, int count) throws IOException {
+ super.write(buffer, offset, count);
+ }
+
+ /**
+ * Writes the specified byte <code>oneByte</code> to this
+ * PipedOutputStream. Only the low order byte of <code>oneByte</code> is
+ * written. The data can now be read from the destination PipedInputStream.
+ * Separate threads should be used for the reader of the PipedInputStream
+ * and the PipedOutputStream. There may be undesirable results if more than
+ * one Thread interacts a input or output pipe.
+ *
+ * @param oneByte
+ * the byte to be written
+ *
+ * @throws IOException
+ * If the receiving thread was terminated without closing the
+ * pipe. This case is not currently handled correctly.
+ * @throws InterruptedIOException
+ * If the pipe is full and the current thread is interrupted
+ * waiting for space to write data. This case is not currently
+ * handled correctly.
+ * @throws NullPointerException
+ * If the receiver has not been connected yet.
+ */
+ public void write(int oneByte) throws IOException {
+ if (dest != null)
+ dest.receive(oneByte);
+ else
+ throw new IOException();
+ }
+}