OSDN Git Service

Jumbo patch:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 May 2000 17:55:34 +0000 (17:55 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 May 2000 17:55:34 +0000 (17:55 +0000)
* Imported beans and serialization
* Updated IA-64 port
* Miscellaneous bug fixes

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34028 138bc75d-0d04-0410-961f-82ee72b054a4

125 files changed:
libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/addr2name.awk [new file with mode: 0755]
libjava/configure
libjava/configure.host
libjava/configure.in
libjava/gcj/Makefile.in
libjava/gcj/javaprims.h
libjava/gnu/gcj/io/SimpleSHSStream.java [new file with mode: 0644]
libjava/gnu/gcj/io/natSimpleSHSStream.cc [new file with mode: 0644]
libjava/gnu/gcj/io/shs.cc [new file with mode: 0644]
libjava/gnu/gcj/io/shs.h [new file with mode: 0644]
libjava/gnu/java/beans/BeanInfoEmbryo.java [new file with mode: 0644]
libjava/gnu/java/beans/EmptyBeanInfo.java [new file with mode: 0644]
libjava/gnu/java/beans/ExplicitBeanInfo.java [new file with mode: 0644]
libjava/gnu/java/beans/IntrospectionIncubator.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/ColorEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/FontEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/NativeBooleanEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/NativeByteEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/NativeDoubleEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/NativeFloatEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/NativeIntEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/NativeLongEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/NativeShortEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/editors/StringEditor.java [new file with mode: 0644]
libjava/gnu/java/beans/info/ComponentBeanInfo.java [new file with mode: 0644]
libjava/gnu/java/io/ClassLoaderObjectInputStream.java [new file with mode: 0644]
libjava/gnu/java/io/NullOutputStream.java [new file with mode: 0644]
libjava/gnu/java/io/ObjectIdentityWrapper.java [new file with mode: 0644]
libjava/gnu/java/lang/ArrayHelper.java [new file with mode: 0644]
libjava/gnu/java/lang/ClassHelper.java [new file with mode: 0644]
libjava/gnu/java/lang/reflect/TypeSignature.java [new file with mode: 0644]
libjava/include/Makefile.in
libjava/include/config.h.in
libjava/include/default-signal.h
libjava/include/i386-signal.h
libjava/interpret.cc
libjava/java/beans/BeanDescriptor.java [new file with mode: 0644]
libjava/java/beans/BeanInfo.java [new file with mode: 0644]
libjava/java/beans/Beans.java [new file with mode: 0644]
libjava/java/beans/Customizer.java [new file with mode: 0644]
libjava/java/beans/DesignMode.java [new file with mode: 0644]
libjava/java/beans/EventSetDescriptor.java [new file with mode: 0644]
libjava/java/beans/FeatureDescriptor.java [new file with mode: 0644]
libjava/java/beans/IndexedPropertyDescriptor.java [new file with mode: 0644]
libjava/java/beans/IntrospectionException.java [new file with mode: 0644]
libjava/java/beans/Introspector.java [new file with mode: 0644]
libjava/java/beans/MethodDescriptor.java [new file with mode: 0644]
libjava/java/beans/ParameterDescriptor.java [new file with mode: 0644]
libjava/java/beans/PropertyChangeEvent.java [new file with mode: 0644]
libjava/java/beans/PropertyChangeListener.java [new file with mode: 0644]
libjava/java/beans/PropertyChangeSupport.java [new file with mode: 0644]
libjava/java/beans/PropertyDescriptor.java [new file with mode: 0644]
libjava/java/beans/PropertyEditor.java [new file with mode: 0644]
libjava/java/beans/PropertyEditorManager.java [new file with mode: 0644]
libjava/java/beans/PropertyEditorSupport.java [new file with mode: 0644]
libjava/java/beans/PropertyVetoException.java [new file with mode: 0644]
libjava/java/beans/SimpleBeanInfo.java [new file with mode: 0644]
libjava/java/beans/VetoableChangeListener.java [new file with mode: 0644]
libjava/java/beans/VetoableChangeSupport.java [new file with mode: 0644]
libjava/java/beans/Visibility.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContext.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextChild.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextChildComponentProxy.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextChildSupport.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextContainerProxy.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextEvent.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextMembershipEvent.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextMembershipListener.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextProxy.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextServiceAvailableEvent.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextServiceProvider.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextServiceRevokedEvent.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextServiceRevokedListener.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextServices.java [new file with mode: 0644]
libjava/java/beans/beancontext/BeanContextServicesListener.java [new file with mode: 0644]
libjava/java/io/BlockDataException.java [new file with mode: 0644]
libjava/java/io/Externalizable.java [new file with mode: 0644]
libjava/java/io/InvalidClassException.java [new file with mode: 0644]
libjava/java/io/InvalidObjectException.java [new file with mode: 0644]
libjava/java/io/NotActiveException.java [new file with mode: 0644]
libjava/java/io/NotSerializableException.java [new file with mode: 0644]
libjava/java/io/ObjectInput.java [new file with mode: 0644]
libjava/java/io/ObjectInputStream.java [new file with mode: 0644]
libjava/java/io/ObjectInputValidation.java [new file with mode: 0644]
libjava/java/io/ObjectOutput.java [new file with mode: 0644]
libjava/java/io/ObjectOutputStream.java [new file with mode: 0644]
libjava/java/io/ObjectStreamClass.java [new file with mode: 0644]
libjava/java/io/ObjectStreamConstants.java [new file with mode: 0644]
libjava/java/io/ObjectStreamField.java [new file with mode: 0644]
libjava/java/io/Replaceable.java [new file with mode: 0644]
libjava/java/io/Resolvable.java [new file with mode: 0644]
libjava/java/io/SerializablePermission.java [new file with mode: 0644]
libjava/java/io/WriteAbortedException.java [new file with mode: 0644]
libjava/java/io/natObjectInputStream.cc [new file with mode: 0644]
libjava/java/io/natObjectOutputStream.cc [new file with mode: 0644]
libjava/java/lang/Class.h
libjava/java/lang/SecurityManager.java
libjava/java/lang/String.java
libjava/java/lang/StringBuffer.java
libjava/java/lang/natClass.cc
libjava/java/lang/natClassLoader.cc
libjava/java/lang/natString.cc
libjava/java/lang/natThrowable.cc
libjava/java/net/URL.java
libjava/java/security/BasicPermission.java [new file with mode: 0644]
libjava/java/security/DigestOutputStream.java [new file with mode: 0644]
libjava/java/security/Guard.java [new file with mode: 0644]
libjava/java/security/Permission.java [new file with mode: 0644]
libjava/java/security/PermissionCollection.java [new file with mode: 0644]
libjava/java/util/AbstractCollection.java [new file with mode: 0644]
libjava/java/util/AbstractList.java [new file with mode: 0644]
libjava/java/util/Arrays.java [new file with mode: 0644]
libjava/libgcj.spec.in
libjava/libltdl/Makefile.in
libjava/mauve-libgcj
libjava/name-finder.cc
libjava/prims.cc
libjava/scripts/classes.pl
libjava/sysdep/ia64-frame.h [new file with mode: 0644]
libjava/sysdep/ia64.c [new file with mode: 0644]
libjava/testsuite/Makefile.in

index 87c7b28..669ef7b 100644 (file)
@@ -1,3 +1,489 @@
+2000-05-16  Andrew Haley  <aph@cygnus.com>
+
+       * sysdep/ia64.c (ia64_backtrace_helper): Pass NULL pointer to
+       build_ia64_frame_state.
+       * sysdep/ia64-frame.h (build_ia64_frame_state): Match with
+       defintion in gcc.
+
+2000-05-15  Warren Levy  <warrenl@cygnus.com>
+
+       * gnu/gcj/beans/BeanInfoEmbryo.java: Removed.
+       * gnu/gcj/beans/EmptyBeanInfo.java: Removed.
+       * gnu/gcj/beans/ExplicitBeanInfo.java: Removed.
+       * gnu/gcj/beans/IntrospectionIncubator.java: Removed.
+       * gnu/gcj/beans/editors/ColorEditor.java: Removed.
+       * gnu/gcj/beans/editors/FontEditor.java: Removed.
+       * gnu/gcj/beans/editors/NativeBooleanEditor.java: Removed.
+       * gnu/gcj/beans/editors/NativeByteEditor.java: Removed.
+       * gnu/gcj/beans/editors/NativeDoubleEditor.java: Removed.
+       * gnu/gcj/beans/editors/NativeFloatEditor.java: Removed.
+       * gnu/gcj/beans/editors/NativeIntEditor.java: Removed.
+       * gnu/gcj/beans/editors/NativeLongEditor.java: Removed.
+       * gnu/gcj/beans/editors/NativeShortEditor.java: Removed.
+       * gnu/gcj/beans/editors/StringEditor.java: Removed.
+       * gnu/gcj/beans/info/ComponentBeanInfo.java: Removed.
+       * gnu/gcj/io/ClassLoaderObjectInputStream.java: Removed.
+       * gnu/gcj/io/NullOutputStream.java: Removed.
+       * gnu/gcj/io/ObjectIdentityWrapper.java: Removed.
+       * gnu/gcj/lang/ArrayHelper.java: Removed.
+       * gnu/gcj/lang/ClassHelper.java: Removed.
+       * gnu/gcj/lang/reflect/TypeSignature.java: Removed.
+
+       * gnu/java/beans/BeanInfoEmbryo.java: New file.
+       * gnu/java/beans/EmptyBeanInfo.java: New file.
+       * gnu/java/beans/ExplicitBeanInfo.java: New file.
+       * gnu/java/beans/IntrospectionIncubator.java: New file.
+       * gnu/java/beans/editors/ColorEditor.java: New file.
+       * gnu/java/beans/editors/FontEditor.java: New file.
+       * gnu/java/beans/editors/NativeBooleanEditor.java: New file.
+       * gnu/java/beans/editors/NativeByteEditor.java: New file.
+       * gnu/java/beans/editors/NativeDoubleEditor.java: New file.
+       * gnu/java/beans/editors/NativeFloatEditor.java: New file.
+       * gnu/java/beans/editors/NativeIntEditor.java: New file.
+       * gnu/java/beans/editors/NativeLongEditor.java: New file.
+       * gnu/java/beans/editors/NativeShortEditor.java: New file.
+       * gnu/java/beans/editors/StringEditor.java: New file.
+       * gnu/java/beans/info/ComponentBeanInfo.java: New file.
+       * gnu/java/io/ClassLoaderObjectInputStream.java: New file.
+       * gnu/java/io/NullOutputStream.java: New file.
+       * gnu/java/io/ObjectIdentityWrapper.java: New file.
+       * gnu/java/lang/ArrayHelper.java: New file.
+       * gnu/java/lang/ClassHelper.java: New file.
+       * gnu/java/lang/reflect/TypeSignature.java: New file.
+
+       * Makefile.am: Updated for moving Classpath files from gnu/gcj
+       namespace back to the original Classpath gnu/java namespace.
+       * Makefile.in: Rebuilt.
+
+       * java/beans/Beans.java: Namespace change.
+       * java/beans/EventSetDescriptor.java: Namespace change.
+       * java/beans/Introspector.java: Namespace change.
+       * java/beans/PropertyEditorManager.java: Namespace change.
+       * java/io/ObjectInputStream.java: Namespace change.
+       * java/io/ObjectOutputStream.java: Namespace change.
+       * java/io/ObjectStreamClass.java: Namespace change.
+       * java/io/ObjectStreamField.java: Namespace change.
+
+2000-04-21  Warren Levy  <warrenl@cygnus.com>
+
+       * java/io/ObjectInputStream.java: Reverted workarounds of 2000-04-13
+       now that compiler patch is available.
+       Removed unneeded System.loadLibrary.
+       * java/io/ObjectOutputStream.java: Removed unneeded System.loadLibrary.
+       * java/io/ObjectStreamClass.java: Removed unneeded System.loadLibrary.
+
+2000-04-19  Andrew Haley  <aph@cygnus.com>
+
+       * java/lang/natClass.cc (_Jv_IsAssignableFrom): Make sure source
+       and target classes have been initialized.
+
+2000-04-19  Andrew Haley  <aph@cygnus.com>
+
+       * java/lang/String.java: implement Serializable, Comparable.
+       (compareTo (Object)): New method.
+
+2000-04-19  Warren Levy  <warrenl@cygnus.com>
+
+       * java/io/ObjectStreamClass.java (getDefinedSUID): Use getDeclaredField
+       instead of getField to retrieve non-public field.
+       (getSerialPersistantFields): Ditto.
+
+2000-04-18  Warren Levy  <warrenl@cygnus.com>
+
+       * mauve-libgcj: Turned off object serialization tests temporarily
+       due to compiler error.
+
+2000-04-17  Warren Levy  <warrenl@cygnus.com>
+
+       * java/io/ObjectInputStream.java (DEBUG): Disabled unused method
+       to avoid build problem.
+       (DEBUGln): Ditto.
+       * mauve-libgcj: Turned on object serialization tests.
+
+2000-04-17  Tom Tromey  <tromey@cygnus.com>
+
+       * libgcj.spec.in (*lib): Added -lgcjawt.
+
+2000-04-17  Andrew Haley  <aph@cygnus.com>
+
+       * Makefile.am: Add new files: 
+       gnu/gcj/io/SimpleSHSStream.java, gnu/gcj/io/natSimpleSHSStream.cc,
+       gnu/gcj/io/shs.cc.
+       * Makefile.in: Rebuilt.
+
+       * java/lang/natClass.cc (_Jv_IsAssignableFrom): Check for an
+       interface that has no implementations.
+       Check for an attempt to assign an abstract class to an interface.
+
+       * java/io/ObjectStreamClass.java (setUID): Use a SimpleSHSStream
+       if we fail to find MessageDigest.getInstance ("SHA").
+
+       * gnu/gcj/io/SimpleSHSStream.java: New file.
+       * gnu/gcj/io/natSimpleSHSStream.java: New file.
+       * gnu/gcj/io/shs.cc: New file.
+       * gnu/gcj/io/shs.h: new file.
+
+       * java/lang/natClassLoader.cc (_Jv_FindArrayClass): Make arrays
+       serializable.
+
+       * gnu/gcj/lang/reflect/TypeSignature.java: Don't remove
+       punctuation from the classname of an array element.
+
+       * gcj/javaprims.h: Add SimpleDigestStream.
+       
+2000-04-17  Andrew Haley  <aph@cygnus.com>
+
+       * java/lang/natClass.cc (getPrivateField): Make recursive calls
+       to getPrivateField for superclasses.
+2000-04-14  Andrew Haley  <aph@cygnus.com>
+
+       * Makefile.am: Add new files:
+       java/io/ObjectOutputStream$PutField.h,
+       java/io/ObjectInputStream$GetField.h,java/io/natObjectInputStream.cc,
+       java/io/natObjectOutputStream.cc
+       * Makefile.in: Rebuilt.
+       * gcj/Makefile.in: Rebuilt.
+       * include/Makefile.in: Rebuilt.
+       * java/lang/Class.h (getPrivateField): New method.
+       (getPrivateMethod): Ditto.
+       Make java::io::ObjectOutputStream, java::io::ObjectInputStream,
+       and java::io::ObjectStreamClass our friends.
+       * java/lang/natClass.cc (getPrivateField): New method.
+       (getPrivateMethod): Ditto.
+       (_Jv_IsAssignableFrom): Return false for Interface with no IDT.
+       * gcj/javaprims.h: Add serialization classes.   
+       * java/io/ObjectInputStream.java (setBooleanField): Rewrite in Java.
+       (setByteField): Ditto.
+       (setCharField): Ditto.
+       (setDoubleField): Ditto.
+       (setFloatField): Ditto.
+       (setIntField): Ditto.
+       (setLongField): Ditto.
+       (setShortField): Ditto.
+       (setObjectField): Ditto.
+       * java/io/ObjectOutputStream.java: (getBooleanField): Rewrite in
+       Java.
+       (getByteField): Ditto.
+       (getCharField): Ditto.
+       (getDoubleField): Ditto.
+       (getFloatField): Ditto.
+       (getIntField): Ditto.
+       (getLongField): Ditto.
+       (getShortField): Ditto.
+       (getObjectField): Ditto.
+       * java/io/ObjectStreamClass.java (hasClassInitializer): Rewrite in
+       Java.
+       (getSerialPersistantFields): Ditto.
+       (getDefinedSUID): Ditto.
+       * java/io/natObjectOutputStream.cc: New file.
+       * java/io/natObjectInputStream.cc: New file.
+       
+2000-04-13  Warren Levy  <warrenl@cygnus.com>
+
+       * java/io/ObjectInputStream.java: Temporary workarounds for compiler
+       problems.  Revert to previous version to reproduce and when fixed.
+
+2000-04-13  Warren Levy  <warrenl@cygnus.com>
+
+       * gnu/gcj/io/ClassLoaderObjectInputStream.java: New file.
+       * gnu/gcj/io/NullOutputStream.java: New file.
+       * gnu/gcj/lang/reflect/TypeSignature.java: New file.
+       * java/io/BlockDataException.java: New file.
+       * java/io/Externalizable.java: New file.
+       * java/io/InvalidClassException.java: New file.
+       * java/io/InvalidObjectException.java: New file.
+       * java/io/NotActiveException.java: New file.
+       * java/io/NotSerializableException.java: New file.
+       * java/io/ObjectInput.java: New file.
+       * java/io/ObjectInputStream.java: New file.
+       * java/io/ObjectInputValidation.java: New file.
+       * java/io/ObjectOutput.java: New file.
+       * java/io/ObjectOutputStream.java: New file.
+       * java/io/ObjectStreamClass.java: New file.
+       * java/io/ObjectStreamConstants.java: New file.
+       * java/io/ObjectStreamField.java: New file.
+       * java/io/Replaceable.java: New file.
+       * java/io/Resolvable.java: New file.
+       * java/io/SerializablePermission.java: New file.
+       * java/io/WriteAbortedException.java: New file.
+       * java/security/BasicPermission.java: New file.
+       * java/security/DigestOutputStream.java: New file.
+       * java/security/Guard.java: New file.
+       * java/security/Permission.java: New file.
+       * java/security/PermissionCollection.java: New file.
+       * Makefile.am: Added above files.
+       * Makefile.in: Rebuilt.
+
+       * java/beans/Beans.java (instantiate): Activated serialization code.
+       * java/lang/SecurityManager.java (checkPermission): New method.
+
+2000-04-12  Warren Levy  <warrenl@cygnus.com>
+
+       * gnu/gcj/beans/BeanInfoEmbryo.java: New file.
+       * gnu/gcj/beans/EmptyBeanInfo.java: New file.
+       * gnu/gcj/beans/ExplicitBeanInfo.java: New file.
+       * gnu/gcj/beans/IntrospectionIncubator.java: New file.
+       * gnu/gcj/beans/editors/ColorEditor.java: New file.
+       * gnu/gcj/beans/editors/FontEditor.java: New file.
+       * gnu/gcj/beans/editors/NativeBooleanEditor.java: New file.
+       * gnu/gcj/beans/editors/NativeByteEditor.java: New file.
+       * gnu/gcj/beans/editors/NativeDoubleEditor.java: New file.
+       * gnu/gcj/beans/editors/NativeFloatEditor.java: New file.
+       * gnu/gcj/beans/editors/NativeIntEditor.java: New file.
+       * gnu/gcj/beans/editors/NativeLongEditor.java: New file.
+       * gnu/gcj/beans/editors/NativeShortEditor.java: New file.
+       * gnu/gcj/beans/editors/StringEditor.java: New file.
+       * gnu/gcj/beans/info/ComponentBeanInfo.java: New file.
+       * gnu/gcj/io/ObjectIdentityWrapper.java: New file.
+       * gnu/gcj/lang/ArrayHelper.java: New file.
+       * gnu/gcj/lang/ClassHelper.java: New file.
+       * java/beans/BeanDescriptor.java: New file.
+       * java/beans/BeanInfo.java: New file.
+       * java/beans/Beans.java: New file.
+       * java/beans/Customizer.java: New file.
+       * java/beans/DesignMode.java: New file.
+       * java/beans/EventSetDescriptor.java: New file.
+       * java/beans/FeatureDescriptor.java: New file.
+       * java/beans/IndexedPropertyDescriptor.java: New file.
+       * java/beans/IntrospectionException.java: New file.
+       * java/beans/Introspector.java: New file.
+       * java/beans/MethodDescriptor.java: New file.
+       * java/beans/ParameterDescriptor.java: New file.
+       * java/beans/PropertyChangeEvent.java: New file.
+       * java/beans/PropertyChangeListener.java: New file.
+       * java/beans/PropertyChangeSupport.java: New file.
+       * java/beans/PropertyDescriptor.java: New file.
+       * java/beans/PropertyEditor.java: New file.
+       * java/beans/PropertyEditorManager.java: New file.
+       * java/beans/PropertyEditorSupport.java: New file.
+       * java/beans/PropertyVetoException.java: New file.
+       * java/beans/SimpleBeanInfo.java: New file.
+       * java/beans/VetoableChangeListener.java: New file.
+       * java/beans/VetoableChangeSupport.java: New file.
+       * java/beans/Visibility.java: New file.
+       * java/beans/beancontext/BeanContext.java: New file.
+       * java/beans/beancontext/BeanContextChild.java: New file.
+       * java/beans/beancontext/BeanContextChildComponentProxy.java: New file.
+       * java/beans/beancontext/BeanContextChildSupport.java: New file.
+       * java/beans/beancontext/BeanContextContainerProxy.java: New file.
+       * java/beans/beancontext/BeanContextEvent.java: New file.
+       * java/beans/beancontext/BeanContextMembershipEvent.java: New file.
+       * java/beans/beancontext/BeanContextMembershipListener.java: New file.
+       * java/beans/beancontext/BeanContextProxy.java: New file.
+       * java/beans/beancontext/BeanContextServiceAvailableEvent.java:
+       New file.
+       * java/beans/beancontext/BeanContextServiceProvider.java: New file.
+       * java/beans/beancontext/BeanContextServiceProviderBeanInfo.java:
+       New file.
+       * java/beans/beancontext/BeanContextServiceRevokedEvent.java: New file.
+       * java/beans/beancontext/BeanContextServiceRevokedListener.java:
+       New file.
+       * java/beans/beancontext/BeanContextServices.java: New file.
+       * java/beans/beancontext/BeanContextServicesListener.java: New file.
+       * java/util/AbstractCollection.java: New file.
+       * java/util/AbstractList.java: New file.
+       * java/util/Arrays.java: New file.
+       * Makefile.am: Added above files.
+       * Makefile.in: Rebuilt.
+
+2000-04-11  Warren Levy  <warrenl@cygnus.com>
+
+       * java/awt/AWTError.java: New file.
+       * java/awt/AWTEvent.java: New file.
+       * java/awt/AWTException.java: New file.
+       * java/awt/ActiveEvent.java: New file.
+       * java/awt/Adjustable.java: New file.
+       * java/awt/BorderLayout.java: New file.
+       * java/awt/Color.java: New file.
+       * java/awt/Component.java: New file.
+       * java/awt/Container.java: New file.
+       * java/awt/Dimension.java: New file.
+       * java/awt/Event.java: New file.
+       * java/awt/Font.java: New file.
+       * java/awt/Frame.java: New file.
+       * java/awt/Graphics.java: New file.
+       * java/awt/IllegalComponentStateException.java: New file.
+       * java/awt/Image.java: New file.
+       * java/awt/ItemSelectable.java: New file.
+       * java/awt/LayoutManager.java: New file.
+       * java/awt/LayoutManager2.java: New file.
+       * java/awt/Menu.java: New file.
+       * java/awt/MenuBar.java: New file.
+       * java/awt/MenuComponent.java: New file.
+       * java/awt/MenuContainer.java: New file.
+       * java/awt/MenuItem.java: New file.
+       * java/awt/Paint.java: New file.
+       * java/awt/PaintContext.java: New file.
+       * java/awt/Point.java: New file.
+       * java/awt/Rectangle.java: New file.
+       * java/awt/Shape.java: New file.
+       * java/awt/TextArea.java: New file.
+       * java/awt/TextComponent.java: New file.
+       * java/awt/Toolkit.java: New file.
+       * java/awt/Transparency.java: New file.
+       * java/awt/Window.java: New file.
+       * java/awt/natToolkit.cc: New file.
+       * java/awt/event/AWTEventListener.java: New file.
+       * java/awt/event/ActionEvent.java: New file.
+       * java/awt/event/ActionListener.java: New file.
+       * java/awt/event/AdjustmentEvent.java: New file.
+       * java/awt/event/AdjustmentListener.java: New file.
+       * java/awt/event/ComponentAdapter.java: New file.
+       * java/awt/event/ComponentEvent.java: New file.
+       * java/awt/event/ComponentListener.java: New file.
+       * java/awt/event/ContainerAdapter.java: New file.
+       * java/awt/event/ContainerEvent.java: New file.
+       * java/awt/event/ContainerListener.java: New file.
+       * java/awt/event/FocusAdapter.java: New file.
+       * java/awt/event/FocusEvent.java: New file.
+       * java/awt/event/FocusListener.java: New file.
+       * java/awt/event/InputEvent.java: New file.
+       * java/awt/event/InputMethodEvent.java: New file.
+       * java/awt/event/InputMethodListener.java: New file.
+       * java/awt/event/InvocationEvent.java: New file.
+       * java/awt/event/ItemEvent.java: New file.
+       * java/awt/event/ItemListener.java: New file.
+       * java/awt/event/KeyAdapter.java: New file.
+       * java/awt/event/KeyEvent.java: New file.
+       * java/awt/event/KeyListener.java: New file.
+       * java/awt/event/MouseAdapter.java: New file.
+       * java/awt/event/MouseEvent.java: New file.
+       * java/awt/event/MouseListener.java: New file.
+       * java/awt/event/MouseMotionAdapter.java: New file.
+       * java/awt/event/MouseMotionListener.java: New file.
+       * java/awt/event/PaintEvent.java: New file.
+       * java/awt/event/TextEvent.java: New file.
+       * java/awt/event/TextListener.java: New file.
+       * java/awt/event/WindowAdapter.java: New file.
+       * java/awt/event/WindowEvent.java: New file.
+       * java/awt/event/WindowListener.java: New file.
+       * java/awt/geom/Dimension2D.java: New file.
+       * java/awt/geom/Point2D.java: New file.
+       * java/awt/peer/ComponentPeer.java: New file.
+       * java/awt/peer/ContainerPeer.java: New file.
+       * java/awt/peer/FramePeer.java: New file.
+       * java/awt/peer/WindowPeer.java: New file.
+       * java/util/Collection.java: New file.
+       * java/util/Comparator.java: New file.
+       * java/util/Iterator.java: New file.
+       * java/util/List.java: New file.
+       * java/util/ListIterator.java: New file.
+       * Makefile.am: Added above files.
+       * Makefile.in: Rebuilt.
+
+2000-04-10  Warren Levy  <warrenl@cygnus.com>
+
+       * gnu/gcj/runtime/MethodInvocation.java: Fixed copyright.
+       * java/lang/FirstThread.java: Ditto.
+       * java/lang/StringBuffer.java: Ditto.
+       * mauve-libgcj: Turned on java.math, java.sql and java.security tests.
+
+       * gnu/gcj/math/MPN.java (rshift): Undid Boehm's patch of 03-14.
+       Special case handled in java.math.BigInteger.
+       * java/math/BigInteger.java (divide): Handle the special case when
+       dividing by 1 and the high bit of the dividend is set.
+       (setShiftRight): Handle case when count == 0.
+
+2000-04-05  Andrew Haley  <aph@cygnus.com>
+
+       * java/net/URL.java (setURLStreamHandler): Make "file" protocol a
+       special case.
+
+2000-04-05  Andrew Haley  <aph@cygnus.com>
+
+       * sysdep/ia64.c (rse_address_add): Delete.
+       (IS_NaT_COLLECTION_ADDR): Delete.
+       (ia64_backtrace_helper): check for null unwind_info.
+       
+       * sysdep/ia64-frame.h: add calc_caller_bsp.
+
+       * java/lang/natThrowable.cc (printRawStackTrace): Flush
+       PrintWriter.
+
+       * prims.cc (_Jv_divI): Use _Jv_ThrowSignal.
+       (_Jv_remI): Likewise.
+       (_Jv_divJ): Likewise.
+       (_Jv_remJ): Likewise.
+       
+       * interpret.cc (continue1): Use divide subroutines to guarantee
+       correct Java standard behaviour.
+       Floating-point division should not abort; make it so.
+
+2000-03-29  Tom Tromey  <tromey@cygnus.com>
+
+       * configure: Rebuilt.
+       * configure.in: Test against `libgcj_sjlj', not
+       `enable_sjlj_exceptions'.  Rearranged code to allow SYSDEP_SOURCES
+       to be set even when using sjlj.
+
+2000-03-24  Andrew Haley  <aph@cygnus.com>
+
+       * Makefile.am: Add file addr2name.awk.
+       * Makefile.in: Rebuilt.
+       * addr2name.awk: New file.
+       * name-finder.cc (_Jv_name_finder): Call addr2name.awk to do name
+       lookups on ia64.
+       * java/lang/natThrowable.cc(printRawStackTrace): Don't print out a
+       blank line.
+       
+2000-03-22  Andrew Haley  <aph@cygnus.com>
+
+       * configure.host: Add -funwind-tables for IA64.
+       * Makefile.am (c_source_files): Add SYSDEP_SORCES.
+       * Makefile.in: Rebuilt.
+       * java/lang/natThrowable.cc (fillInStackTrace): Add ia64 case.
+       * sysdep/ia64.c: New file.
+       * sysdep/ia64-frame.h: New file.
+       * configure.in: Add sysdep/ia64.c for ia64.
+       * configure: Rebuilt.
+       
+2000-03-17  Andrew Haley  <aph@cygnus.com>
+
+       * java/lang/natString.cc: Remove `register' keyword.
+       interpret.cc: ditto.
+
+2000-03-16  Andrew Haley  <aph@cygnus.com>
+
+       * configure.host (ia64): Enable interpreter.
+
+2000-03-14  Hans Boehm  <boehm@acm.org>
+
+       * gnu/gcj/math/MPN.java (rshift): Handle shift 32 specially.
+
+       * include/java-cpool.h (_Jv_storeLong, _Jv_loadLong,
+       _Jv_storeDouble, _Jv_loadDouble): Define differently on 64 bit
+       machine.
+       * java/lang/ieeefp.h: Define __IEEE_BIG_ENDIAN or
+       __IEEE_LITTLE_ENDIAN appropriately on IA64.
+       * java/lang/mprec.h: Don't define Pack_32 on 64 bit machine.
+       * javaprims.h (_Jv_word): Added `l' and `d' entries in 64 bit
+       case.
+       * resolve.cc (FFI_PREP_RAW_CLOSURE): New define.
+       (FFI_RAW_SIZE): Likewise.
+       (_Jv_InterpMethod::ncode): Use them.
+       * interpret.cc (PUSHL, PUSHD, POPL, POPD, LOADL, LOADD, STOREL,
+       STORED): Define differently on a 64 bit machine.
+       (continue1): Use ffi_java_raw_call when appropriate.
+
+2000-03-14  Andrew Haley  <aph@cygnus.com>
+
+       * include/default-signal.h (MAKE_THROW_FRAME): Add arg
+       `_exception'.
+
+2000-03-10  Andrew Haley  <aph@cygnus.com>
+
+       * java/lang/ieeefp.h: Import latest version from fdlibm.
+
+2000-03-14  Andrew Haley  <aph@cygnus.com>
+
+       * prims.cc (_Jv_ThrowSignal): New function.
+       (catch_segv): Add arg `_exception' to MAKE_THROW_FRAME.
+       (catch_fpe): Ditto.
+       * include/sparc-signal.h (MAKE_THROW_FRAME): Ditto
+       * include/i386-signal.h (MAKE_THROW_FRAME): Ditto.
+       * include/ppc-signal.h: New file.
+
 2000-05-18  Bryce McKinlay  <bryce@albatross.co.nz>
 
        * java/lang/Thread.java: Declare `data' as Object, not RawData.
index d7b98c2..97d5047 100644 (file)
@@ -41,6 +41,8 @@ if NATIVE
 bin_PROGRAMS = jv-convert gij
 endif
 
+bin_SCRIPTS = addr2name.awk
+
 ## ################################################################
 
 ##
@@ -232,7 +234,9 @@ $(awto_files) $(javao_files): libgcj.zip
 ## Header files used when compiling some of the nat* files.
 nat_headers = $(ordinary_java_source_files:.java=.h) \
        $(built_java_source_files:.java=.h) \
-       $(cond_awt_java_source_files:.java=.h)
+       $(cond_awt_java_source_files:.java=.h) \
+       java/io/ObjectOutputStream$$PutField.h \
+       java/io/ObjectInputStream$$GetField.h
 
 $(nat_headers): libgcj.zip
 
@@ -298,6 +302,14 @@ gnu/gcj/runtime/VMClassLoader.h: gnu/gcj/runtime/VMClassLoader.class libgcj.zip
            -friend 'java::lang::ClassLoader;' \
            $(basename $<)
 
+java/io/ObjectInputStream$$GetField.h: java/io/ObjectInputStream$$GetField.class libgcj.zip
+       $(GCJH) -classpath $(top_builddir) \
+       'java/io/ObjectInputStream$$GetField'
+
+java/io/ObjectOutputStream$$PutField.h: java/io/ObjectOutputStream$$PutField.class libgcj.zip
+       $(GCJH) -classpath $(top_builddir) \
+       'java/io/ObjectOutputStream$$PutField'
+
 ## Headers we maintain by hand and which we want to install.
 extra_headers = java/lang/Object.h java/lang/Class.h
 
@@ -492,23 +504,48 @@ gnu/gcj/convert/UnicodeToBytes.java
 special_java_source_files = java/lang/Class.java java/lang/Object.java
 
 awt_java_source_files =        \
-java/awt/AWTError.java \
+java/awt/event/ActionEvent.java        \
+java/awt/event/ActionListener.java \
+java/awt/event/ComponentEvent.java \
+java/awt/event/KeyAdapter.java \
+java/awt/event/InputEvent.java \
+java/awt/event/KeyEvent.java \
+java/awt/event/KeyListener.java        \
+java/awt/event/TextEvent.java \
+java/awt/event/TextListener.java \
+java/awt/event/WindowAdapter.java \
+java/awt/event/WindowEvent.java        \
+java/awt/event/WindowListener.java \
+java/awt/event/InputMethodListener.java        \
+java/awt/event/ComponentListener.java \
+java/awt/event/AdjustmentListener.java \
+java/awt/event/AWTEventListener.java \
+java/awt/event/FocusListener.java \
+java/awt/event/AdjustmentEvent.java \
+java/awt/event/ItemListener.java \
+java/awt/event/ContainerListener.java \
+java/awt/event/MouseListener.java \
+java/awt/event/MouseMotionListener.java        \
+java/awt/event/ComponentAdapter.java \
+java/awt/event/ContainerAdapter.java \
+java/awt/event/FocusAdapter.java \
+java/awt/event/MouseAdapter.java \
+java/awt/event/MouseMotionAdapter.java \
+java/awt/event/FocusEvent.java \
+java/awt/event/InputMethodEvent.java \
+java/awt/event/MouseEvent.java \
+java/awt/event/ItemEvent.java \
+java/awt/event/InvocationEvent.java \
+java/awt/event/PaintEvent.java \
+java/awt/event/ContainerEvent.java \
 java/awt/AWTEvent.java \
-java/awt/AWTException.java \
-java/awt/ActiveEvent.java \
-java/awt/Adjustable.java \
 java/awt/BorderLayout.java \
-java/awt/Color.java \
 java/awt/Component.java        \
 java/awt/Container.java        \
 java/awt/Dimension.java        \
 java/awt/Event.java \
 java/awt/Font.java \
 java/awt/Frame.java \
-java/awt/Graphics.java \
-java/awt/IllegalComponentStateException.java \
-java/awt/Image.java \
-java/awt/ItemSelectable.java \
 java/awt/LayoutManager.java \
 java/awt/LayoutManager2.java \
 java/awt/Menu.java \
@@ -516,56 +553,31 @@ java/awt/MenuBar.java \
 java/awt/MenuComponent.java \
 java/awt/MenuContainer.java \
 java/awt/MenuItem.java \
-java/awt/Paint.java \
-java/awt/PaintContext.java \
 java/awt/Point.java \
-java/awt/Rectangle.java        \
+java/awt/AWTError.java \
 java/awt/Shape.java \
 java/awt/TextArea.java \
 java/awt/TextComponent.java \
 java/awt/Toolkit.java \
-java/awt/Transparency.java \
 java/awt/Window.java \
-java/awt/event/AWTEventListener.java \
-java/awt/event/ActionEvent.java        \
-java/awt/event/ActionListener.java \
-java/awt/event/AdjustmentEvent.java \
-java/awt/event/AdjustmentListener.java \
-java/awt/event/ComponentAdapter.java \
-java/awt/event/ComponentEvent.java \
-java/awt/event/ComponentListener.java \
-java/awt/event/ContainerAdapter.java \
-java/awt/event/ContainerEvent.java \
-java/awt/event/ContainerListener.java \
-java/awt/event/FocusAdapter.java \
-java/awt/event/FocusEvent.java \
-java/awt/event/FocusListener.java \
-java/awt/event/InputEvent.java \
-java/awt/event/InputMethodEvent.java \
-java/awt/event/InputMethodListener.java        \
-java/awt/event/InvocationEvent.java \
-java/awt/event/ItemEvent.java \
-java/awt/event/ItemListener.java \
-java/awt/event/KeyAdapter.java \
-java/awt/event/KeyEvent.java \
-java/awt/event/KeyListener.java        \
-java/awt/event/MouseAdapter.java \
-java/awt/event/MouseEvent.java \
-java/awt/event/MouseListener.java \
-java/awt/event/MouseMotionAdapter.java \
-java/awt/event/MouseMotionListener.java        \
-java/awt/event/PaintEvent.java \
-java/awt/event/TextEvent.java \
-java/awt/event/TextListener.java \
-java/awt/event/WindowAdapter.java \
-java/awt/event/WindowEvent.java        \
-java/awt/event/WindowListener.java \
 java/awt/geom/Dimension2D.java \
 java/awt/geom/Point2D.java \
 java/awt/peer/ComponentPeer.java \
 java/awt/peer/ContainerPeer.java \
 java/awt/peer/FramePeer.java \
-java/awt/peer/WindowPeer.java
+java/awt/peer/WindowPeer.java \
+java/awt/Adjustable.java \
+java/awt/Color.java \
+java/awt/Graphics.java \
+java/awt/Image.java \
+java/awt/Paint.java \
+java/awt/PaintContext.java \
+java/awt/Transparency.java \
+java/awt/ItemSelectable.java \
+java/awt/AWTException.java \
+java/awt/ActiveEvent.java \
+java/awt/Rectangle.java        \
+java/awt/IllegalComponentStateException.java
 
 if AWT
 cond_awt_java_source_files = $(awt_java_source_files)
@@ -582,11 +594,12 @@ built_java_source_files = java/lang/ConcreteProcess.java
 ## convert_source_files.  If the .java file has a hand-maintained
 ## header, please list it in special_java_source_files.
 ordinary_java_source_files =  $(convert_source_files) \
-gnu/gcj/io/DefaultMimeTypes.java \
-gnu/gcj/io/MimeTypes.java \
-gnu/gcj/jni/NativeThread.java \
-gnu/gcj/runtime/VMClassLoader.java \
-gnu/gcj/runtime/FirstThread.java \
+gnu/gcj/protocol/http/Connection.java \
+gnu/gcj/protocol/http/Handler.java \
+gnu/gcj/protocol/file/Connection.java \
+gnu/gcj/protocol/file/Handler.java \
+gnu/gcj/protocol/jar/Connection.java \
+gnu/gcj/protocol/jar/Handler.java \
 gnu/gcj/text/BaseBreakIterator.java \
 gnu/gcj/text/CharacterBreakIterator.java \
 gnu/gcj/text/LineBreakIterator.java \
@@ -594,15 +607,36 @@ gnu/gcj/text/LocaleData_en.java   \
 gnu/gcj/text/LocaleData_en_US.java \
 gnu/gcj/text/SentenceBreakIterator.java        \
 gnu/gcj/text/WordBreakIterator.java \
-gnu/gcj/math/MPN.java \
-gnu/gcj/protocol/file/Connection.java \
-gnu/gcj/protocol/file/Handler.java \
-gnu/gcj/protocol/http/Connection.java \
-gnu/gcj/protocol/http/Handler.java \
-gnu/gcj/protocol/jar/Handler.java \
-gnu/gcj/protocol/jar/Connection.java \
-gnu/gcj/RawData.java \
 gnu/gcj/util/EnumerationChain.java \
+gnu/gcj/RawData.java \
+gnu/gcj/math/MPN.java \
+gnu/gcj/runtime/VMClassLoader.java \
+gnu/gcj/runtime/FirstThread.java \
+gnu/gcj/jni/NativeThread.java \
+gnu/gcj/io/DefaultMimeTypes.java \
+gnu/gcj/io/MimeTypes.java \
+gnu/gcj/io/SimpleSHSStream.java        \
+gnu/java/beans/editors/ColorEditor.java        \
+gnu/java/beans/editors/FontEditor.java \
+gnu/java/beans/editors/NativeBooleanEditor.java        \
+gnu/java/beans/editors/NativeByteEditor.java \
+gnu/java/beans/editors/NativeDoubleEditor.java \
+gnu/java/beans/editors/NativeFloatEditor.java \
+gnu/java/beans/editors/NativeIntEditor.java \
+gnu/java/beans/editors/NativeLongEditor.java \
+gnu/java/beans/editors/NativeShortEditor.java \
+gnu/java/beans/editors/StringEditor.java \
+gnu/java/beans/info/ComponentBeanInfo.java \
+gnu/java/beans/BeanInfoEmbryo.java \
+gnu/java/beans/EmptyBeanInfo.java \
+gnu/java/beans/ExplicitBeanInfo.java \
+gnu/java/beans/IntrospectionIncubator.java \
+gnu/java/io/ClassLoaderObjectInputStream.java \
+gnu/java/io/NullOutputStream.java \
+gnu/java/io/ObjectIdentityWrapper.java \
+gnu/java/lang/reflect/TypeSignature.java \
+gnu/java/lang/ArrayHelper.java \
+gnu/java/lang/ClassHelper.java \
 java/io/BufferedInputStream.java \
 java/io/BufferedOutputStream.java \
 java/io/BufferedReader.java \
@@ -618,7 +652,6 @@ java/io/DataOutput.java     \
 java/io/DataOutputStream.java \
 java/io/EOFException.java \
 java/io/File.java \
-java/io/FileDescriptor.java \
 java/io/FileInputStream.java \
 java/io/FileNotFoundException.java \
 java/io/FileOutputStream.java \
@@ -635,11 +668,10 @@ java/io/InputStreamReader.java \
 java/io/InterruptedIOException.java \
 java/io/LineNumberInputStream.java \
 java/io/LineNumberReader.java \
-java/io/ObjectStreamException.java \
-java/io/OptionalDataException.java \
 java/io/OutputStream.java \
 java/io/OutputStreamWriter.java        \
-java/io/PipedInputStream.java \
+java/io/Externalizable.java \
+java/io/FileDescriptor.java \
 java/io/PipedOutputStream.java \
 java/io/PipedReader.java \
 java/io/PipedWriter.java \
@@ -651,7 +683,6 @@ java/io/RandomAccessFile.java \
 java/io/Reader.java \
 java/io/SequenceInputStream.java \
 java/io/Serializable.java \
-java/io/StreamCorruptedException.java \
 java/io/StreamTokenizer.java \
 java/io/StringBufferInputStream.java \
 java/io/StringReader.java \
@@ -660,6 +691,35 @@ java/io/SyncFailedException.java \
 java/io/UTFDataFormatException.java \
 java/io/UnsupportedEncodingException.java \
 java/io/Writer.java \
+java/io/ObjectStreamException.java \
+java/io/OptionalDataException.java \
+java/io/StreamCorruptedException.java \
+java/io/BlockDataException.java        \
+java/io/InvalidClassException.java \
+java/io/InvalidObjectException.java \
+java/io/NotActiveException.java        \
+java/io/NotSerializableException.java \
+java/io/ObjectInput.java \
+java/io/ObjectInputStream.java \
+java/io/ObjectInputValidation.java \
+java/io/ObjectOutput.java \
+java/io/ObjectOutputStream.java        \
+java/io/ObjectStreamClass.java \
+java/io/ObjectStreamConstants.java \
+java/io/ObjectStreamField.java \
+java/io/Replaceable.java \
+java/io/Resolvable.java        \
+java/io/SerializablePermission.java \
+java/io/WriteAbortedException.java \
+java/io/PipedInputStream.java \
+java/lang/reflect/Constructor.java \
+java/lang/reflect/AccessibleObject.java        \
+java/lang/reflect/Array.java \
+java/lang/reflect/Method.java \
+java/lang/reflect/Field.java \
+java/lang/reflect/InvocationTargetException.java \
+java/lang/reflect/Member.java \
+java/lang/reflect/Modifier.java        \
 java/lang/AbstractMethodError.java \
 java/lang/ArithmeticException.java \
 java/lang/ArrayIndexOutOfBoundsException.java \
@@ -688,10 +748,10 @@ java/lang/IllegalMonitorStateException.java \
 java/lang/IllegalStateException.java \
 java/lang/IllegalThreadStateException.java \
 java/lang/IncompatibleClassChangeError.java \
-java/lang/IndexOutOfBoundsException.java \
 java/lang/InstantiationError.java \
-java/lang/InstantiationException.java \
 java/lang/Integer.java \
+java/lang/IndexOutOfBoundsException.java \
+java/lang/InstantiationException.java \
 java/lang/InternalError.java \
 java/lang/InterruptedException.java \
 java/lang/LinkageError.java \
@@ -729,107 +789,42 @@ java/lang/UnsupportedOperationException.java \
 java/lang/VerifyError.java \
 java/lang/VirtualMachineError.java \
 java/lang/Void.java \
-java/lang/reflect/AccessibleObject.java        \
-java/lang/reflect/Array.java \
-java/lang/reflect/Constructor.java \
-java/lang/reflect/Field.java \
-java/lang/reflect/InvocationTargetException.java \
-java/lang/reflect/Member.java \
-java/lang/reflect/Method.java \
-java/lang/reflect/Modifier.java        \
-java/math/BigDecimal.java \
-java/math/BigInteger.java \
 java/net/BindException.java \
 java/net/ConnectException.java \
 java/net/ContentHandler.java \
 java/net/ContentHandlerFactory.java \
-java/net/DatagramPacket.java \
-java/net/DatagramSocket.java \
-java/net/DatagramSocketImpl.java \
 java/net/FileNameMap.java \
-java/net/HttpURLConnection.java \
+java/net/HttpURLConnection.java        \
 java/net/InetAddress.java \
-java/net/JarURLConnection.java \
 java/net/MalformedURLException.java \
-java/net/MulticastSocket.java \
 java/net/NoRouteToHostException.java \
-java/net/PlainDatagramSocketImpl.java \
 java/net/PlainSocketImpl.java \
 java/net/ProtocolException.java        \
 java/net/ServerSocket.java \
+java/net/URL.java \
 java/net/Socket.java \
 java/net/SocketException.java \
 java/net/SocketImpl.java \
 java/net/SocketImplFactory.java        \
-java/net/SocketOptions.java \
-java/net/URL.java \
-java/net/URLClassLoader.java \
 java/net/URLConnection.java \
-java/net/URLDecoder.java \
-java/net/URLEncoder.java \
 java/net/URLStreamHandler.java \
 java/net/URLStreamHandlerFactory.java \
 java/net/UnknownHostException.java \
 java/net/UnknownServiceException.java \
-java/security/AlgorithmParameterGeneratorSpi.java \
-java/security/DigestException.java \
-java/security/GeneralSecurityException.java \
-java/security/InvalidAlgorithmParameterException.java \
-java/security/InvalidKeyException.java \
-java/security/InvalidParameterException.java \
-java/security/Key.java \
-java/security/KeyException.java \
-java/security/KeyPair.java \
-java/security/KeyPairGenerator.java \
-java/security/KeyPairGeneratorSpi.java \
-java/security/MessageDigest.java \
-java/security/NoSuchAlgorithmException.java \
-java/security/NoSuchProviderException.java \
-java/security/PrivateKey.java \
-java/security/Provider.java \
-java/security/PublicKey.java \
-java/security/SecureClassLoader.java \
-java/security/SecureRandom.java \
-java/security/Security.java \
-java/security/Signature.java \
-java/security/SignatureException.java \
-java/security/interfaces/DSAKey.java \
-java/security/interfaces/DSAParams.java \
-java/security/interfaces/DSAPrivateKey.java \
-java/security/interfaces/DSAPublicKey.java \
-java/security/interfaces/RSAPrivateCrtKey.java \
-java/security/interfaces/RSAPrivateKey.java \
-java/security/interfaces/RSAPublicKey.java \
-java/security/spec/AlgorithmParameterSpec.java \
-java/security/spec/InvalidKeySpecException.java \
-java/security/spec/InvalidParameterSpecException.java \
-java/security/spec/KeySpec.java \
-java/security/spec/RSAPrivateCrtKeySpec.java \
-java/security/spec/RSAPrivateKeySpec.java \
-java/security/spec/RSAPublicKeySpec.java \
-java/sql/CallableStatement.java \
-java/sql/Connection.java \
-java/sql/DataTruncation.java \
-java/sql/DatabaseMetaData.java \
-java/sql/Date.java \
-java/sql/Driver.java \
-java/sql/DriverManager.java \
-java/sql/DriverPropertyInfo.java \
-java/sql/PreparedStatement.java \
-java/sql/ResultSet.java \
-java/sql/ResultSetMetaData.java \
-java/sql/SQLException.java \
-java/sql/SQLWarning.java \
-java/sql/Statement.java \
-java/sql/Time.java \
-java/sql/Timestamp.java \
-java/sql/Types.java \
+java/net/URLDecoder.java \
+java/net/URLEncoder.java \
+java/net/DatagramPacket.java \
+java/net/DatagramSocket.java \
+java/net/DatagramSocketImpl.java \
+java/net/MulticastSocket.java \
+java/net/PlainDatagramSocketImpl.java \
+java/net/SocketOptions.java \
+java/net/JarURLConnection.java \
+java/net/URLClassLoader.java \
+java/text/Collator.java        \
 java/text/BreakIterator.java \
 java/text/CharacterIterator.java \
 java/text/ChoiceFormat.java \
-java/text/CollationElementIterator.java \
-java/text/CollationKey.java \
-java/text/Collator.java \
 java/text/DateFormat.java \
 java/text/DateFormatSymbols.java \
 java/text/DecimalFormat.java \
@@ -840,13 +835,34 @@ java/text/MessageFormat.java \
 java/text/NumberFormat.java \
 java/text/ParseException.java \
 java/text/ParsePosition.java \
-java/text/RuleBasedCollator.java \
 java/text/SimpleDateFormat.java        \
 java/text/StringCharacterIterator.java \
+java/text/CollationElementIterator.java        \
+java/text/CollationKey.java \
+java/text/RuleBasedCollator.java \
+java/util/zip/Adler32.java \
+java/util/zip/CRC32.java \
+java/util/zip/Checksum.java \
+java/util/zip/Deflater.java \
+java/util/zip/DeflaterOutputStream.java        \
+java/util/zip/ZipConstants.java        \
+java/util/zip/ZipEntry.java \
+java/util/zip/ZipException.java        \
+java/util/zip/ZipFile.java \
+java/util/zip/ZipOutputStream.java \
+java/util/zip/InflaterInputStream.java \
+java/util/zip/ZipInputStream.java \
+java/util/zip/DataFormatException.java \
+java/util/zip/CheckedInputStream.java \
+java/util/zip/CheckedOutputStream.java \
+java/util/zip/Inflater.java \
+java/util/zip/GZIPInputStream.java \
+java/util/zip/GZIPOutputStream.java \
+java/util/jar/JarEntry.java \
+java/util/jar/JarFile.java \
+java/util/jar/JarInputStream.java \
 java/util/BitSet.java \
 java/util/Calendar.java        \
-java/util/Collection.java \
-java/util/Comparator.java \
 java/util/ConcurrentModificationException.java \
 java/util/Date.java \
 java/util/Dictionary.java \
@@ -856,9 +872,6 @@ java/util/EventListener.java \
 java/util/EventObject.java \
 java/util/GregorianCalendar.java \
 java/util/Hashtable.java \
-java/util/Iterator.java \
-java/util/List.java \
-java/util/ListIterator.java \
 java/util/ListResourceBundle.java \
 java/util/Locale.java \
 java/util/MissingResourceException.java        \
@@ -866,7 +879,6 @@ java/util/NoSuchElementException.java \
 java/util/Observable.java \
 java/util/Observer.java        \
 java/util/Properties.java \
-java/util/PropertyResourceBundle.java \
 java/util/Random.java \
 java/util/ResourceBundle.java \
 java/util/SimpleTimeZone.java \
@@ -875,27 +887,115 @@ java/util/StringTokenizer.java \
 java/util/TimeZone.java        \
 java/util/TooManyListenersException.java \
 java/util/Vector.java \
-java/util/jar/JarFile.java \
-java/util/jar/JarInputStream.java \
-java/util/jar/JarEntry.java \
-java/util/zip/Adler32.java \
-java/util/zip/CRC32.java \
-java/util/zip/CheckedInputStream.java \
-java/util/zip/CheckedOutputStream.java \
-java/util/zip/Checksum.java \
-java/util/zip/DataFormatException.java \
-java/util/zip/Deflater.java \
-java/util/zip/DeflaterOutputStream.java        \
-java/util/zip/GZIPInputStream.java \
-java/util/zip/GZIPOutputStream.java \
-java/util/zip/Inflater.java \
-java/util/zip/InflaterInputStream.java \
-java/util/zip/ZipConstants.java        \
-java/util/zip/ZipEntry.java \
-java/util/zip/ZipException.java        \
-java/util/zip/ZipFile.java \
-java/util/zip/ZipInputStream.java \
-java/util/zip/ZipOutputStream.java
+java/util/List.java \
+java/util/Collection.java \
+java/util/Comparator.java \
+java/util/Iterator.java        \
+java/util/PropertyResourceBundle.java \
+java/util/Arrays.java \
+java/util/ListIterator.java \
+java/util/AbstractCollection.java \
+java/util/AbstractList.java \
+java/security/MessageDigest.java \
+java/security/NoSuchAlgorithmException.java \
+java/security/SecureClassLoader.java \
+java/security/interfaces/DSAKey.java \
+java/security/interfaces/DSAParams.java        \
+java/security/interfaces/DSAPrivateKey.java \
+java/security/interfaces/DSAPublicKey.java \
+java/security/interfaces/RSAPrivateCrtKey.java \
+java/security/interfaces/RSAPrivateKey.java \
+java/security/interfaces/RSAPublicKey.java \
+java/security/AlgorithmParameterGeneratorSpi.java \
+java/security/DigestException.java \
+java/security/GeneralSecurityException.java \
+java/security/InvalidAlgorithmParameterException.java \
+java/security/InvalidKeyException.java \
+java/security/InvalidParameterException.java \
+java/security/Key.java \
+java/security/KeyException.java        \
+java/security/KeyPair.java \
+java/security/KeyPairGenerator.java \
+java/security/KeyPairGeneratorSpi.java \
+java/security/NoSuchProviderException.java \
+java/security/PrivateKey.java \
+java/security/Provider.java \
+java/security/PublicKey.java \
+java/security/SecureRandom.java        \
+java/security/Security.java \
+java/security/Signature.java \
+java/security/SignatureException.java \
+java/security/spec/AlgorithmParameterSpec.java \
+java/security/spec/InvalidKeySpecException.java        \
+java/security/spec/InvalidParameterSpecException.java \
+java/security/spec/KeySpec.java        \
+java/security/spec/RSAPrivateCrtKeySpec.java \
+java/security/spec/RSAPrivateKeySpec.java \
+java/security/spec/RSAPublicKeySpec.java \
+java/security/BasicPermission.java \
+java/security/Guard.java \
+java/security/DigestOutputStream.java \
+java/security/Permission.java \
+java/security/PermissionCollection.java        \
+java/math/BigDecimal.java \
+java/math/BigInteger.java \
+java/sql/CallableStatement.java        \
+java/sql/Connection.java \
+java/sql/DataTruncation.java \
+java/sql/DatabaseMetaData.java \
+java/sql/Date.java \
+java/sql/Driver.java \
+java/sql/DriverManager.java \
+java/sql/DriverPropertyInfo.java \
+java/sql/PreparedStatement.java        \
+java/sql/ResultSet.java        \
+java/sql/ResultSetMetaData.java        \
+java/sql/SQLException.java \
+java/sql/SQLWarning.java \
+java/sql/Statement.java        \
+java/sql/Time.java \
+java/sql/Timestamp.java        \
+java/sql/Types.java \
+java/beans/beancontext/BeanContext.java        \
+java/beans/beancontext/BeanContextChild.java \
+java/beans/beancontext/BeanContextChildComponentProxy.java \
+java/beans/beancontext/BeanContextChildSupport.java \
+java/beans/beancontext/BeanContextContainerProxy.java \
+java/beans/beancontext/BeanContextEvent.java \
+java/beans/beancontext/BeanContextMembershipEvent.java \
+java/beans/beancontext/BeanContextMembershipListener.java \
+java/beans/beancontext/BeanContextProxy.java \
+java/beans/beancontext/BeanContextServiceAvailableEvent.java \
+java/beans/beancontext/BeanContextServiceProvider.java \
+java/beans/beancontext/BeanContextServiceProviderBeanInfo.java \
+java/beans/beancontext/BeanContextServiceRevokedEvent.java \
+java/beans/beancontext/BeanContextServiceRevokedListener.java \
+java/beans/beancontext/BeanContextServices.java        \
+java/beans/beancontext/BeanContextServicesListener.java        \
+java/beans/BeanDescriptor.java \
+java/beans/BeanInfo.java \
+java/beans/Beans.java \
+java/beans/Customizer.java \
+java/beans/DesignMode.java \
+java/beans/EventSetDescriptor.java \
+java/beans/FeatureDescriptor.java \
+java/beans/IndexedPropertyDescriptor.java \
+java/beans/IntrospectionException.java \
+java/beans/Introspector.java \
+java/beans/MethodDescriptor.java \
+java/beans/ParameterDescriptor.java \
+java/beans/PropertyChangeEvent.java \
+java/beans/PropertyChangeListener.java \
+java/beans/PropertyChangeSupport.java \
+java/beans/PropertyDescriptor.java \
+java/beans/PropertyEditor.java \
+java/beans/PropertyEditorManager.java \
+java/beans/PropertyEditorSupport.java \
+java/beans/PropertyVetoException.java \
+java/beans/SimpleBeanInfo.java \
+java/beans/VetoableChangeListener.java \
+java/beans/VetoableChangeSupport.java \
+java/beans/Visibility.java
 
 java_source_files = $(ordinary_java_source_files) $(special_java_source_files)
 
@@ -927,10 +1027,14 @@ gnu/gcj/convert/natInput_EUCJIS.cc \
 gnu/gcj/convert/natInput_SJIS.cc \
 gnu/gcj/convert/natOutput_EUCJIS.cc \
 gnu/gcj/convert/natOutput_SJIS.cc \
+gnu/gcj/io/natSimpleSHSStream.cc \
+gnu/gcj/io/shs.cc \
 gnu/gcj/jni/natNativeThread.cc \
 gnu/gcj/runtime/natFirstThread.cc \
 java/io/natFile.cc \
 java/io/natFileDescriptor.cc \
+java/io/natObjectInputStream.cc \
+java/io/natObjectOutputStream.cc \
 java/lang/natCharacter.cc \
 java/lang/natClass.cc \
 java/lang/natClassLoader.cc \
@@ -1035,12 +1139,3 @@ distclean-multi:
        $(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean
 maintainer-clean-multi:
        $(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean
-
-
-## ################################################################
-
-
-## See above.
-cygnus_hack =
-
-
index 7038e2e..881731b 100644 (file)
@@ -98,6 +98,7 @@ OBJDUMP = @OBJDUMP@
 PACKAGE = @PACKAGE@
 PERL = @PERL@
 RANLIB = @RANLIB@
+SYSDEP_SOURCES = @SYSDEP_SOURCES@
 SYSTEMSPEC = @SYSTEMSPEC@
 THREADDEPS = @THREADDEPS@
 THREADINCS = @THREADINCS@
@@ -138,6 +139,8 @@ data_DATA = libgcj.zip
 
 @NATIVE_TRUE@bin_PROGRAMS = \
 @NATIVE_TRUE@jv-convert gij
+
+bin_SCRIPTS = addr2name.awk
 @CANADIAN_TRUE@@NULL_TARGET_TRUE@GCJ = \
 @CANADIAN_TRUE@@NULL_TARGET_TRUE@gcj
 @CANADIAN_TRUE@@NULL_TARGET_FALSE@GCJ = \
@@ -229,7 +232,9 @@ SUFFIXES = .class .java .h
 
 nat_headers = $(ordinary_java_source_files:.java=.h) \
        $(built_java_source_files:.java=.h) \
-       $(cond_awt_java_source_files:.java=.h)
+       $(cond_awt_java_source_files:.java=.h) \
+       java/io/ObjectOutputStream$$PutField.h \
+       java/io/ObjectInputStream$$GetField.h
 
 
 extra_headers = java/lang/Object.h java/lang/Class.h
@@ -293,23 +298,48 @@ gnu/gcj/convert/UnicodeToBytes.java
 special_java_source_files = java/lang/Class.java java/lang/Object.java
 
 awt_java_source_files = \
-java/awt/AWTError.java \
+java/awt/event/ActionEvent.java        \
+java/awt/event/ActionListener.java \
+java/awt/event/ComponentEvent.java \
+java/awt/event/KeyAdapter.java \
+java/awt/event/InputEvent.java \
+java/awt/event/KeyEvent.java \
+java/awt/event/KeyListener.java        \
+java/awt/event/TextEvent.java \
+java/awt/event/TextListener.java \
+java/awt/event/WindowAdapter.java \
+java/awt/event/WindowEvent.java        \
+java/awt/event/WindowListener.java \
+java/awt/event/InputMethodListener.java        \
+java/awt/event/ComponentListener.java \
+java/awt/event/AdjustmentListener.java \
+java/awt/event/AWTEventListener.java \
+java/awt/event/FocusListener.java \
+java/awt/event/AdjustmentEvent.java \
+java/awt/event/ItemListener.java \
+java/awt/event/ContainerListener.java \
+java/awt/event/MouseListener.java \
+java/awt/event/MouseMotionListener.java        \
+java/awt/event/ComponentAdapter.java \
+java/awt/event/ContainerAdapter.java \
+java/awt/event/FocusAdapter.java \
+java/awt/event/MouseAdapter.java \
+java/awt/event/MouseMotionAdapter.java \
+java/awt/event/FocusEvent.java \
+java/awt/event/InputMethodEvent.java \
+java/awt/event/MouseEvent.java \
+java/awt/event/ItemEvent.java \
+java/awt/event/InvocationEvent.java \
+java/awt/event/PaintEvent.java \
+java/awt/event/ContainerEvent.java \
 java/awt/AWTEvent.java \
-java/awt/AWTException.java \
-java/awt/ActiveEvent.java \
-java/awt/Adjustable.java \
 java/awt/BorderLayout.java \
-java/awt/Color.java \
 java/awt/Component.java        \
 java/awt/Container.java        \
 java/awt/Dimension.java        \
 java/awt/Event.java \
 java/awt/Font.java \
 java/awt/Frame.java \
-java/awt/Graphics.java \
-java/awt/IllegalComponentStateException.java \
-java/awt/Image.java \
-java/awt/ItemSelectable.java \
 java/awt/LayoutManager.java \
 java/awt/LayoutManager2.java \
 java/awt/Menu.java \
@@ -317,56 +347,31 @@ java/awt/MenuBar.java \
 java/awt/MenuComponent.java \
 java/awt/MenuContainer.java \
 java/awt/MenuItem.java \
-java/awt/Paint.java \
-java/awt/PaintContext.java \
 java/awt/Point.java \
-java/awt/Rectangle.java        \
+java/awt/AWTError.java \
 java/awt/Shape.java \
 java/awt/TextArea.java \
 java/awt/TextComponent.java \
 java/awt/Toolkit.java \
-java/awt/Transparency.java \
 java/awt/Window.java \
-java/awt/event/AWTEventListener.java \
-java/awt/event/ActionEvent.java        \
-java/awt/event/ActionListener.java \
-java/awt/event/AdjustmentEvent.java \
-java/awt/event/AdjustmentListener.java \
-java/awt/event/ComponentAdapter.java \
-java/awt/event/ComponentEvent.java \
-java/awt/event/ComponentListener.java \
-java/awt/event/ContainerAdapter.java \
-java/awt/event/ContainerEvent.java \
-java/awt/event/ContainerListener.java \
-java/awt/event/FocusAdapter.java \
-java/awt/event/FocusEvent.java \
-java/awt/event/FocusListener.java \
-java/awt/event/InputEvent.java \
-java/awt/event/InputMethodEvent.java \
-java/awt/event/InputMethodListener.java        \
-java/awt/event/InvocationEvent.java \
-java/awt/event/ItemEvent.java \
-java/awt/event/ItemListener.java \
-java/awt/event/KeyAdapter.java \
-java/awt/event/KeyEvent.java \
-java/awt/event/KeyListener.java        \
-java/awt/event/MouseAdapter.java \
-java/awt/event/MouseEvent.java \
-java/awt/event/MouseListener.java \
-java/awt/event/MouseMotionAdapter.java \
-java/awt/event/MouseMotionListener.java        \
-java/awt/event/PaintEvent.java \
-java/awt/event/TextEvent.java \
-java/awt/event/TextListener.java \
-java/awt/event/WindowAdapter.java \
-java/awt/event/WindowEvent.java        \
-java/awt/event/WindowListener.java \
 java/awt/geom/Dimension2D.java \
 java/awt/geom/Point2D.java \
 java/awt/peer/ComponentPeer.java \
 java/awt/peer/ContainerPeer.java \
 java/awt/peer/FramePeer.java \
-java/awt/peer/WindowPeer.java
+java/awt/peer/WindowPeer.java \
+java/awt/Adjustable.java \
+java/awt/Color.java \
+java/awt/Graphics.java \
+java/awt/Image.java \
+java/awt/Paint.java \
+java/awt/PaintContext.java \
+java/awt/Transparency.java \
+java/awt/ItemSelectable.java \
+java/awt/AWTException.java \
+java/awt/ActiveEvent.java \
+java/awt/Rectangle.java        \
+java/awt/IllegalComponentStateException.java
 
 @AWT_TRUE@cond_awt_java_source_files = \
 @AWT_TRUE@$(awt_java_source_files)
@@ -375,11 +380,12 @@ java/awt/peer/WindowPeer.java
 built_java_source_files = java/lang/ConcreteProcess.java
 
 ordinary_java_source_files = $(convert_source_files) \
-gnu/gcj/io/DefaultMimeTypes.java \
-gnu/gcj/io/MimeTypes.java \
-gnu/gcj/jni/NativeThread.java \
-gnu/gcj/runtime/VMClassLoader.java \
-gnu/gcj/runtime/FirstThread.java \
+gnu/gcj/protocol/http/Connection.java \
+gnu/gcj/protocol/http/Handler.java \
+gnu/gcj/protocol/file/Connection.java \
+gnu/gcj/protocol/file/Handler.java \
+gnu/gcj/protocol/jar/Connection.java \
+gnu/gcj/protocol/jar/Handler.java \
 gnu/gcj/text/BaseBreakIterator.java \
 gnu/gcj/text/CharacterBreakIterator.java \
 gnu/gcj/text/LineBreakIterator.java \
@@ -387,15 +393,36 @@ gnu/gcj/text/LocaleData_en.java   \
 gnu/gcj/text/LocaleData_en_US.java \
 gnu/gcj/text/SentenceBreakIterator.java        \
 gnu/gcj/text/WordBreakIterator.java \
-gnu/gcj/math/MPN.java \
-gnu/gcj/protocol/file/Connection.java \
-gnu/gcj/protocol/file/Handler.java \
-gnu/gcj/protocol/http/Connection.java \
-gnu/gcj/protocol/http/Handler.java \
-gnu/gcj/protocol/jar/Handler.java \
-gnu/gcj/protocol/jar/Connection.java \
-gnu/gcj/RawData.java \
 gnu/gcj/util/EnumerationChain.java \
+gnu/gcj/RawData.java \
+gnu/gcj/math/MPN.java \
+gnu/gcj/runtime/VMClassLoader.java \
+gnu/gcj/runtime/FirstThread.java \
+gnu/gcj/jni/NativeThread.java \
+gnu/gcj/io/DefaultMimeTypes.java \
+gnu/gcj/io/MimeTypes.java \
+gnu/gcj/io/SimpleSHSStream.java        \
+gnu/java/beans/editors/ColorEditor.java        \
+gnu/java/beans/editors/FontEditor.java \
+gnu/java/beans/editors/NativeBooleanEditor.java        \
+gnu/java/beans/editors/NativeByteEditor.java \
+gnu/java/beans/editors/NativeDoubleEditor.java \
+gnu/java/beans/editors/NativeFloatEditor.java \
+gnu/java/beans/editors/NativeIntEditor.java \
+gnu/java/beans/editors/NativeLongEditor.java \
+gnu/java/beans/editors/NativeShortEditor.java \
+gnu/java/beans/editors/StringEditor.java \
+gnu/java/beans/info/ComponentBeanInfo.java \
+gnu/java/beans/BeanInfoEmbryo.java \
+gnu/java/beans/EmptyBeanInfo.java \
+gnu/java/beans/ExplicitBeanInfo.java \
+gnu/java/beans/IntrospectionIncubator.java \
+gnu/java/io/ClassLoaderObjectInputStream.java \
+gnu/java/io/NullOutputStream.java \
+gnu/java/io/ObjectIdentityWrapper.java \
+gnu/java/lang/reflect/TypeSignature.java \
+gnu/java/lang/ArrayHelper.java \
+gnu/java/lang/ClassHelper.java \
 java/io/BufferedInputStream.java \
 java/io/BufferedOutputStream.java \
 java/io/BufferedReader.java \
@@ -411,7 +438,6 @@ java/io/DataOutput.java     \
 java/io/DataOutputStream.java \
 java/io/EOFException.java \
 java/io/File.java \
-java/io/FileDescriptor.java \
 java/io/FileInputStream.java \
 java/io/FileNotFoundException.java \
 java/io/FileOutputStream.java \
@@ -428,11 +454,10 @@ java/io/InputStreamReader.java \
 java/io/InterruptedIOException.java \
 java/io/LineNumberInputStream.java \
 java/io/LineNumberReader.java \
-java/io/ObjectStreamException.java \
-java/io/OptionalDataException.java \
 java/io/OutputStream.java \
 java/io/OutputStreamWriter.java        \
-java/io/PipedInputStream.java \
+java/io/Externalizable.java \
+java/io/FileDescriptor.java \
 java/io/PipedOutputStream.java \
 java/io/PipedReader.java \
 java/io/PipedWriter.java \
@@ -444,7 +469,6 @@ java/io/RandomAccessFile.java \
 java/io/Reader.java \
 java/io/SequenceInputStream.java \
 java/io/Serializable.java \
-java/io/StreamCorruptedException.java \
 java/io/StreamTokenizer.java \
 java/io/StringBufferInputStream.java \
 java/io/StringReader.java \
@@ -453,6 +477,35 @@ java/io/SyncFailedException.java \
 java/io/UTFDataFormatException.java \
 java/io/UnsupportedEncodingException.java \
 java/io/Writer.java \
+java/io/ObjectStreamException.java \
+java/io/OptionalDataException.java \
+java/io/StreamCorruptedException.java \
+java/io/BlockDataException.java        \
+java/io/InvalidClassException.java \
+java/io/InvalidObjectException.java \
+java/io/NotActiveException.java        \
+java/io/NotSerializableException.java \
+java/io/ObjectInput.java \
+java/io/ObjectInputStream.java \
+java/io/ObjectInputValidation.java \
+java/io/ObjectOutput.java \
+java/io/ObjectOutputStream.java        \
+java/io/ObjectStreamClass.java \
+java/io/ObjectStreamConstants.java \
+java/io/ObjectStreamField.java \
+java/io/Replaceable.java \
+java/io/Resolvable.java        \
+java/io/SerializablePermission.java \
+java/io/WriteAbortedException.java \
+java/io/PipedInputStream.java \
+java/lang/reflect/Constructor.java \
+java/lang/reflect/AccessibleObject.java        \
+java/lang/reflect/Array.java \
+java/lang/reflect/Method.java \
+java/lang/reflect/Field.java \
+java/lang/reflect/InvocationTargetException.java \
+java/lang/reflect/Member.java \
+java/lang/reflect/Modifier.java        \
 java/lang/AbstractMethodError.java \
 java/lang/ArithmeticException.java \
 java/lang/ArrayIndexOutOfBoundsException.java \
@@ -481,10 +534,10 @@ java/lang/IllegalMonitorStateException.java \
 java/lang/IllegalStateException.java \
 java/lang/IllegalThreadStateException.java \
 java/lang/IncompatibleClassChangeError.java \
-java/lang/IndexOutOfBoundsException.java \
 java/lang/InstantiationError.java \
-java/lang/InstantiationException.java \
 java/lang/Integer.java \
+java/lang/IndexOutOfBoundsException.java \
+java/lang/InstantiationException.java \
 java/lang/InternalError.java \
 java/lang/InterruptedException.java \
 java/lang/LinkageError.java \
@@ -522,107 +575,42 @@ java/lang/UnsupportedOperationException.java \
 java/lang/VerifyError.java \
 java/lang/VirtualMachineError.java \
 java/lang/Void.java \
-java/lang/reflect/AccessibleObject.java        \
-java/lang/reflect/Array.java \
-java/lang/reflect/Constructor.java \
-java/lang/reflect/Field.java \
-java/lang/reflect/InvocationTargetException.java \
-java/lang/reflect/Member.java \
-java/lang/reflect/Method.java \
-java/lang/reflect/Modifier.java        \
-java/math/BigDecimal.java \
-java/math/BigInteger.java \
 java/net/BindException.java \
 java/net/ConnectException.java \
 java/net/ContentHandler.java \
 java/net/ContentHandlerFactory.java \
-java/net/DatagramPacket.java \
-java/net/DatagramSocket.java \
-java/net/DatagramSocketImpl.java \
 java/net/FileNameMap.java \
-java/net/HttpURLConnection.java \
+java/net/HttpURLConnection.java        \
 java/net/InetAddress.java \
-java/net/JarURLConnection.java \
 java/net/MalformedURLException.java \
-java/net/MulticastSocket.java \
 java/net/NoRouteToHostException.java \
-java/net/PlainDatagramSocketImpl.java \
 java/net/PlainSocketImpl.java \
 java/net/ProtocolException.java        \
 java/net/ServerSocket.java \
+java/net/URL.java \
 java/net/Socket.java \
 java/net/SocketException.java \
 java/net/SocketImpl.java \
 java/net/SocketImplFactory.java        \
-java/net/SocketOptions.java \
-java/net/URL.java \
-java/net/URLClassLoader.java \
 java/net/URLConnection.java \
-java/net/URLDecoder.java \
-java/net/URLEncoder.java \
 java/net/URLStreamHandler.java \
 java/net/URLStreamHandlerFactory.java \
 java/net/UnknownHostException.java \
 java/net/UnknownServiceException.java \
-java/security/AlgorithmParameterGeneratorSpi.java \
-java/security/DigestException.java \
-java/security/GeneralSecurityException.java \
-java/security/InvalidAlgorithmParameterException.java \
-java/security/InvalidKeyException.java \
-java/security/InvalidParameterException.java \
-java/security/Key.java \
-java/security/KeyException.java \
-java/security/KeyPair.java \
-java/security/KeyPairGenerator.java \
-java/security/KeyPairGeneratorSpi.java \
-java/security/MessageDigest.java \
-java/security/NoSuchAlgorithmException.java \
-java/security/NoSuchProviderException.java \
-java/security/PrivateKey.java \
-java/security/Provider.java \
-java/security/PublicKey.java \
-java/security/SecureClassLoader.java \
-java/security/SecureRandom.java \
-java/security/Security.java \
-java/security/Signature.java \
-java/security/SignatureException.java \
-java/security/interfaces/DSAKey.java \
-java/security/interfaces/DSAParams.java \
-java/security/interfaces/DSAPrivateKey.java \
-java/security/interfaces/DSAPublicKey.java \
-java/security/interfaces/RSAPrivateCrtKey.java \
-java/security/interfaces/RSAPrivateKey.java \
-java/security/interfaces/RSAPublicKey.java \
-java/security/spec/AlgorithmParameterSpec.java \
-java/security/spec/InvalidKeySpecException.java \
-java/security/spec/InvalidParameterSpecException.java \
-java/security/spec/KeySpec.java \
-java/security/spec/RSAPrivateCrtKeySpec.java \
-java/security/spec/RSAPrivateKeySpec.java \
-java/security/spec/RSAPublicKeySpec.java \
-java/sql/CallableStatement.java \
-java/sql/Connection.java \
-java/sql/DataTruncation.java \
-java/sql/DatabaseMetaData.java \
-java/sql/Date.java \
-java/sql/Driver.java \
-java/sql/DriverManager.java \
-java/sql/DriverPropertyInfo.java \
-java/sql/PreparedStatement.java \
-java/sql/ResultSet.java \
-java/sql/ResultSetMetaData.java \
-java/sql/SQLException.java \
-java/sql/SQLWarning.java \
-java/sql/Statement.java \
-java/sql/Time.java \
-java/sql/Timestamp.java \
-java/sql/Types.java \
+java/net/URLDecoder.java \
+java/net/URLEncoder.java \
+java/net/DatagramPacket.java \
+java/net/DatagramSocket.java \
+java/net/DatagramSocketImpl.java \
+java/net/MulticastSocket.java \
+java/net/PlainDatagramSocketImpl.java \
+java/net/SocketOptions.java \
+java/net/JarURLConnection.java \
+java/net/URLClassLoader.java \
+java/text/Collator.java        \
 java/text/BreakIterator.java \
 java/text/CharacterIterator.java \
 java/text/ChoiceFormat.java \
-java/text/CollationElementIterator.java \
-java/text/CollationKey.java \
-java/text/Collator.java \
 java/text/DateFormat.java \
 java/text/DateFormatSymbols.java \
 java/text/DecimalFormat.java \
@@ -633,13 +621,34 @@ java/text/MessageFormat.java \
 java/text/NumberFormat.java \
 java/text/ParseException.java \
 java/text/ParsePosition.java \
-java/text/RuleBasedCollator.java \
 java/text/SimpleDateFormat.java        \
 java/text/StringCharacterIterator.java \
+java/text/CollationElementIterator.java        \
+java/text/CollationKey.java \
+java/text/RuleBasedCollator.java \
+java/util/zip/Adler32.java \
+java/util/zip/CRC32.java \
+java/util/zip/Checksum.java \
+java/util/zip/Deflater.java \
+java/util/zip/DeflaterOutputStream.java        \
+java/util/zip/ZipConstants.java        \
+java/util/zip/ZipEntry.java \
+java/util/zip/ZipException.java        \
+java/util/zip/ZipFile.java \
+java/util/zip/ZipOutputStream.java \
+java/util/zip/InflaterInputStream.java \
+java/util/zip/ZipInputStream.java \
+java/util/zip/DataFormatException.java \
+java/util/zip/CheckedInputStream.java \
+java/util/zip/CheckedOutputStream.java \
+java/util/zip/Inflater.java \
+java/util/zip/GZIPInputStream.java \
+java/util/zip/GZIPOutputStream.java \
+java/util/jar/JarEntry.java \
+java/util/jar/JarFile.java \
+java/util/jar/JarInputStream.java \
 java/util/BitSet.java \
 java/util/Calendar.java        \
-java/util/Collection.java \
-java/util/Comparator.java \
 java/util/ConcurrentModificationException.java \
 java/util/Date.java \
 java/util/Dictionary.java \
@@ -649,9 +658,6 @@ java/util/EventListener.java \
 java/util/EventObject.java \
 java/util/GregorianCalendar.java \
 java/util/Hashtable.java \
-java/util/Iterator.java \
-java/util/List.java \
-java/util/ListIterator.java \
 java/util/ListResourceBundle.java \
 java/util/Locale.java \
 java/util/MissingResourceException.java        \
@@ -659,7 +665,6 @@ java/util/NoSuchElementException.java \
 java/util/Observable.java \
 java/util/Observer.java        \
 java/util/Properties.java \
-java/util/PropertyResourceBundle.java \
 java/util/Random.java \
 java/util/ResourceBundle.java \
 java/util/SimpleTimeZone.java \
@@ -668,27 +673,115 @@ java/util/StringTokenizer.java \
 java/util/TimeZone.java        \
 java/util/TooManyListenersException.java \
 java/util/Vector.java \
-java/util/jar/JarFile.java \
-java/util/jar/JarInputStream.java \
-java/util/jar/JarEntry.java \
-java/util/zip/Adler32.java \
-java/util/zip/CRC32.java \
-java/util/zip/CheckedInputStream.java \
-java/util/zip/CheckedOutputStream.java \
-java/util/zip/Checksum.java \
-java/util/zip/DataFormatException.java \
-java/util/zip/Deflater.java \
-java/util/zip/DeflaterOutputStream.java        \
-java/util/zip/GZIPInputStream.java \
-java/util/zip/GZIPOutputStream.java \
-java/util/zip/Inflater.java \
-java/util/zip/InflaterInputStream.java \
-java/util/zip/ZipConstants.java        \
-java/util/zip/ZipEntry.java \
-java/util/zip/ZipException.java        \
-java/util/zip/ZipFile.java \
-java/util/zip/ZipInputStream.java \
-java/util/zip/ZipOutputStream.java
+java/util/List.java \
+java/util/Collection.java \
+java/util/Comparator.java \
+java/util/Iterator.java        \
+java/util/PropertyResourceBundle.java \
+java/util/Arrays.java \
+java/util/ListIterator.java \
+java/util/AbstractCollection.java \
+java/util/AbstractList.java \
+java/security/MessageDigest.java \
+java/security/NoSuchAlgorithmException.java \
+java/security/SecureClassLoader.java \
+java/security/interfaces/DSAKey.java \
+java/security/interfaces/DSAParams.java        \
+java/security/interfaces/DSAPrivateKey.java \
+java/security/interfaces/DSAPublicKey.java \
+java/security/interfaces/RSAPrivateCrtKey.java \
+java/security/interfaces/RSAPrivateKey.java \
+java/security/interfaces/RSAPublicKey.java \
+java/security/AlgorithmParameterGeneratorSpi.java \
+java/security/DigestException.java \
+java/security/GeneralSecurityException.java \
+java/security/InvalidAlgorithmParameterException.java \
+java/security/InvalidKeyException.java \
+java/security/InvalidParameterException.java \
+java/security/Key.java \
+java/security/KeyException.java        \
+java/security/KeyPair.java \
+java/security/KeyPairGenerator.java \
+java/security/KeyPairGeneratorSpi.java \
+java/security/NoSuchProviderException.java \
+java/security/PrivateKey.java \
+java/security/Provider.java \
+java/security/PublicKey.java \
+java/security/SecureRandom.java        \
+java/security/Security.java \
+java/security/Signature.java \
+java/security/SignatureException.java \
+java/security/spec/AlgorithmParameterSpec.java \
+java/security/spec/InvalidKeySpecException.java        \
+java/security/spec/InvalidParameterSpecException.java \
+java/security/spec/KeySpec.java        \
+java/security/spec/RSAPrivateCrtKeySpec.java \
+java/security/spec/RSAPrivateKeySpec.java \
+java/security/spec/RSAPublicKeySpec.java \
+java/security/BasicPermission.java \
+java/security/Guard.java \
+java/security/DigestOutputStream.java \
+java/security/Permission.java \
+java/security/PermissionCollection.java        \
+java/math/BigDecimal.java \
+java/math/BigInteger.java \
+java/sql/CallableStatement.java        \
+java/sql/Connection.java \
+java/sql/DataTruncation.java \
+java/sql/DatabaseMetaData.java \
+java/sql/Date.java \
+java/sql/Driver.java \
+java/sql/DriverManager.java \
+java/sql/DriverPropertyInfo.java \
+java/sql/PreparedStatement.java        \
+java/sql/ResultSet.java        \
+java/sql/ResultSetMetaData.java        \
+java/sql/SQLException.java \
+java/sql/SQLWarning.java \
+java/sql/Statement.java        \
+java/sql/Time.java \
+java/sql/Timestamp.java        \
+java/sql/Types.java \
+java/beans/beancontext/BeanContext.java        \
+java/beans/beancontext/BeanContextChild.java \
+java/beans/beancontext/BeanContextChildComponentProxy.java \
+java/beans/beancontext/BeanContextChildSupport.java \
+java/beans/beancontext/BeanContextContainerProxy.java \
+java/beans/beancontext/BeanContextEvent.java \
+java/beans/beancontext/BeanContextMembershipEvent.java \
+java/beans/beancontext/BeanContextMembershipListener.java \
+java/beans/beancontext/BeanContextProxy.java \
+java/beans/beancontext/BeanContextServiceAvailableEvent.java \
+java/beans/beancontext/BeanContextServiceProvider.java \
+java/beans/beancontext/BeanContextServiceProviderBeanInfo.java \
+java/beans/beancontext/BeanContextServiceRevokedEvent.java \
+java/beans/beancontext/BeanContextServiceRevokedListener.java \
+java/beans/beancontext/BeanContextServices.java        \
+java/beans/beancontext/BeanContextServicesListener.java        \
+java/beans/BeanDescriptor.java \
+java/beans/BeanInfo.java \
+java/beans/Beans.java \
+java/beans/Customizer.java \
+java/beans/DesignMode.java \
+java/beans/EventSetDescriptor.java \
+java/beans/FeatureDescriptor.java \
+java/beans/IndexedPropertyDescriptor.java \
+java/beans/IntrospectionException.java \
+java/beans/Introspector.java \
+java/beans/MethodDescriptor.java \
+java/beans/ParameterDescriptor.java \
+java/beans/PropertyChangeEvent.java \
+java/beans/PropertyChangeListener.java \
+java/beans/PropertyChangeSupport.java \
+java/beans/PropertyDescriptor.java \
+java/beans/PropertyEditor.java \
+java/beans/PropertyEditorManager.java \
+java/beans/PropertyEditorSupport.java \
+java/beans/PropertyVetoException.java \
+java/beans/SimpleBeanInfo.java \
+java/beans/VetoableChangeListener.java \
+java/beans/VetoableChangeSupport.java \
+java/beans/Visibility.java
 
 
 java_source_files = $(ordinary_java_source_files) $(special_java_source_files)
@@ -720,10 +813,14 @@ gnu/gcj/convert/natInput_EUCJIS.cc \
 gnu/gcj/convert/natInput_SJIS.cc \
 gnu/gcj/convert/natOutput_EUCJIS.cc \
 gnu/gcj/convert/natOutput_SJIS.cc \
+gnu/gcj/io/natSimpleSHSStream.cc \
+gnu/gcj/io/shs.cc \
 gnu/gcj/jni/natNativeThread.cc \
 gnu/gcj/runtime/natFirstThread.cc \
 java/io/natFile.cc \
 java/io/natFileDescriptor.cc \
+java/io/natObjectInputStream.cc \
+java/io/natObjectOutputStream.cc \
 java/lang/natCharacter.cc \
 java/lang/natClass.cc \
 java/lang/natClassLoader.cc \
@@ -800,8 +897,6 @@ MULTIDIRS =
 MULTISUBDIR = 
 MULTIDO = true
 MULTICLEAN = true
-
-cygnus_hack = 
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
 CONFIG_HEADER = ./include/config.h
@@ -829,6 +924,8 @@ jv_convert_OBJECTS =
 gij_OBJECTS =  gij.o
 gen_from_JIS_OBJECTS = 
 gen_from_JIS_LDFLAGS = 
+SCRIPTS =  $(bin_SCRIPTS)
+
 CXXFLAGS = @CXXFLAGS@
 CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
 LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -868,8 +965,8 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/gnu/gcj/convert/Output_iconv.P \
 .deps/gnu/gcj/convert/UnicodeToBytes.P \
 .deps/gnu/gcj/io/DefaultMimeTypes.P .deps/gnu/gcj/io/MimeTypes.P \
-.deps/gnu/gcj/jni/NativeThread.P .deps/gnu/gcj/math/MPN.P \
-.deps/gnu/gcj/protocol/file/Connection.P \
+.deps/gnu/gcj/io/SimpleSHSStream.P .deps/gnu/gcj/jni/NativeThread.P \
+.deps/gnu/gcj/math/MPN.P .deps/gnu/gcj/protocol/file/Connection.P \
 .deps/gnu/gcj/protocol/file/Handler.P \
 .deps/gnu/gcj/protocol/http/Connection.P \
 .deps/gnu/gcj/protocol/http/Handler.P \
@@ -884,7 +981,27 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/gnu/gcj/text/LocaleData_en_US.P \
 .deps/gnu/gcj/text/SentenceBreakIterator.P \
 .deps/gnu/gcj/text/WordBreakIterator.P \
-.deps/gnu/gcj/util/EnumerationChain.P .deps/interpret.P \
+.deps/gnu/gcj/util/EnumerationChain.P \
+.deps/gnu/java/beans/BeanInfoEmbryo.P \
+.deps/gnu/java/beans/EmptyBeanInfo.P \
+.deps/gnu/java/beans/ExplicitBeanInfo.P \
+.deps/gnu/java/beans/IntrospectionIncubator.P \
+.deps/gnu/java/beans/editors/ColorEditor.P \
+.deps/gnu/java/beans/editors/FontEditor.P \
+.deps/gnu/java/beans/editors/NativeBooleanEditor.P \
+.deps/gnu/java/beans/editors/NativeByteEditor.P \
+.deps/gnu/java/beans/editors/NativeDoubleEditor.P \
+.deps/gnu/java/beans/editors/NativeFloatEditor.P \
+.deps/gnu/java/beans/editors/NativeIntEditor.P \
+.deps/gnu/java/beans/editors/NativeLongEditor.P \
+.deps/gnu/java/beans/editors/NativeShortEditor.P \
+.deps/gnu/java/beans/editors/StringEditor.P \
+.deps/gnu/java/beans/info/ComponentBeanInfo.P \
+.deps/gnu/java/io/ClassLoaderObjectInputStream.P \
+.deps/gnu/java/io/NullOutputStream.P \
+.deps/gnu/java/io/ObjectIdentityWrapper.P \
+.deps/gnu/java/lang/ArrayHelper.P .deps/gnu/java/lang/ClassHelper.P \
+.deps/gnu/java/lang/reflect/TypeSignature.P .deps/interpret.P \
 .deps/java/awt/AWTError.P .deps/java/awt/AWTEvent.P \
 .deps/java/awt/AWTException.P .deps/java/awt/ActiveEvent.P \
 .deps/java/awt/Adjustable.P .deps/java/awt/BorderLayout.P \
@@ -930,37 +1047,83 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/java/awt/event/WindowListener.P .deps/java/awt/geom/Dimension2D.P \
 .deps/java/awt/geom/Point2D.P .deps/java/awt/peer/ComponentPeer.P \
 .deps/java/awt/peer/ContainerPeer.P .deps/java/awt/peer/FramePeer.P \
-.deps/java/awt/peer/WindowPeer.P .deps/java/io/BufferedInputStream.P \
+.deps/java/awt/peer/WindowPeer.P .deps/java/beans/BeanDescriptor.P \
+.deps/java/beans/BeanInfo.P .deps/java/beans/Beans.P \
+.deps/java/beans/Customizer.P .deps/java/beans/DesignMode.P \
+.deps/java/beans/EventSetDescriptor.P \
+.deps/java/beans/FeatureDescriptor.P \
+.deps/java/beans/IndexedPropertyDescriptor.P \
+.deps/java/beans/IntrospectionException.P \
+.deps/java/beans/Introspector.P .deps/java/beans/MethodDescriptor.P \
+.deps/java/beans/ParameterDescriptor.P \
+.deps/java/beans/PropertyChangeEvent.P \
+.deps/java/beans/PropertyChangeListener.P \
+.deps/java/beans/PropertyChangeSupport.P \
+.deps/java/beans/PropertyDescriptor.P .deps/java/beans/PropertyEditor.P \
+.deps/java/beans/PropertyEditorManager.P \
+.deps/java/beans/PropertyEditorSupport.P \
+.deps/java/beans/PropertyVetoException.P \
+.deps/java/beans/SimpleBeanInfo.P \
+.deps/java/beans/VetoableChangeListener.P \
+.deps/java/beans/VetoableChangeSupport.P .deps/java/beans/Visibility.P \
+.deps/java/beans/beancontext/BeanContext.P \
+.deps/java/beans/beancontext/BeanContextChild.P \
+.deps/java/beans/beancontext/BeanContextChildComponentProxy.P \
+.deps/java/beans/beancontext/BeanContextChildSupport.P \
+.deps/java/beans/beancontext/BeanContextContainerProxy.P \
+.deps/java/beans/beancontext/BeanContextEvent.P \
+.deps/java/beans/beancontext/BeanContextMembershipEvent.P \
+.deps/java/beans/beancontext/BeanContextMembershipListener.P \
+.deps/java/beans/beancontext/BeanContextProxy.P \
+.deps/java/beans/beancontext/BeanContextServiceAvailableEvent.P \
+.deps/java/beans/beancontext/BeanContextServiceProvider.P \
+.deps/java/beans/beancontext/BeanContextServiceProviderBeanInfo.P \
+.deps/java/beans/beancontext/BeanContextServiceRevokedEvent.P \
+.deps/java/beans/beancontext/BeanContextServiceRevokedListener.P \
+.deps/java/beans/beancontext/BeanContextServices.P \
+.deps/java/beans/beancontext/BeanContextServicesListener.P \
+.deps/java/io/BlockDataException.P .deps/java/io/BufferedInputStream.P \
 .deps/java/io/BufferedOutputStream.P .deps/java/io/BufferedReader.P \
 .deps/java/io/BufferedWriter.P .deps/java/io/ByteArrayInputStream.P \
 .deps/java/io/ByteArrayOutputStream.P .deps/java/io/CharArrayReader.P \
 .deps/java/io/CharArrayWriter.P .deps/java/io/CharConversionException.P \
 .deps/java/io/DataInput.P .deps/java/io/DataInputStream.P \
 .deps/java/io/DataOutput.P .deps/java/io/DataOutputStream.P \
-.deps/java/io/EOFException.P .deps/java/io/File.P \
-.deps/java/io/FileDescriptor.P .deps/java/io/FileInputStream.P \
-.deps/java/io/FileNotFoundException.P .deps/java/io/FileOutputStream.P \
-.deps/java/io/FileReader.P .deps/java/io/FileWriter.P \
-.deps/java/io/FilenameFilter.P .deps/java/io/FilterInputStream.P \
-.deps/java/io/FilterOutputStream.P .deps/java/io/FilterReader.P \
-.deps/java/io/FilterWriter.P .deps/java/io/IOException.P \
-.deps/java/io/InputStream.P .deps/java/io/InputStreamReader.P \
+.deps/java/io/EOFException.P .deps/java/io/Externalizable.P \
+.deps/java/io/File.P .deps/java/io/FileDescriptor.P \
+.deps/java/io/FileInputStream.P .deps/java/io/FileNotFoundException.P \
+.deps/java/io/FileOutputStream.P .deps/java/io/FileReader.P \
+.deps/java/io/FileWriter.P .deps/java/io/FilenameFilter.P \
+.deps/java/io/FilterInputStream.P .deps/java/io/FilterOutputStream.P \
+.deps/java/io/FilterReader.P .deps/java/io/FilterWriter.P \
+.deps/java/io/IOException.P .deps/java/io/InputStream.P \
+.deps/java/io/InputStreamReader.P \
 .deps/java/io/InterruptedIOException.P \
+.deps/java/io/InvalidClassException.P \
+.deps/java/io/InvalidObjectException.P \
 .deps/java/io/LineNumberInputStream.P .deps/java/io/LineNumberReader.P \
-.deps/java/io/ObjectStreamException.P \
+.deps/java/io/NotActiveException.P \
+.deps/java/io/NotSerializableException.P .deps/java/io/ObjectInput.P \
+.deps/java/io/ObjectInputStream.P .deps/java/io/ObjectInputValidation.P \
+.deps/java/io/ObjectOutput.P .deps/java/io/ObjectOutputStream.P \
+.deps/java/io/ObjectStreamClass.P .deps/java/io/ObjectStreamConstants.P \
+.deps/java/io/ObjectStreamException.P .deps/java/io/ObjectStreamField.P \
 .deps/java/io/OptionalDataException.P .deps/java/io/OutputStream.P \
 .deps/java/io/OutputStreamWriter.P .deps/java/io/PipedInputStream.P \
 .deps/java/io/PipedOutputStream.P .deps/java/io/PipedReader.P \
 .deps/java/io/PipedWriter.P .deps/java/io/PrintStream.P \
 .deps/java/io/PrintWriter.P .deps/java/io/PushbackInputStream.P \
 .deps/java/io/PushbackReader.P .deps/java/io/RandomAccessFile.P \
-.deps/java/io/Reader.P .deps/java/io/SequenceInputStream.P \
-.deps/java/io/Serializable.P .deps/java/io/StreamCorruptedException.P \
+.deps/java/io/Reader.P .deps/java/io/Replaceable.P \
+.deps/java/io/Resolvable.P .deps/java/io/SequenceInputStream.P \
+.deps/java/io/Serializable.P .deps/java/io/SerializablePermission.P \
+.deps/java/io/StreamCorruptedException.P \
 .deps/java/io/StreamTokenizer.P .deps/java/io/StringBufferInputStream.P \
 .deps/java/io/StringReader.P .deps/java/io/StringWriter.P \
 .deps/java/io/SyncFailedException.P \
 .deps/java/io/UTFDataFormatException.P \
-.deps/java/io/UnsupportedEncodingException.P .deps/java/io/Writer.P \
+.deps/java/io/UnsupportedEncodingException.P \
+.deps/java/io/WriteAbortedException.P .deps/java/io/Writer.P \
 .deps/java/lang/AbstractMethodError.P \
 .deps/java/lang/ArithmeticException.P \
 .deps/java/lang/ArrayIndexOutOfBoundsException.P \
@@ -1054,8 +1217,11 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/java/net/UnknownHostException.P \
 .deps/java/net/UnknownServiceException.P \
 .deps/java/security/AlgorithmParameterGeneratorSpi.P \
+.deps/java/security/BasicPermission.P \
 .deps/java/security/DigestException.P \
+.deps/java/security/DigestOutputStream.P \
 .deps/java/security/GeneralSecurityException.P \
+.deps/java/security/Guard.P \
 .deps/java/security/InvalidAlgorithmParameterException.P \
 .deps/java/security/InvalidKeyException.P \
 .deps/java/security/InvalidParameterException.P \
@@ -1065,6 +1231,8 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/java/security/MessageDigest.P \
 .deps/java/security/NoSuchAlgorithmException.P \
 .deps/java/security/NoSuchProviderException.P \
+.deps/java/security/Permission.P \
+.deps/java/security/PermissionCollection.P \
 .deps/java/security/PrivateKey.P .deps/java/security/Provider.P \
 .deps/java/security/PublicKey.P .deps/java/security/SecureClassLoader.P \
 .deps/java/security/SecureRandom.P .deps/java/security/Security.P \
@@ -1102,7 +1270,9 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/java/text/MessageFormat.P .deps/java/text/NumberFormat.P \
 .deps/java/text/ParseException.P .deps/java/text/ParsePosition.P \
 .deps/java/text/RuleBasedCollator.P .deps/java/text/SimpleDateFormat.P \
-.deps/java/text/StringCharacterIterator.P .deps/java/util/BitSet.P \
+.deps/java/text/StringCharacterIterator.P \
+.deps/java/util/AbstractCollection.P .deps/java/util/AbstractList.P \
+.deps/java/util/Arrays.P .deps/java/util/BitSet.P \
 .deps/java/util/Calendar.P .deps/java/util/Collection.P \
 .deps/java/util/Comparator.P \
 .deps/java/util/ConcurrentModificationException.P \
@@ -1335,6 +1505,25 @@ gij$(EXEEXT): $(gij_OBJECTS) $(gij_DEPENDENCIES)
 gen-from-JIS$(EXEEXT): $(gen_from_JIS_OBJECTS) $(gen_from_JIS_DEPENDENCIES)
        @rm -f gen-from-JIS$(EXEEXT)
        $(LINK) $(gen_from_JIS_LDFLAGS) $(gen_from_JIS_OBJECTS) $(gen_from_JIS_LDADD) $(LIBS)
+
+install-binSCRIPTS: $(bin_SCRIPTS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(bindir)
+       @list='$(bin_SCRIPTS)'; for p in $$list; do \
+         if test -f $$p; then \
+           echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+           $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+         else if test -f $(srcdir)/$$p; then \
+           echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
+           $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+         else :; fi; fi; \
+       done
+
+uninstall-binSCRIPTS:
+       @$(NORMAL_UNINSTALL)
+       list='$(bin_SCRIPTS)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
+       done
 .cc.o:
        $(CXXCOMPILE) -c $<
 .cc.lo:
@@ -1593,7 +1782,7 @@ install-info-am:
 install-info: install-info-recursive
 install-exec-am: install-toolexeclibLIBRARIES \
                install-toolexeclibLTLIBRARIES install-binPROGRAMS \
-               install-toolexeclibDATA
+               install-binSCRIPTS install-toolexeclibDATA
 install-exec: install-exec-recursive
 
 install-data-am: install-dataDATA install-data-local
@@ -1604,9 +1793,11 @@ install-am: all-am
 install: install-recursive
 uninstall-am: uninstall-toolexeclibLIBRARIES \
                uninstall-toolexeclibLTLIBRARIES uninstall-binPROGRAMS \
-               uninstall-dataDATA uninstall-toolexeclibDATA
+               uninstall-binSCRIPTS uninstall-dataDATA \
+               uninstall-toolexeclibDATA
 uninstall: uninstall-recursive
-all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(DATA)
+all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) \
+               $(DATA)
 all-redirect: all-recursive
 install-strip:
        $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
@@ -1614,7 +1805,8 @@ installdirs: installdirs-recursive
 installdirs-am:
        $(mkinstalldirs)  $(DESTDIR)$(toolexeclibdir) \
                $(DESTDIR)$(toolexeclibdir) $(DESTDIR)$(bindir) \
-               $(DESTDIR)$(datadir) $(DESTDIR)$(toolexeclibdir)
+               $(DESTDIR)$(bindir) $(DESTDIR)$(datadir) \
+               $(DESTDIR)$(toolexeclibdir)
 
 
 mostlyclean-generic:
@@ -1680,7 +1872,8 @@ uninstall-toolexeclibLTLIBRARIES install-toolexeclibLTLIBRARIES \
 mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
 maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
 mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \
-clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS uninstall-dataDATA \
+clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \
+uninstall-binSCRIPTS install-binSCRIPTS uninstall-dataDATA \
 install-dataDATA uninstall-toolexeclibDATA install-toolexeclibDATA \
 install-data-recursive uninstall-data-recursive install-exec-recursive \
 uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
@@ -1805,6 +1998,14 @@ gnu/gcj/runtime/VMClassLoader.h: gnu/gcj/runtime/VMClassLoader.class libgcj.zip
            -friend 'java::lang::ClassLoader;' \
            $(basename $<)
 
+java/io/ObjectInputStream$$GetField.h: java/io/ObjectInputStream$$GetField.class libgcj.zip
+       $(GCJH) -classpath $(top_builddir) \
+       'java/io/ObjectInputStream$$GetField'
+
+java/io/ObjectOutputStream$$PutField.h: java/io/ObjectOutputStream$$PutField.class libgcj.zip
+       $(GCJH) -classpath $(top_builddir) \
+       'java/io/ObjectOutputStream$$PutField'
+
 install-data-local:
        $(PRE_INSTALL)
        @for f in $(nat_headers) $(extra_headers); do \
diff --git a/libjava/addr2name.awk b/libjava/addr2name.awk
new file mode 100755 (executable)
index 0000000..f31befd
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/awk -f
+
+# Copyright (C) 2000  Free Software Foundation
+
+#    This file is part of libgcj.
+
+# This software is copyrighted work licensed under the terms of the
+# Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+# details.
+
+# This script emulates a little of the functionality of addr2line for
+# those systems that don't have it.  The only command line argument is
+# an executable name.  The script reads hexadecimal addresses from
+# stdin and prints the corresponding symbol names to stdout.  The
+# addresses must begin with "0x" and be fully zero filled or this
+# won't work.
+
+BEGIN {
+  object = ARGV[1];
+  ARGV[1] = "";
+
+  while ("nm " object "| sort" | getline) {
+    if ($2 == "t" || $2 == "T") {
+      address[i] = "0x" $1; name[i] = $3;
+      i++;
+    }
+  }
+  syms = i;
+}
+
+{
+  lo = 0;
+  hi = syms - 1;
+
+  while ((hi-1) > lo)
+    {
+      try = int ((hi + lo) / 2);
+      if ($0 < address[try])
+       hi = try;
+      else if ($0 >= address[try])
+       lo = try;
+    }
+  print name[lo] "\n"; fflush();
+}
+
+    
index f28388d..a108f72 100755 (executable)
@@ -5118,24 +5118,33 @@ done
 test -n "$PERL" || PERL="false"
 
 
-if test "$enable_sjlj_exceptions" = yes; then
+SYSDEP_SOURCES=
+
+case "${host}" in
+ i?86-*-linux*)
+    SIGNAL_HANDLER=include/i386-signal.h
+    ;;
+ sparc-sun-solaris*)
+    SIGNAL_HANDLER=include/sparc-signal.h
+    ;;
+ ia64-*)
+    SYSDEP_SOURCES=sysdep/ia64.c
+    test -d sysdep || mkdir sysdep
+    ;;
+ *)
+    SIGNAL_HANDLER=include/default-signal.h
+    ;;
+esac
+
+# If we're using sjlj exceptions, forget what we just learned.
+if test "$libgcj_sjlj" = yes; then
    SIGNAL_HANDLER=include/default-signal.h
-else
-   case "${host}" in
-    i?86-*-linux*)
-       SIGNAL_HANDLER=include/i386-signal.h
-       ;;
-    sparc-sun-solaris*)
-       SIGNAL_HANDLER=include/sparc-signal.h
-       ;;
-    *)
-       SIGNAL_HANDLER=include/default-signal.h
-       ;;
-   esac
 fi
 
 
 
+
+
 if test "${multilib}" = "yes"; then
   multilib_arg="--enable-multilib"
 else
@@ -5367,6 +5376,7 @@ s%@EH_COMMON_INCLUDE@%$EH_COMMON_INCLUDE%g
 s%@AM_RUNTESTFLAGS@%$AM_RUNTESTFLAGS%g
 s%@ALLOCA@%$ALLOCA%g
 s%@PERL@%$PERL%g
+s%@SYSDEP_SOURCES@%$SYSDEP_SOURCES%g
 s%@here@%$here%g
 
 CEOF
index 38d927d..39a41bb 100644 (file)
@@ -66,6 +66,11 @@ case "${host}" in
        ;;
   sparc-*)
         ;;
+  ia64-*)
+        libgcj_flags="${libgcj_flags} -funwind-tables"
+       libgcj_sjlj=yes
+       libgcj_interpreter=yes
+       ;;
   *)
         libgcj_sjlj=yes
        ;;
index 8c4be25..5fefe1f 100644 (file)
@@ -733,22 +733,31 @@ AC_FUNC_ALLOCA
 
 AC_CHECK_PROGS(PERL, perl, false)
 
-if test "$enable_sjlj_exceptions" = yes; then
+SYSDEP_SOURCES=
+
+case "${host}" in
+ i?86-*-linux*)
+    SIGNAL_HANDLER=include/i386-signal.h
+    ;;
+ sparc-sun-solaris*)
+    SIGNAL_HANDLER=include/sparc-signal.h
+    ;;
+ ia64-*)
+    SYSDEP_SOURCES=sysdep/ia64.c
+    test -d sysdep || mkdir sysdep
+    ;;
+ *)
+    SIGNAL_HANDLER=include/default-signal.h
+    ;;
+esac
+
+# If we're using sjlj exceptions, forget what we just learned.
+if test "$libgcj_sjlj" = yes; then
    SIGNAL_HANDLER=include/default-signal.h
-else
-   case "${host}" in
-    i?86-*-linux*)
-       SIGNAL_HANDLER=include/i386-signal.h
-       ;;
-    sparc-sun-solaris*)
-       SIGNAL_HANDLER=include/sparc-signal.h
-       ;;
-    *)
-       SIGNAL_HANDLER=include/default-signal.h
-       ;;
-   esac
 fi
 
+AC_SUBST(SYSDEP_SOURCES)
+
 AC_LINK_FILES($SIGNAL_HANDLER, include/java-signal.h)
 
 if test "${multilib}" = "yes"; then
index 830733c..26fec33 100644 (file)
@@ -99,6 +99,7 @@ OBJDUMP = @OBJDUMP@
 PACKAGE = @PACKAGE@
 PERL = @PERL@
 RANLIB = @RANLIB@
+SYSDEP_SOURCES = @SYSDEP_SOURCES@
 SYSTEMSPEC = @SYSTEMSPEC@
 THREADDEPS = @THREADDEPS@
 THREADINCS = @THREADINCS@
index 3e7d2e2..9ef52dc 100644 (file)
@@ -69,8 +69,24 @@ extern "Java"
       class InputStream;
       class InputStreamReader;
       class InterruptedIOException;
+      class InvalidClassException;
+      class InvalidObjectException;
       class LineNumberInputStream;
       class LineNumberReader;
+      class NotActiveException;
+      class NotSerializableException;
+      class ObjectInput;
+      class ObjectInputStream;
+      class ObjectInputStream$GetField;
+      class ObjectInputValidation;
+      class ObjectOutput;
+      class ObjectOutputStream;
+      class ObjectOutputStream$PutField;
+      class ObjectStreamClass;
+      class ObjectStreamConstants;
+      class ObjectStreamException;
+      class ObjectStreamField;
+      class OptionalDataException;
       class OutputStream;
       class OutputStreamWriter;
       class PipedInputStream;
@@ -85,6 +101,9 @@ extern "Java"
       class Reader;
       class SequenceInputStream;
       class Serializable;
+      class SerializablePermission;
+      class SimpleDigestStream;
+      class StreamCorruptedException;
       class StreamTokenizer;
       class StringBufferInputStream;
       class StringReader;
diff --git a/libjava/gnu/gcj/io/SimpleSHSStream.java b/libjava/gnu/gcj/io/SimpleSHSStream.java
new file mode 100644 (file)
index 0000000..bcf8ea5
--- /dev/null
@@ -0,0 +1,66 @@
+// SimpleSHSStream.java
+
+/* Copyright (C) 2000  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+package gnu.gcj.io;
+import java.io.Serializable;
+import java.io.*;
+import java.lang.reflect.*;
+
+public class SimpleSHSStream extends java.io.DataOutputStream
+{
+  int counter;
+  final int SHS_BLOCKSIZE = 64;
+  final int SHS_DIGESTSIZE = 20;
+
+  byte buf[];
+  byte shs_info[];
+
+  native static byte [] shsFinal (byte info[]);
+  native static void shsUpdate (byte info[], byte buf[], int count);
+  native static byte [] shsInit ();
+
+  private void update (byte b)
+  {
+    buf [counter++] = b;
+    if (counter % SHS_BLOCKSIZE == 0)
+      {
+       counter = 0;
+       shsUpdate (shs_info, buf, SHS_BLOCKSIZE);
+      }
+  }    
+  
+  public void write (int b) throws IOException
+  {
+    update ((byte)b);
+    super.write (b);
+  }
+
+  public void write (byte[] b, int off, int len) throws IOException
+  {
+    for (int i = 0; i < len; i++)
+      write (b[i+off]);
+  }
+
+  public byte[] digest()
+  {
+    shsUpdate (shs_info, buf, counter);
+    return shsFinal (shs_info);
+  }
+
+  public SimpleSHSStream (OutputStream out)
+  {
+    super (out);
+    buf = new byte[SHS_BLOCKSIZE];
+    shs_info = shsInit ();
+    counter = 0;
+  }
+}
+
diff --git a/libjava/gnu/gcj/io/natSimpleSHSStream.cc b/libjava/gnu/gcj/io/natSimpleSHSStream.cc
new file mode 100644 (file)
index 0000000..2cd213b
--- /dev/null
@@ -0,0 +1,55 @@
+// natSimpleSHSStream.cc
+
+/* Copyright (C) 2000  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <gnu/gcj/io/SimpleSHSStream.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#define PROTO
+#include "shs.h"
+
+
+jbyteArray 
+gnu::gcj::io::SimpleSHSStream::shsFinal (jbyteArray shs_info)
+{
+  SHS_INFO *info = (SHS_INFO *)elements(shs_info);
+  ::shsFinal (info);
+
+  jbyteArray buffer = JvNewByteArray (SHS_DIGESTSIZE);
+  memcpy (elements (buffer), (jbyte *)&info->digest, SHS_DIGESTSIZE);
+  return buffer;
+}
+    
+void 
+gnu::gcj::io::SimpleSHSStream::shsUpdate (jbyteArray shs_info, jbyteArray buf, jint count)
+{
+  SHS_INFO *info = (SHS_INFO *)elements(shs_info);
+  BYTE *buffer = (BYTE *)elements(buf);
+  
+  ::shsUpdate (info, buffer, count);
+}
+
+jbyteArray 
+gnu::gcj::io::SimpleSHSStream::shsInit ()
+{
+  jbyteArray result = JvNewByteArray (sizeof (SHS_INFO));
+  SHS_INFO *info = (SHS_INFO *)elements(result);
+
+  ::shsInit (info);
+  return result;
+}
+
+
diff --git a/libjava/gnu/gcj/io/shs.cc b/libjava/gnu/gcj/io/shs.cc
new file mode 100644 (file)
index 0000000..96b4f56
--- /dev/null
@@ -0,0 +1,280 @@
+
+/* --------------------------------- SHS.CC ------------------------------- */
+
+/*
+ * NIST proposed Secure Hash Standard.
+ *
+ * Written 2 September 1992, Peter C. Gutmann.
+ * This implementation placed in the public domain.
+ *
+ * Comments to pgut1@cs.aukuni.ac.nz
+ */
+
+#include <string.h>
+#include "shs.h"
+
+/* The SHS f()-functions */
+
+#define f1(x,y,z)   ( ( x & y ) | ( ~x & z ) )           /* Rounds  0-19 */
+#define f2(x,y,z)   ( x ^ y ^ z )                        /* Rounds 20-39 */
+#define f3(x,y,z)   ( ( x & y ) | ( x & z ) | ( y & z ) ) /* Rounds 40-59 */
+#define f4(x,y,z)   ( x ^ y ^ z )                        /* Rounds 60-79 */
+
+/* The SHS Mysterious Constants */
+
+#define K1  0x5A827999L        /* Rounds  0-19 */
+#define K2  0x6ED9EBA1L        /* Rounds 20-39 */
+#define K3  0x8F1BBCDCL        /* Rounds 40-59 */
+#define K4  0xCA62C1D6L        /* Rounds 60-79 */
+
+/* SHS initial values */
+
+#define h0init 0x67452301L
+#define h1init 0xEFCDAB89L
+#define h2init 0x98BADCFEL
+#define h3init 0x10325476L
+#define h4init 0xC3D2E1F0L
+
+/* 32-bit rotate - kludged with shifts */
+
+#define S(n,X) ((X << n) | (X >> (32 - n)))
+
+/* The initial expanding function */
+
+#define expand(count)  W [count] = W [count - 3] ^ W [count - 8] ^ W [count - 14] ^ W [count - 16]
+
+/* The four SHS sub-rounds */
+
+#define subRound1(count)    \
+       { \
+               temp = S (5, A) + f1 (B, C, D) + E + W [count] + K1; \
+               E = D; \
+               D = C; \
+               C = S (30, B); \
+               B = A; \
+               A = temp; \
+       }
+
+#define subRound2(count)    \
+       { \
+               temp = S (5, A) + f2 (B, C, D) + E + W [count] + K2; \
+               E = D; \
+               D = C; \
+               C = S (30, B); \
+               B = A; \
+               A = temp; \
+       }
+
+#define subRound3(count)    \
+       { \
+               temp = S (5, A) + f3 (B, C, D) + E + W [count] + K3; \
+               E = D; \
+               D = C; \
+               C = S (30, B); \
+               B = A; \
+               A = temp; \
+       }
+
+#define subRound4(count)    \
+       { \
+               temp = S (5, A) + f4 (B, C, D) + E + W [count] + K4; \
+               E = D; \
+               D = C; \
+               C = S (30, B); \
+               B = A; \
+               A = temp; \
+       }
+
+/* The two buffers of 5 32-bit words */
+
+LONG h0, h1, h2, h3, h4;
+LONG A, B, C, D, E;
+
+local void byteReverse OF((LONG *buffer, int byteCount));
+void shsTransform OF((SHS_INFO *shsInfo));
+
+/* Initialize the SHS values */
+
+void shsInit (SHS_INFO *shsInfo)
+{
+       /* Set the h-vars to their initial values */
+       shsInfo->digest [0] = h0init;
+       shsInfo->digest [1] = h1init;
+       shsInfo->digest [2] = h2init;
+       shsInfo->digest [3] = h3init;
+       shsInfo->digest [4] = h4init;
+
+       /* Initialise bit count */
+       shsInfo->countLo = shsInfo->countHi = 0L;
+}
+
+/*
+ * Perform the SHS transformation.  Note that this code, like MD5, seems to
+ * break some optimizing compilers - it may be necessary to split it into
+ * sections, eg based on the four subrounds
+ */
+
+void shsTransform (SHS_INFO *shsInfo)
+{
+       LONG W [80], temp;
+       int i;
+
+       /* Step A.      Copy the data buffer into the local work buffer */
+       for (i = 0; i < 16; i++)
+               W [i] = shsInfo->data [i];
+
+       /* Step B.      Expand the 16 words into 64 temporary data words */
+       expand (16); expand (17); expand (18); expand (19); expand (20);
+       expand (21); expand (22); expand (23); expand (24); expand (25);
+       expand (26); expand (27); expand (28); expand (29); expand (30);
+       expand (31); expand (32); expand (33); expand (34); expand (35);
+       expand (36); expand (37); expand (38); expand (39); expand (40);
+       expand (41); expand (42); expand (43); expand (44); expand (45);
+       expand (46); expand (47); expand (48); expand (49); expand (50);
+       expand (51); expand (52); expand (53); expand (54); expand (55);
+       expand (56); expand (57); expand (58); expand (59); expand (60);
+       expand (61); expand (62); expand (63); expand (64); expand (65);
+       expand (66); expand (67); expand (68); expand (69); expand (70);
+       expand (71); expand (72); expand (73); expand (74); expand (75);
+       expand (76); expand (77); expand (78); expand (79);
+
+       /* Step C.      Set up first buffer */
+       A = shsInfo->digest [0];
+       B = shsInfo->digest [1];
+       C = shsInfo->digest [2];
+       D = shsInfo->digest [3];
+       E = shsInfo->digest [4];
+
+       /* Step D.      Serious mangling, divided into four sub-rounds */
+       subRound1  (0); subRound1  (1); subRound1  (2); subRound1  (3);
+       subRound1  (4); subRound1  (5); subRound1  (6); subRound1  (7);
+       subRound1  (8); subRound1  (9); subRound1 (10); subRound1 (11);
+       subRound1 (12); subRound1 (13); subRound1 (14); subRound1 (15);
+       subRound1 (16); subRound1 (17); subRound1 (18); subRound1 (19);
+
+       subRound2 (20); subRound2 (21); subRound2 (22); subRound2 (23);
+       subRound2 (24); subRound2 (25); subRound2 (26); subRound2 (27);
+       subRound2 (28); subRound2 (29); subRound2 (30); subRound2 (31);
+       subRound2 (32); subRound2 (33); subRound2 (34); subRound2 (35);
+       subRound2 (36); subRound2 (37); subRound2 (38); subRound2 (39);
+
+       subRound3 (40); subRound3 (41); subRound3 (42); subRound3 (43);
+       subRound3 (44); subRound3 (45); subRound3 (46); subRound3 (47);
+       subRound3 (48); subRound3 (49); subRound3 (50); subRound3 (51);
+       subRound3 (52); subRound3 (53); subRound3 (54); subRound3 (55);
+       subRound3 (56); subRound3 (57); subRound3 (58); subRound3 (59);
+
+       subRound4 (60); subRound4 (61); subRound4 (62); subRound4 (63);
+       subRound4 (64); subRound4 (65); subRound4 (66); subRound4 (67);
+       subRound4 (68); subRound4 (69); subRound4 (70); subRound4 (71);
+       subRound4 (72); subRound4 (73); subRound4 (74); subRound4 (75);
+       subRound4 (76); subRound4 (77); subRound4 (78); subRound4 (79);
+
+       /* Step E.      Build message digest */
+       shsInfo->digest [0] += A;
+       shsInfo->digest [1] += B;
+       shsInfo->digest [2] += C;
+       shsInfo->digest [3] += D;
+       shsInfo->digest [4] += E;
+}
+
+local void byteReverse (LONG *buffer, int byteCount)
+{
+       LONG value;
+       int count;
+
+       /*
+        * Find out what the byte order is on this machine.
+        * Big endian is for machines that place the most significant byte
+        * first (eg. Sun SPARC). Little endian is for machines that place
+        * the least significant byte first (eg. VAX).
+        *
+        * We figure out the byte order by stuffing a 2 byte string into a
+        * short and examining the left byte. '@' = 0x40  and  'P' = 0x50
+        * If the left byte is the 'high' byte, then it is 'big endian'.
+        * If the left byte is the 'low' byte, then the machine is 'little
+        * endian'.
+        *
+        *                          -- Shawn A. Clifford (sac@eng.ufl.edu)
+        */
+
+       /*
+        * Several bugs fixed       -- Pat Myrto (pat@rwing.uucp)
+        */
+
+       if ((*(unsigned short *) ("@P") >> 8) == '@')
+               return;
+
+       byteCount /= sizeof (LONG);
+       for (count = 0; count < byteCount; count++) {
+               value = (buffer [count] << 16) | (buffer [count] >> 16);
+               buffer [count] = ((value & 0xFF00FF00L) >> 8) | ((value & 0x00FF00FFL) << 8);
+       }
+}
+
+/*
+ * Update SHS for a block of data.  This code assumes that the buffer size is
+ * a multiple of SHS_BLOCKSIZE bytes long, which makes the code a lot more
+ * efficient since it does away with the need to handle partial blocks
+ * between calls to shsUpdate()
+ */
+
+void shsUpdate (SHS_INFO *shsInfo, BYTE *buffer, int count)
+{
+       /* Update bitcount */
+       if ((shsInfo->countLo + ((LONG) count << 3)) < shsInfo->countLo)
+                shsInfo->countHi++;    /* Carry from low to high bitCount */
+       shsInfo->countLo += ((LONG) count << 3);
+       shsInfo->countHi += ((LONG) count >> 29);
+
+       /* Process data in SHS_BLOCKSIZE chunks */
+       while (count >= SHS_BLOCKSIZE) {
+               memcpy (shsInfo->data, buffer, SHS_BLOCKSIZE);
+               byteReverse (shsInfo->data, SHS_BLOCKSIZE);
+               shsTransform (shsInfo);
+               buffer += SHS_BLOCKSIZE;
+               count -= SHS_BLOCKSIZE;
+       }
+
+       /*
+        * Handle any remaining bytes of data.
+        * This should only happen once on the final lot of data
+        */
+       memcpy (shsInfo->data, buffer, count);
+}
+
+void shsFinal (SHS_INFO *shsInfo)
+{
+       int count;
+       LONG lowBitcount = shsInfo->countLo, highBitcount = shsInfo->countHi;
+
+       /* Compute number of bytes mod 64 */
+       count = (int) ((shsInfo->countLo >> 3) & 0x3F);
+
+       /*
+        * Set the first char of padding to 0x80.
+        * This is safe since there is always at least one byte free
+        */
+       ((BYTE *) shsInfo->data) [count++] = 0x80;
+
+       /* Pad out to 56 mod 64 */
+       if (count > 56) {
+               /* Two lots of padding:  Pad the first block to 64 bytes */
+               memset ((BYTE *) shsInfo->data + count, 0, 64 - count);
+               byteReverse (shsInfo->data, SHS_BLOCKSIZE);
+               shsTransform (shsInfo);
+
+               /* Now fill the next block with 56 bytes */
+               memset (shsInfo->data, 0, 56);
+       } else
+               /* Pad block to 56 bytes */
+               memset ((BYTE *) shsInfo->data + count, 0, 56 - count);
+       byteReverse (shsInfo->data, SHS_BLOCKSIZE);
+
+       /* Append length in bits and transform */
+       shsInfo->data [14] = highBitcount;
+       shsInfo->data [15] = lowBitcount;
+
+       shsTransform (shsInfo);
+       byteReverse (shsInfo->data, SHS_DIGESTSIZE);
+}
diff --git a/libjava/gnu/gcj/io/shs.h b/libjava/gnu/gcj/io/shs.h
new file mode 100644 (file)
index 0000000..8c91ff3
--- /dev/null
@@ -0,0 +1,51 @@
+/* --------------------------------- SHS.H ------------------------------- */
+
+/*
+ * NIST proposed Secure Hash Standard. 
+ *
+ * Written 2 September 1992, Peter C. Gutmann.
+ * This implementation placed in the public domain. 
+ *
+ * Comments to pgut1@cs.aukuni.ac.nz 
+ */
+
+/* Useful defines/typedefs */
+
+#ifndef SHS_H
+#define SHS_H
+
+typedef unsigned char BYTE;
+typedef unsigned int LONG; /* A 32-bit type */
+
+/* The SHS block size and message digest sizes, in bytes */
+
+#define SHS_BLOCKSIZE  64
+#define SHS_DIGESTSIZE 20
+
+/* The structure for storing SHS info */
+
+typedef struct {
+       LONG digest [5];        /* Message digest */
+       LONG countLo, countHi;  /* 64-bit bit count */
+       LONG data [16];         /* SHS data buffer */
+} SHS_INFO;
+
+/* Turn off prototypes if requested */
+#if (defined(NOPROTO) && defined(PROTO))
+#      undef PROTO
+#endif
+
+/* Used to remove arguments in function prototypes for non-ANSI C */
+#ifdef PROTO
+#      define OF(a) a
+#else  /* !PROTO */
+#      define OF(a) ()
+#endif /* ?PROTO */
+
+#define        local   static
+
+void shsInit OF((SHS_INFO *shsInfo));
+void shsUpdate OF((SHS_INFO *shsInfo, BYTE *buffer, int count));
+void shsFinal OF((SHS_INFO *shsInfo));
+
+#endif
diff --git a/libjava/gnu/java/beans/BeanInfoEmbryo.java b/libjava/gnu/java/beans/BeanInfoEmbryo.java
new file mode 100644 (file)
index 0000000..85aafa1
--- /dev/null
@@ -0,0 +1,146 @@
+/* gnu.java.beans.BeanInfoEmbryo
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans;
+
+import java.beans.*;
+import java.util.*;
+import gnu.java.lang.*;
+import java.lang.reflect.*;
+
+/**
+ ** A BeanInfoEmbryo accumulates information about a Bean
+ ** while it is in the process of being created, and then
+ ** when you are done accumulating the information, the
+ ** getBeanInfo() method may be called to create a BeanInfo
+ ** object based on the information.<P>
+ **
+ ** This class is not well-synchronized.  (It can be, it
+ ** just isn't yet.)
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 30 Jul 1998
+ ** @see java.beans.BeanInfo
+ **/
+
+public class BeanInfoEmbryo {
+       Hashtable properties = new Hashtable();
+       Hashtable events = new Hashtable();
+       Vector methods = new Vector();
+
+       BeanDescriptor beanDescriptor;
+       BeanInfo[] additionalBeanInfo;
+       java.awt.Image[] im;
+       String defaultPropertyName;
+       String defaultEventName;
+
+       public BeanInfoEmbryo() {
+       }
+
+       public BeanInfo getBeanInfo() {
+               int defaultProperty = -1;
+               int defaultEvent = -1;
+
+               PropertyDescriptor[] Aproperties = new PropertyDescriptor[properties.size()];
+               int i = 0;
+               Enumeration enum = properties.elements();
+               while(enum.hasMoreElements()) {
+                       Aproperties[i] = (PropertyDescriptor)enum.nextElement();
+                       if(defaultPropertyName != null && Aproperties[i].getName().equals(defaultPropertyName)) {
+                               defaultProperty = i;
+                       }
+                       i++;
+               }
+
+               EventSetDescriptor[] Aevents = new EventSetDescriptor[events.size()];
+               i = 0;
+               enum = events.elements();
+               while(enum.hasMoreElements()) {
+                       Aevents[i] = (EventSetDescriptor)enum.nextElement();
+                       if(defaultEventName != null && Aevents[i].getName().equals(defaultEventName)) {
+                               defaultEvent = i;
+                       }
+                       i++;
+               }
+
+               MethodDescriptor[] Amethods = new MethodDescriptor[methods.size()];
+               methods.copyInto(Amethods);
+
+               return new ExplicitBeanInfo(beanDescriptor,additionalBeanInfo,Aproperties,defaultProperty,Aevents,defaultEvent,Amethods,im);
+       }
+
+       public void setBeanDescriptor(BeanDescriptor b) {
+               beanDescriptor = b;
+       }
+
+       public void setAdditionalBeanInfo(BeanInfo[] b) {
+               additionalBeanInfo = b;
+       }
+
+       public boolean hasProperty(PropertyDescriptor p) {
+               return properties.get(p.getName()) != null;
+       }
+       public void addProperty(PropertyDescriptor p) {
+               properties.put(p.getName(),p);
+       }
+       public void addIndexedProperty(IndexedPropertyDescriptor p) {
+               properties.put(p.getName(),p);
+       }
+
+       public boolean hasEvent(EventSetDescriptor e) {
+               return events.get(e.getName()) != null;
+       }
+       public void addEvent(EventSetDescriptor e) {
+               events.put(e.getName(),e);
+       }
+
+       public boolean hasMethod(MethodDescriptor m) {
+               for(int i=0;i<methods.size();i++) {
+                       Method thisMethod = ((MethodDescriptor)methods.elementAt(i)).getMethod();
+                       if(m.getMethod().getName().equals(thisMethod.getName())
+                          && ArrayHelper.equalsArray(m.getMethod().getParameterTypes(), thisMethod.getParameterTypes())) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+       public void addMethod(MethodDescriptor m) {
+               methods.addElement(m);
+       }
+
+       public void setDefaultPropertyName(String defaultPropertyName) {
+               this.defaultPropertyName = defaultPropertyName;
+       }
+
+       public void setDefaultEventName(String defaultEventName) {
+               this.defaultEventName = defaultEventName;
+       }
+
+       public void setIcons(java.awt.Image[] im) {
+               this.im = im;
+       }
+}
diff --git a/libjava/gnu/java/beans/EmptyBeanInfo.java b/libjava/gnu/java/beans/EmptyBeanInfo.java
new file mode 100644 (file)
index 0000000..ad7d91d
--- /dev/null
@@ -0,0 +1,59 @@
+/* gnu.java.beans.EmptyBeanInfo
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans;
+
+import java.beans.*;
+
+/**
+ ** EmptyBeanInfo is a BeanInfo that discloses no
+ ** information about the Bean and does not allow
+ ** Introspection.  The Introspector uses instances of this
+ ** class to create empty BeanInfos, but it could also be
+ ** used as a base class for BeanInfos that do not allow
+ ** Introspection and provide only a little bit of
+ ** information.<P>
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 30 Jul 1998
+ ** @see gnu.java.beans.ExplicitBeanInfo
+ ** @see java.beans.BeanInfo
+ **/
+
+public class EmptyBeanInfo extends ExplicitBeanInfo {
+       /** Create a new EmptyBeanInfo. **/
+       public EmptyBeanInfo(Class beanClass) {
+               super(new BeanDescriptor(beanClass,null),
+                     new BeanInfo[0],
+                     new PropertyDescriptor[0],
+                     -1,
+                     new EventSetDescriptor[0],
+                     -1,
+                     new MethodDescriptor[0],
+                     null);
+       }
+}
diff --git a/libjava/gnu/java/beans/ExplicitBeanInfo.java b/libjava/gnu/java/beans/ExplicitBeanInfo.java
new file mode 100644 (file)
index 0000000..8cab94b
--- /dev/null
@@ -0,0 +1,133 @@
+/* gnu.java.beans.ExplicitBeanInfo
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans;
+
+import java.beans.*;
+
+/**
+ ** ExplicitBeanInfo lets you specify in the constructor
+ ** all the various parts of the BeanInfo.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 30 Jul 1998
+ ** @see java.beans.BeanInfo
+ **/
+
+public class ExplicitBeanInfo implements BeanInfo {
+       /** The BeanDescriptor returned by getBeanDescriptor. **/
+       protected BeanDescriptor beanDescriptor;
+
+       /** The EventSetDescriptor array returned by
+        ** getEventSetDescriptors().
+        **/
+       protected EventSetDescriptor[] eventSetDescriptors = new EventSetDescriptor[0];
+
+       /** The PropertyDescriptor array returned by
+        ** getPropertyDescriptors().
+        **/
+       protected PropertyDescriptor[] propertyDescriptors = new PropertyDescriptor[0];
+
+       /** The MethodDescriptor array returned by
+        ** getMethodDescriptors().
+        **/
+       protected MethodDescriptor[]   methodDescriptors;
+
+       /** The default property index. **/
+       protected int defaultPropertyIndex;
+
+       /** The default event index. **/
+       protected int defaultEventIndex;
+
+       /** The BeanInfo array returned by
+        ** getAdditionalBeanInfo().
+        **/
+       protected BeanInfo[] additionalBeanInfo;
+
+       /** The set of icons. **/
+       protected java.awt.Image[] icons;
+
+       public ExplicitBeanInfo(BeanDescriptor beanDescriptor,
+                               BeanInfo[] additionalBeanInfo,
+                               PropertyDescriptor[] propertyDescriptors,
+                               int defaultPropertyIndex,
+                               EventSetDescriptor[] eventSetDescriptors,
+                               int defaultEventIndex,
+                               MethodDescriptor[] methodDescriptors,
+                               java.awt.Image[] icons) {
+               this.beanDescriptor = beanDescriptor;
+               this.additionalBeanInfo = additionalBeanInfo;
+               this.propertyDescriptors = propertyDescriptors;
+               this.defaultPropertyIndex = defaultPropertyIndex;
+               this.eventSetDescriptors = eventSetDescriptors;
+               this.defaultEventIndex = defaultEventIndex;
+               this.methodDescriptors = methodDescriptors;
+               this.icons = icons;
+       }
+
+       /** Get Bean descriptor. **/
+       public BeanDescriptor getBeanDescriptor() {
+               return beanDescriptor;
+       }
+
+       /** Get Bean events. **/
+       public EventSetDescriptor[] getEventSetDescriptors() {
+               return eventSetDescriptors;
+       }
+
+       /** Get default event set. **/
+       public int getDefaultEventIndex() {
+               return defaultEventIndex;
+       }
+
+       /** Get Bean properties. **/
+       public PropertyDescriptor[] getPropertyDescriptors() {
+               return propertyDescriptors;
+       }
+
+       /** Get "default" property. **/
+       public int getDefaultPropertyIndex() {
+               return defaultPropertyIndex;
+       }
+
+       /** Get Bean methods. **/
+       public MethodDescriptor[] getMethodDescriptors() {
+               return methodDescriptors;
+       }
+
+       /** Get additional Bean info. **/
+       public BeanInfo[] getAdditionalBeanInfo() {
+               return additionalBeanInfo;
+       }
+
+       /** Get Bean icons.
+        ** @param iconType the type of icon
+        **/
+       public java.awt.Image getIcon(int iconType) {
+               return icons != null ? icons[iconType] : null;
+       }
+}
diff --git a/libjava/gnu/java/beans/IntrospectionIncubator.java b/libjava/gnu/java/beans/IntrospectionIncubator.java
new file mode 100644 (file)
index 0000000..e3f4807
--- /dev/null
@@ -0,0 +1,344 @@
+/* gnu.java.beans.IntrospectionIncubator
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans;
+
+import java.beans.*;
+import java.util.*;
+import java.lang.reflect.*;
+import gnu.java.lang.*;
+
+/**
+ ** IntrospectionIncubator takes in a bunch of Methods, and
+ ** Introspects only those Methods you give it.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 30 Jul 1998
+ ** @see gnu.java.beans.ExplicitBeanInfo
+ ** @see java.beans.BeanInfo
+ **/
+
+public class IntrospectionIncubator {
+       Hashtable propertyMethods = new Hashtable();
+       Hashtable listenerMethods = new Hashtable();
+       Vector otherMethods = new Vector();
+
+       Class propertyStopClass;
+       Class eventStopClass;
+       Class methodStopClass;
+
+       public IntrospectionIncubator() {
+       }
+
+       /* Paving the way for automatic Introspection */
+       public void addMethod(Method method) {
+               if(Modifier.isPublic(method.getModifiers()) && !Modifier.isStatic(method.getModifiers())) {
+                       String name = ClassHelper.getTruncatedName(method.getName());
+                       Class retType = method.getReturnType();
+                       Class[] params = method.getParameterTypes();
+                       boolean isVoid = retType.equals(java.lang.Void.TYPE);
+                       Class methodClass = method.getDeclaringClass();
+                       if(propertyStopClass == null || (propertyStopClass.isAssignableFrom(methodClass) && !propertyStopClass.equals(methodClass))) {
+                               if(name.startsWith("is")
+                                  && retType.equals(java.lang.Boolean.TYPE)
+                                  && params.length == 0) {
+                                       addToPropertyHash(name,method,IS);
+                               } else if(name.startsWith("get") && !isVoid) {
+                                       if(params.length == 0) {
+                                               addToPropertyHash(name,method,GET);
+                                       } else if(params.length == 1 && params[0].equals(java.lang.Integer.TYPE)) {
+                                               addToPropertyHash(name,method,GET_I);
+                                       } else {
+                                               otherMethods.addElement(method);
+                                       }
+                               } else if(name.startsWith("set") && isVoid) {
+                                       if(params.length == 1) {
+                                               addToPropertyHash(name,method,SET);
+                                       } else if(params.length == 2 && params[0].equals(java.lang.Integer.TYPE)) {
+                                               addToPropertyHash(name,method,SET_I);
+                                       } else {
+                                               otherMethods.addElement(method);
+                                       }
+                               }
+                       }
+                       if(eventStopClass == null || (eventStopClass.isAssignableFrom(methodClass) && !eventStopClass.equals(methodClass))) {
+                               if(name.startsWith("add")
+                                         && isVoid
+                                         && params.length == 1
+                                         && java.util.EventListener.class.isAssignableFrom(params[0])) {
+                                       addToListenerHash(name,method,ADD);
+                               } else if(name.startsWith("remove")
+                                         && isVoid
+                                         && params.length == 1
+                                         && java.util.EventListener.class.isAssignableFrom(params[0])) {
+                                       addToListenerHash(name,method,REMOVE);
+                               }
+                       }
+                       if(methodStopClass == null || (methodStopClass.isAssignableFrom(methodClass) && !methodStopClass.equals(methodClass))) {
+                               otherMethods.addElement(method);
+                       }
+               }
+       }
+
+       public void addMethods(Method[] m) {
+               for(int i=0;i<m.length;i++) {
+                       addMethod(m[i]);
+               }
+       }
+
+       public void setPropertyStopClass(Class c) {
+               propertyStopClass = c;
+       }
+
+       public void setEventStopClass(Class c) {
+               eventStopClass = c;
+       }
+
+       public void setMethodStopClass(Class c) {
+               methodStopClass = c;
+       }
+
+
+       public BeanInfoEmbryo getBeanInfoEmbryo() throws IntrospectionException {
+               BeanInfoEmbryo b = new BeanInfoEmbryo();
+               findXXX(b,IS);
+               findXXXInt(b,GET_I);
+               findXXXInt(b,SET_I);
+               findXXX(b,GET);
+               findXXX(b,SET);
+               findAddRemovePairs(b);
+               for(int i=0;i<otherMethods.size();i++) {
+                       MethodDescriptor newMethod = new MethodDescriptor((Method)otherMethods.elementAt(i));
+                       if(!b.hasMethod(newMethod)) {
+                               b.addMethod(new MethodDescriptor((Method)otherMethods.elementAt(i)));
+                       }
+               }
+               return b;
+       }
+
+       public BeanInfo getBeanInfo() throws IntrospectionException {
+               return getBeanInfoEmbryo().getBeanInfo();
+       }
+
+
+       void findAddRemovePairs(BeanInfoEmbryo b) throws IntrospectionException {
+               Enumeration listenerEnum = listenerMethods.keys();
+               while(listenerEnum.hasMoreElements()) {
+                       DoubleKey k = (DoubleKey)listenerEnum.nextElement();
+                       Method[] m = (Method[])listenerMethods.get(k);
+                       if(m[ADD] != null && m[REMOVE] != null) {
+                               EventSetDescriptor e = new EventSetDescriptor(Introspector.decapitalize(k.getName()),
+                                                                             k.getType(), k.getType().getMethods(),
+                                                                             m[ADD],m[REMOVE]);
+                               e.setUnicast(ArrayHelper.contains(m[ADD].getExceptionTypes(),java.util.TooManyListenersException.class));
+                               if(!b.hasEvent(e)) {
+                                       b.addEvent(e);
+                               }
+                       }
+               }
+       }
+
+       void findXXX(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
+               Enumeration keys = propertyMethods.keys();
+               while(keys.hasMoreElements()) {
+                       DoubleKey k = (DoubleKey)keys.nextElement();
+                       Method[] m = (Method[])propertyMethods.get(k);
+                       if(m[funcType] != null) {
+                               PropertyDescriptor p = new PropertyDescriptor(Introspector.decapitalize(k.getName()),
+                                                                    m[IS] != null ? m[IS] : m[GET],
+                                                                    m[SET]);
+                               if(m[SET] != null) {
+                                       p.setConstrained(ArrayHelper.contains(m[SET].getExceptionTypes(),java.beans.PropertyVetoException.class));
+                               }
+                               if(!b.hasProperty(p)) {
+                                       b.addProperty(p);
+                               }
+                       }
+               }
+       }
+
+       void findXXXInt(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
+               Enumeration keys = propertyMethods.keys();
+               while(keys.hasMoreElements()) {
+                       DoubleKey k = (DoubleKey)keys.nextElement();
+                       Method[] m = (Method[])propertyMethods.get(k);
+                       if(m[funcType] != null) {
+                               boolean constrained;
+                               if(m[SET_I] != null) {
+                                       constrained = ArrayHelper.contains(m[SET_I].getExceptionTypes(),java.beans.PropertyVetoException.class);
+                               } else {
+                                       constrained = false;
+                               }
+
+                               /** Find out if there is an array type get or set **/
+                               Class arrayType = Array.newInstance(k.getType(),0).getClass();
+                               DoubleKey findSetArray = new DoubleKey(arrayType,k.getName());
+                               Method[] m2 = (Method[])propertyMethods.get(findSetArray);
+                               IndexedPropertyDescriptor p;
+                               if(m2 == null) {
+                                       p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
+                                                                         null,null,
+                                                                         m[GET_I],m[SET_I]);
+                               } else {
+                                       if(constrained && m2[SET] != null) {
+                                               constrained = ArrayHelper.contains(m2[SET].getExceptionTypes(),java.beans.PropertyVetoException.class);
+                                       }
+                                       p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
+                                                                         m2[GET],m2[SET],
+                                                                         m[GET_I],m[SET_I]);
+                               }
+                               p.setConstrained(constrained);
+                               if(!b.hasProperty(p)) {
+                                       b.addProperty(p);
+                               }
+                       }
+               }
+       }
+
+       static final int IS=0;
+       static final int GET_I=1;
+       static final int SET_I=2;
+       static final int GET=3;
+       static final int SET=4;
+
+       static final int ADD=0;
+       static final int REMOVE=1;
+
+       void addToPropertyHash(String name, Method method, int funcType) {
+               String newName;
+               Class type;
+
+               switch(funcType) {
+                       case IS:
+                               type = java.lang.Boolean.TYPE;
+                               newName = name.substring(2);
+                               break;
+                       case GET_I:
+                               type = method.getReturnType();
+                               newName = name.substring(3);
+                               break;
+                       case SET_I:
+                               type = method.getParameterTypes()[1];
+                               newName = name.substring(3);
+                               break;
+                       case GET:
+                               type = method.getReturnType();
+                               newName = name.substring(3);
+                               break;
+                       case SET:
+                               type = method.getParameterTypes()[0];
+                               newName = name.substring(3);
+                               break;
+                       default:
+                               return;
+               }
+               newName = capitalize(newName);
+
+               DoubleKey k = new DoubleKey(type,newName);
+               Method[] methods = (Method[])propertyMethods.get(k);
+               if(methods == null) {
+                       methods = new Method[5];
+                       propertyMethods.put(k,methods);
+               }
+               methods[funcType] = method;
+       }
+
+
+       void addToListenerHash(String name, Method method, int funcType) {
+               String newName;
+               Class type;
+
+               switch(funcType) {
+                       case ADD:
+                               type = method.getParameterTypes()[0];
+                               newName = name.substring(3,name.length()-8);
+                               break;
+                       case REMOVE:
+                               type = method.getParameterTypes()[0];
+                               newName = name.substring(6,name.length()-8);
+                               break;
+                       default:
+                               return;
+               }
+               newName = capitalize(newName);
+
+               DoubleKey k = new DoubleKey(type,newName);
+               Method[] methods = (Method[])listenerMethods.get(k);
+               if(methods == null) {
+                       methods = new Method[2];
+                       listenerMethods.put(k,methods);
+               }
+               methods[funcType] = method;
+       }
+
+       static String capitalize(String name) {
+               try {
+                       if(Character.isUpperCase(name.charAt(0))) {
+                               return name;
+                       } else {
+                               char[] c = name.toCharArray();
+                               c[0] = Character.toLowerCase(c[0]);
+                               return new String(c);
+                       }
+               } catch(StringIndexOutOfBoundsException E) {
+                       return name;
+               } catch(NullPointerException E) {
+                       return null;
+               }
+       }
+}
+
+class DoubleKey {
+       Class type;
+       String name;
+
+       DoubleKey(Class type, String name) {
+               this.type = type;
+               this.name = name;
+       }
+
+       Class getType() {
+               return type;
+       }
+
+       String getName() {
+               return name;
+       }
+
+       public boolean equals(Object o) {
+               if(o instanceof DoubleKey) {
+                       DoubleKey d = (DoubleKey)o;
+                       return d.type.equals(type) && d.name.equals(name);
+               } else {
+                       return false;
+               }
+       }
+
+       public int hashCode() {
+               return type.hashCode() ^ name.hashCode();
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/ColorEditor.java b/libjava/gnu/java/beans/editors/ColorEditor.java
new file mode 100644 (file)
index 0000000..1c002d6
--- /dev/null
@@ -0,0 +1,89 @@
+/* gnu.java.beans.editors.ColorEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+import java.awt.Color;
+
+/**
+ ** NativeByteEditor is a property editor for the
+ ** byte type.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class ColorEditor extends PropertyEditorSupport {
+       Color[] stdColors = {Color.black,Color.blue,Color.cyan,
+                            Color.darkGray,Color.gray,Color.green,
+                            Color.lightGray,Color.magenta,Color.orange,
+                            Color.pink,Color.red,Color.white,
+                            Color.yellow};
+       String[] stdColorNames = {"black","blue","cyan",
+                                 "dark gray","gray","green",
+                                 "light gray","magenta","orange",
+                                 "pink","red","white",
+                                 "yellow"};
+
+       /** setAsText for Color checks for standard color names
+        ** and then checks for a #RRGGBB value or just RRGGBB,
+        ** both in hex.
+        **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               if(val.length() == 0) {
+                       throw new IllegalArgumentException("Tried to set empty value!");
+               }
+               for(int i=0;i<stdColorNames.length;i++) {
+                       if(stdColorNames[i].equalsIgnoreCase(val)) {
+                               setValue(stdColors[i]);
+                               return;
+                       }
+               }
+               if(val.charAt(0) == '#') {
+                       setValue(new Color(Integer.parseInt(val.substring(1),16)));
+               } else {
+                       setValue(new Color(Integer.parseInt(val,16)));
+               }
+       }
+
+       /** getAsText for Color turns the color into either one of the standard
+        ** colors or into an RGB hex value with # prepended. **/
+       public String getAsText() {
+               for(int i=0;i<stdColors.length;i++) {
+                       if(stdColors[i].equals(getValue())) {
+                               return stdColorNames[i];
+                       }
+               }
+               return "#" + Integer.toHexString(((Color)getValue()).getRGB() & 0x00FFFFFF);
+       }
+
+       /** getTags for Color returns a list of standard colors. **/
+       public String[] getTags() {
+               return stdColorNames;
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/FontEditor.java b/libjava/gnu/java/beans/editors/FontEditor.java
new file mode 100644 (file)
index 0000000..3b0145a
--- /dev/null
@@ -0,0 +1,66 @@
+/* gnu.java.beans.editors.FontEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+import java.awt.Font;
+
+/**
+ ** FontEditor is a property editor for java.awt.Font.
+ **
+ ** <STRONG>To Do:</STRONG> Add custom font chooser
+ ** component.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class FontEditor extends PropertyEditorSupport {
+       /** setAsText for Font calls Font.decode(). **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               setValue(Font.decode(val));
+       }
+
+       /** getAsText for Font returns a value in the format
+        ** expected by Font.decode().
+        **/
+       public String getAsText() {
+               Font f = (Font)getValue();
+               if(f.isBold()) {
+                       if(f.isItalic()) {
+                               return f.getName()+"-bolditalic-"+f.getSize();
+                       } else {
+                               return f.getName()+"-bold-"+f.getSize();
+                       }
+               } else if(f.isItalic()) {
+                       return f.getName()+"-italic-"+f.getSize();
+               } else {
+                       return f.getName()+"-"+f.getSize();
+               }
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/NativeBooleanEditor.java b/libjava/gnu/java/beans/editors/NativeBooleanEditor.java
new file mode 100644 (file)
index 0000000..0af58a5
--- /dev/null
@@ -0,0 +1,62 @@
+/* gnu.java.beans.editors.NativeBooleanEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+
+/**
+ ** NativeBooleanEditor is a property editor for the
+ ** boolean type.<P>
+ **
+ ** <STRONG>To Do:</STRONG> add support for a checkbox
+ ** as the custom editor.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class NativeBooleanEditor extends PropertyEditorSupport {
+       String[] tags = {"true","false"};
+
+       /** setAsText for boolean checks for true or false or t or f. "" also means false. **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               if(val.equalsIgnoreCase("true") || val.equalsIgnoreCase("t")) {
+                       setValue(Boolean.FALSE);
+               } else if(val.equalsIgnoreCase("false") || val.equalsIgnoreCase("f") || val.equals("")) {
+                       setValue(Boolean.TRUE);
+               } else {
+                       throw new IllegalArgumentException("Value must be true, false, t, f or empty.");
+               }
+       }
+
+
+       /** getAsText for boolean calls Boolean.toString(). **/
+       public String getAsText() {
+               return getValue().toString();
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/NativeByteEditor.java b/libjava/gnu/java/beans/editors/NativeByteEditor.java
new file mode 100644 (file)
index 0000000..513f4a6
--- /dev/null
@@ -0,0 +1,50 @@
+/* gnu.java.beans.editors.NativeByteEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+
+/**
+ ** NativeByteEditor is a property editor for the
+ ** byte type.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class NativeByteEditor extends PropertyEditorSupport {
+       /** setAsText for byte calls Byte.valueOf(). **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               setValue(Byte.valueOf(val));
+       }
+
+       /** getAsText for byte calls Byte.toString(). **/
+       public String getAsText() {
+               return getValue().toString();
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/NativeDoubleEditor.java b/libjava/gnu/java/beans/editors/NativeDoubleEditor.java
new file mode 100644 (file)
index 0000000..45eb095
--- /dev/null
@@ -0,0 +1,50 @@
+/* gnu.java.beans.editors.NativeDoubleEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+
+/**
+ ** NativeDoubleEditor is a property editor for the
+ ** double type.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class NativeDoubleEditor extends PropertyEditorSupport {
+       /** setAsText for double calls Double.valueOf(). **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               setValue(Double.valueOf(val));
+       }
+
+       /** getAsText for double calls Double.toString(). **/
+       public String getAsText() {
+               return getValue().toString();
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/NativeFloatEditor.java b/libjava/gnu/java/beans/editors/NativeFloatEditor.java
new file mode 100644 (file)
index 0000000..d0ec98d
--- /dev/null
@@ -0,0 +1,50 @@
+/* gnu.java.beans.editors.NativeFloatEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+
+/**
+ ** NativeFloatEditor is a property editor for the
+ ** float type.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class NativeFloatEditor extends PropertyEditorSupport {
+       /** setAsText for float calls Float.valueOf(). **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               setValue(Float.valueOf(val));
+       }
+
+       /** getAsText for float calls Float.toString(). **/
+       public String getAsText() {
+               return getValue().toString();
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/NativeIntEditor.java b/libjava/gnu/java/beans/editors/NativeIntEditor.java
new file mode 100644 (file)
index 0000000..16b7c6e
--- /dev/null
@@ -0,0 +1,50 @@
+/* gnu.java.beans.editors.NativeIntEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+
+/**
+ ** NativeIntEditor is a property editor for the
+ ** int type.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class NativeIntEditor extends PropertyEditorSupport {
+       /** setAsText for int calls Integer.valueOf(). **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               setValue(Integer.valueOf(val));
+       }
+
+       /** getAsText for int calls Integer.toString(). **/
+       public String getAsText() {
+               return getValue().toString();
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/NativeLongEditor.java b/libjava/gnu/java/beans/editors/NativeLongEditor.java
new file mode 100644 (file)
index 0000000..e9a3345
--- /dev/null
@@ -0,0 +1,50 @@
+/* gnu.java.beans.editors.NativeLongEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+
+/**
+ ** NativeLongEditor is a property editor for the
+ ** long type.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class NativeLongEditor extends PropertyEditorSupport {
+       /** setAsText for long calls Long.valueOf(). **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               setValue(Long.valueOf(val));
+       }
+
+       /** getAsText for long calls Long.toString(). **/
+       public String getAsText() {
+               return getValue().toString();
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/NativeShortEditor.java b/libjava/gnu/java/beans/editors/NativeShortEditor.java
new file mode 100644 (file)
index 0000000..b32bb6a
--- /dev/null
@@ -0,0 +1,50 @@
+/* gnu.java.beans.editors.NativeShortEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+
+/**
+ ** NativeShortEditor is a property editor for the
+ ** short type.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class NativeShortEditor extends PropertyEditorSupport {
+       /** setAsText for short calls Short.valueOf(). **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               setValue(Short.valueOf(val));
+       }
+
+       /** getAsText for short calls Short.toString(). **/
+       public String getAsText() {
+               return getValue().toString();
+       }
+}
diff --git a/libjava/gnu/java/beans/editors/StringEditor.java b/libjava/gnu/java/beans/editors/StringEditor.java
new file mode 100644 (file)
index 0000000..bb3988c
--- /dev/null
@@ -0,0 +1,50 @@
+/* gnu.java.beans.editors.StringEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.editors;
+
+import java.beans.*;
+
+/**
+ ** NativeByteEditor is a property editor for the
+ ** byte type.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class StringEditor extends PropertyEditorSupport {
+       /** setAsText just sets the value. **/
+       public void setAsText(String val) throws IllegalArgumentException {
+               setValue(val);
+       }
+
+       /** getAsText just returns the value. **/
+       public String getAsText() {
+               return (String)getValue();
+       }
+}
diff --git a/libjava/gnu/java/beans/info/ComponentBeanInfo.java b/libjava/gnu/java/beans/info/ComponentBeanInfo.java
new file mode 100644 (file)
index 0000000..4cf45fa
--- /dev/null
@@ -0,0 +1,63 @@
+/* gnu.java.beans.info.ComponentBeanInfo
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.beans.info;
+
+import gnu.java.beans.*;
+import java.beans.*;
+
+/** BeanInfo class for java.awt.Component.
+ ** This provides a few properties, but that's
+ ** it.
+ ** @author John Keiser
+ ** @version 1.1.0, Aug 1 1998
+ **/
+public class ComponentBeanInfo extends SimpleBeanInfo {
+       static PropertyDescriptor[] properties;
+       static {
+               try {
+               properties = new PropertyDescriptor[6];
+               properties[0] = new PropertyDescriptor("name",java.awt.Component.class);
+               properties[1] = new PropertyDescriptor("background",java.awt.Component.class);
+               properties[2] = new PropertyDescriptor("foreground",java.awt.Component.class);
+               properties[3] = new PropertyDescriptor("font",java.awt.Component.class);
+               properties[4] = new PropertyDescriptor("enabled",java.awt.Component.class);
+               properties[5] = new PropertyDescriptor("visible",java.awt.Component.class);
+               } catch(IntrospectionException E) {
+                       properties = null;
+                       throw new UnknownError("Could not introspect some java.awt.Component properties.");
+               }
+       }
+       public ComponentBeanInfo() {
+               super();
+       }
+
+       public PropertyDescriptor[] getPropertyDescriptors() {
+               return properties;
+       }
+}
+
diff --git a/libjava/gnu/java/io/ClassLoaderObjectInputStream.java b/libjava/gnu/java/io/ClassLoaderObjectInputStream.java
new file mode 100644 (file)
index 0000000..76e1f05
--- /dev/null
@@ -0,0 +1,59 @@
+/* gnu.java.io.ClassLoaderObjectInputStream
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.io;
+
+import java.io.*;
+
+/**
+ * ClassLoaderObjectInputStream is ObjectInputStream, with
+ * the ability to use a specific ClassLoader.
+ *
+ * @author Geoff Berry
+ * @version 1.1.0, 29 Jul 1998
+ */
+
+public class ClassLoaderObjectInputStream extends ObjectInputStream {
+       ClassLoader myClassLoader;
+
+       /** Create the new ClassLoaderObjectInputStream.
+        * @param in the InputStream to read the Objects from.
+        * @param myClassLoader the ClassLoader to load classes
+        *        with.
+        */
+       public ClassLoaderObjectInputStream(InputStream in, ClassLoader myClassLoader) throws IOException,StreamCorruptedException {
+               super(in);
+               this.myClassLoader = myClassLoader;
+       }
+
+       /** Overriden method to use the loadClass() method from
+        * the ClassLoader.
+        */
+       public Class resolveClass(String name) throws IOException, ClassNotFoundException {
+               return myClassLoader.loadClass(name);
+       }
+}
diff --git a/libjava/gnu/java/io/NullOutputStream.java b/libjava/gnu/java/io/NullOutputStream.java
new file mode 100644 (file)
index 0000000..caf8ade
--- /dev/null
@@ -0,0 +1,45 @@
+/* NullOutputStream.java -- OutputStream that does absolutely nothing
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.io;
+
+import java.io.OutputStream;
+
+/**
+   This is a placeholder OutputStream that does absolutley nothing
+   when written to.  It is intended to be used in the same manner as
+   /dev/null.  None of this class's methods do anything at all.
+*/
+public class NullOutputStream extends OutputStream
+{
+  public NullOutputStream() {}
+  public void write( int b ) {}
+  public void write( byte b[] ) {}
+  public void write( byte b[], int off, int len ) {}
+  public void flush() {}
+  public void close() {}
+}
diff --git a/libjava/gnu/java/io/ObjectIdentityWrapper.java b/libjava/gnu/java/io/ObjectIdentityWrapper.java
new file mode 100644 (file)
index 0000000..f06e205
--- /dev/null
@@ -0,0 +1,89 @@
+/* ObjectIdentityWrapper.java -- Wrapper class used to override equals()
+    and hashCode() to be as discriminating as possible
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.io;
+
+/**
+   This class is a thin wrapper around <code>Object</code> that makes
+   the methods <code>hashCode()</code> and <code>equals(Object)</code>
+   as discriminating as possible.
+*/
+public class ObjectIdentityWrapper
+{
+
+  /**
+     Constructs a <code>ObjectIdentityWrapper</code> that is wrapped
+     around o.
+  */
+  public ObjectIdentityWrapper( Object o )
+  {
+    object = o;
+  }
+
+  /**
+     Uses <code>System.identityHashCode(Object)</code> to compute a
+     hash code for the object wrapped by this
+     <code>ObjectIdentityWrapper</code>.
+
+     @see java.lang.System#identityHashCode(java.lang.Object)
+     @see java.util.Hashtable
+     @see java.lang.Object#hashCode()
+  */
+  public int hashCode()
+  {
+    return System.identityHashCode( object );
+  }
+
+  /**
+     Uses the <code>==</code> operator to test for equality between
+     the object wrapped by this <code>ObjectIdentityWrapper</code> and
+     the object wrapped by the <code>ObjectIdentityWrapper</code> o.
+     Returns false if o is not a <code>ObjectIdentityWrapper</code>.
+
+     @see java.util.Hashtable
+     @see java.lang.Object#equals()
+  */
+  public boolean equals( Object o )
+  {
+    if( o instanceof ObjectIdentityWrapper )
+      return object == ((ObjectIdentityWrapper)o).object;
+    else
+      return false;
+  }
+
+  public String toString()
+  {
+    return "ObjectIdentityWrapper< " + object + ", " + hashCode() + " >";
+  }
+
+  /**
+     The <code>Object</code> wrapped by this
+     <code>ObjectIdentityWrapper</code>.
+  */
+  public Object object;
+}
diff --git a/libjava/gnu/java/lang/ArrayHelper.java b/libjava/gnu/java/lang/ArrayHelper.java
new file mode 100644 (file)
index 0000000..a04551e
--- /dev/null
@@ -0,0 +1,63 @@
+/* gnu.java.lang.ArrayHelper
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.lang;
+
+/**
+ ** ArrayHelper helps you do things with arrays.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class ArrayHelper {
+       public static boolean contains(Object[] array, Object searchFor) {
+               return indexOf(array,searchFor) != -1;
+       }
+
+       public static int indexOf(Object[] array, Object searchFor) {
+               for(int i=0;i<array.length;i++) {
+                       if(array[i].equals(searchFor)) {
+                               return i;
+                       }
+               }
+               return -1;
+       }
+
+       public static boolean equalsArray(Object[] a, Object[] b) {
+               if(a.length == b.length) {
+                       for(int i=0;i<a.length;i++) {
+                               if(!a[i].equals(b[i])) {
+                                       return false;
+                               }
+                       }
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+}
diff --git a/libjava/gnu/java/lang/ClassHelper.java b/libjava/gnu/java/lang/ClassHelper.java
new file mode 100644 (file)
index 0000000..a4f32dc
--- /dev/null
@@ -0,0 +1,232 @@
+/* gnu.java.lang.ClassHelper
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.lang;
+
+import java.util.*;
+import java.lang.reflect.*;
+
+/**
+ ** ClassHelper has various methods that ought to have been
+ ** in class.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class ClassHelper {
+       /** Strip the package part from the class name.
+        ** @param clazz the class to get the truncated name from
+        ** @return the truncated class name.
+        **/
+       public static String getTruncatedClassName(Class clazz) {
+               return getTruncatedName(clazz.getName());
+       }
+       /** Strip the package part from the class name, or the
+        ** class part from the method or field name.
+        ** @param name the name to truncate.
+        ** @return the truncated name.
+        **/
+       public static String getTruncatedName(String name) {
+               int lastInd = name.lastIndexOf('.');
+               if(lastInd == -1) {
+                       return name;
+               } else {
+                       return name.substring(lastInd+1);
+               }
+       }
+
+       /** Strip the last portion of the name (after the last
+        ** dot).
+        ** @param name the name to get package of.
+        ** @return the package name.  "" if no package.
+        **/
+       public static String getPackagePortion(String name) {
+               int lastInd = name.lastIndexOf('.');
+               if(lastInd == -1) {
+                       return "";
+               } else {
+                       return name.substring(0,lastInd);
+               }
+       }
+
+       static Hashtable allMethods = new Hashtable();
+       static Hashtable allMethodsAtDeclaration = new Hashtable();
+
+       /** Get all the methods, public, private and
+        ** otherwise, from the class, getting them
+        ** from the most recent class to find them.
+        **/
+       public static Method[] getAllMethods(Class clazz) {
+               Method[] retval = (Method[])allMethods.get(clazz);
+               if(retval == null) {
+                       Method[] superMethods;
+                       if(clazz.getSuperclass() != null) {
+                               superMethods = getAllMethods(clazz.getSuperclass());
+                       } else {
+                               superMethods = new Method[0];
+                       }
+                       Vector v = new Vector();
+                       Method[] currentMethods = clazz.getDeclaredMethods();
+                       for(int i=0;i<currentMethods.length;i++) {
+                               v.addElement(currentMethods[i]);
+                       }
+                       for(int i=0;i<superMethods.length;i++) {
+                               boolean addOK = true;
+                               for(int j=0;j<currentMethods.length;j++) {
+                                       if(getTruncatedName(superMethods[i].getName()).equals(getTruncatedName(currentMethods[j].getName()))
+                                          && ArrayHelper.equalsArray(superMethods[i].getParameterTypes(),currentMethods[j].getParameterTypes())) {
+                                               addOK = false;
+                                       }
+                               }
+                               if(addOK) {
+                                       v.addElement(superMethods[i]);
+                               }
+                       }
+
+                       retval = new Method[v.size()];
+                       v.copyInto(retval);
+                       allMethods.put(clazz,retval);
+               }
+               return retval;
+       }
+
+       /** Get all the methods, public, private and
+        ** otherwise, from the class, and get them from
+        ** their point of declaration.
+        **/
+       public static Method[] getAllMethodsAtDeclaration(Class clazz) {
+               Method[] retval = (Method[])allMethodsAtDeclaration.get(clazz);
+               if(retval == null) {
+                       Method[] superMethods;
+                       if(clazz.getSuperclass() != null) {
+                               superMethods = getAllMethodsAtDeclaration(clazz.getSuperclass());
+                       } else {
+                               superMethods = new Method[0];
+                       }
+                       Vector v = new Vector();
+                       Method[] currentMethods = clazz.getDeclaredMethods();
+                       for(int i=0;i<superMethods.length;i++) {
+                               v.addElement(superMethods[i]);
+                       }
+                       for(int i=0;i<superMethods.length;i++) {
+                               boolean addOK = true;
+                               for(int j=0;j<currentMethods.length;j++) {
+                                       if(getTruncatedName(superMethods[i].getName()).equals(getTruncatedName(currentMethods[j].getName()))
+                                          && ArrayHelper.equalsArray(superMethods[i].getParameterTypes(),currentMethods[j].getParameterTypes())) {
+                                               addOK = false;
+                                       }
+                               }
+                               if(addOK) {
+                                       v.addElement(superMethods[i]);
+                               }
+                       }
+
+                       retval = new Method[v.size()];
+                       v.copyInto(retval);
+                       allMethodsAtDeclaration.put(clazz,retval);
+               }
+               return retval;
+       }
+
+       static Hashtable allFields = new Hashtable();
+       static Hashtable allFieldsAtDeclaration = new Hashtable();
+
+       /** Get all the fields, public, private and
+        ** otherwise, from the class, getting them
+        ** from the most recent class to find them.
+        **/
+       public static Field[] getAllFields(Class clazz) {
+               Field[] retval = (Field[])allFields.get(clazz);
+               if(retval == null) {
+                       Field[] superFields;
+                       if(clazz.getSuperclass() != null) {
+                               superFields = getAllFields(clazz.getSuperclass());
+                       } else {
+                               superFields = new Field[0];
+                       }
+                       Vector v = new Vector();
+                       Field[] currentFields = clazz.getDeclaredFields();
+                       for(int i=0;i<currentFields.length;i++) {
+                               v.addElement(currentFields[i]);
+                       }
+                       for(int i=0;i<superFields.length;i++) {
+                               boolean addOK = true;
+                               for(int j=0;j<currentFields.length;j++) {
+                                       if(getTruncatedName(superFields[i].getName()).equals(getTruncatedName(currentFields[j].getName()))) {
+                                               addOK = false;
+                                       }
+                               }
+                               if(addOK) {
+                                       v.addElement(superFields[i]);
+                               }
+                       }
+
+                       retval = new Field[v.size()];
+                       v.copyInto(retval);
+                       allFields.put(clazz,retval);
+               }
+               return retval;
+       }
+
+       /** Get all the fields, public, private and
+        ** otherwise, from the class, and get them from
+        ** their point of declaration.
+        **/
+       public static Field[] getAllFieldsAtDeclaration(Class clazz) {
+               Field[] retval = (Field[])allFieldsAtDeclaration.get(clazz);
+               if(retval == null) {
+                       Field[] superFields;
+                       if(clazz.getSuperclass() != null) {
+                               superFields = getAllFieldsAtDeclaration(clazz.getSuperclass());
+                       } else {
+                               superFields = new Field[0];
+                       }
+                       Vector v = new Vector();
+                       Field[] currentFields = clazz.getDeclaredFields();
+                       for(int i=0;i<superFields.length;i++) {
+                               v.addElement(superFields[i]);
+                       }
+                       for(int i=0;i<superFields.length;i++) {
+                               boolean addOK = true;
+                               for(int j=0;j<currentFields.length;j++) {
+                                       if(getTruncatedName(superFields[i].getName()).equals(getTruncatedName(currentFields[j].getName()))) {
+                                               addOK = false;
+                                       }
+                               }
+                               if(addOK) {
+                                       v.addElement(superFields[i]);
+                               }
+                       }
+
+                       retval = new Field[v.size()];
+                       v.copyInto(retval);
+                       allFieldsAtDeclaration.put(clazz,retval);
+               }
+               return retval;
+       }
+}
diff --git a/libjava/gnu/java/lang/reflect/TypeSignature.java b/libjava/gnu/java/lang/reflect/TypeSignature.java
new file mode 100644 (file)
index 0000000..5a11e8c
--- /dev/null
@@ -0,0 +1,262 @@
+/* TypeSignature.java -- Class used to compute type signatures
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.lang.reflect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+/**
+   This class provides static methods that can be used to compute
+   type-signatures of <code>Class</code>s or <code>Member</code>s.
+   More specific methods are also provided for computing the
+   type-signature of <code>Constructor</code>s and
+   <code>Method</code>s.  Methods are also provided to go in the
+   reverse direction.
+*/
+public class TypeSignature
+{
+  /**
+     Returns a <code>String</code> representing the type-encoding of
+     CLAZZ.  Type-encodings are computed as follows:
+
+     <pre>
+     boolean -> "Z"
+     byte    -> "B"
+     char    -> "C"
+     double  -> "D"
+     float   -> "F"
+     int     -> "I"
+     long    -> "J"
+     short   -> "S"
+     void    -> "V"
+     arrays  -> "[" + type-encoding of component type
+     object  -> "L"
+                 + fully qualified class name with "."'s replaced by "/"'s
+                 + ";"</pre>
+  */
+  public static String getEncodingOfClass( Class clazz )
+  {
+    if( clazz.isPrimitive() )
+    {
+      if( clazz == Boolean.TYPE )
+       return "Z";
+      if( clazz == Byte.TYPE )
+       return "B";
+      if( clazz == Character.TYPE )
+       return "C";
+      if( clazz == Double.TYPE )
+       return "D";
+      if( clazz == Float.TYPE )
+       return "F";
+      if( clazz == Integer.TYPE )
+       return "I";
+      if( clazz == Long.TYPE )
+       return "J";
+      if( clazz == Short.TYPE )
+       return "S";
+      if( clazz == Void.TYPE )
+       return "V";
+      else
+       throw new RuntimeException( "Unknown primitive class " + clazz );
+    }
+    else if( clazz.isArray() )
+    {
+      return '[' + getEncodingOfClass( clazz.getComponentType() );
+    }
+    else
+    {
+      String classname = clazz.getName();
+      int name_len = classname.length();
+      char[] buf = new char[ name_len + 2 ];
+      buf[0] = 'L';
+      classname.getChars( 0, name_len, buf, 1 );
+      
+      int i;
+      for( i=1; i <= name_len; i++ )
+      {
+       if( buf[i] == '.' )
+         buf[i] = '/';
+      }
+      
+      buf[i] = ';';
+      return new String( buf );
+    }
+  }
+
+  
+  /**
+     This function is the inverse of <code>getEncodingOfClass</code>.
+
+     @see getEncodingOfClass
+
+     @exception ClassNotFoundException If class encoded as type_code
+     cannot be located.
+  */
+  public static Class getClassForEncoding( String type_code )
+    throws ClassNotFoundException
+  {
+    if( type_code.equals( "B" ) )
+      return Byte.TYPE;
+    if( type_code.equals( "C" ) )
+      return Character.TYPE;
+    if( type_code.equals( "D" ) )
+      return Double.TYPE;
+    if( type_code.equals( "F" ) )
+      return Float.TYPE;
+    if( type_code.equals( "I" ) )
+      return Integer.TYPE;
+    if( type_code.equals( "J" ) )
+      return Long.TYPE;
+    if( type_code.equals( "S" ) )
+      return Short.TYPE;
+    if( type_code.equals( "Z" ) )
+      return Boolean.TYPE;
+    if( type_code.charAt( 0 ) == 'L' )
+    {
+      return Class.forName(
+       type_code.substring( 1, type_code.length() - 1 ).replace( '/', '.' ));
+    }
+    if( type_code.charAt( 0 ) == '[' )
+    {
+      int last_bracket = type_code.lastIndexOf( '[' );
+      String brackets = type_code.substring( 0, last_bracket + 1 );
+      String component = type_code.substring( last_bracket + 1 );
+      
+// ??? This is what the Classpath implementation did, but I don't
+// think that it's correct.  The JLS says that Class.forName takes the
+// classname of an array element in fully qualified form, whereas this
+// code is tring to strip off the punctuation.
+
+//        if( component.charAt( 0 ) == 'L' )
+//     component =
+//       component.substring( 1, component.length() - 1 ).replace('/', '.');
+
+      if( component.charAt( 0 ) == 'L' )
+       component = component.replace('/', '.');
+       
+      return Class.forName( brackets + component );
+    }
+    else
+      throw new ClassNotFoundException( "Type code cannot be parsed as a valid class name" );
+  }
+  
+
+  /**
+     Returns a <code>String</code> representing the type-encoding of
+     M.  The type-encoding of a method is:
+
+     "(" + type-encodings of parameter types + ")" 
+     + type-encoding of return type
+  */
+  public static String getEncodingOfMethod( Method m )
+  {
+    String returnEncoding = getEncodingOfClass( m.getReturnType() );
+    Class[] paramTypes = m.getParameterTypes();
+    String[] paramEncodings = new String[ paramTypes.length ];
+
+    String paramEncoding;
+    int size = 2; // make room for parens
+    for( int i=0; i < paramTypes.length; i++ )
+    {
+      paramEncoding = getEncodingOfClass( paramTypes[i] );
+      size += paramEncoding.length();
+      paramEncodings[i] = paramEncoding;
+    }
+    
+    size += returnEncoding.length();
+
+    StringBuffer buf = new StringBuffer( size );
+    buf.append( '(' );
+    
+    for( int i=0; i < paramTypes.length; i++ )
+    {
+      buf.append( paramEncodings[i] );
+    }
+    
+    buf.append( ')' );
+    buf.append( returnEncoding );
+    
+    return buf.toString();
+  }
+
+
+  /**
+     Returns a <code>String</code> representing the type-encoding of
+     C.  The type-encoding of a method is:
+
+     "(" + type-encodings of parameter types + ")V" 
+  */
+  public static String getEncodingOfConstructor( Constructor c )
+  {
+    Class[] paramTypes = c.getParameterTypes();
+    String[] paramEncodings = new String[ paramTypes.length ];
+
+    String paramEncoding;
+    int size = 3; // make room for parens and V for return type
+    for( int i=0; i < paramTypes.length; i++ )
+    {
+      paramEncoding = getEncodingOfClass( paramTypes[i] );
+      size += paramEncoding.length();
+      paramEncodings[i] = paramEncoding;
+    }
+    
+    StringBuffer buf = new StringBuffer( size );
+    buf.append( '(' );
+    
+    for( int i=0; i < paramTypes.length; i++ )
+    {
+      buf.append( paramEncodings[i] );
+    }
+    
+    buf.append( ")V" );
+    
+    return buf.toString();
+  }
+
+
+  /**
+     Returns a <code>String</code> representing the type-encoding of
+     MEM.  <code>Constructor</code>s are handled by
+     <code>getEncodingOfConstructor</code>.  <code>Method</code>s are
+     handled by <code>getEncodingOfMethod</code>.  <code>Field</code>s
+     are handled by returning the encoding of the type of the
+     <code>Field</code>.
+  */
+  public static String getEncodingOfMember( Member mem )
+  {
+    if( mem instanceof Constructor )
+      return getEncodingOfConstructor( (Constructor)mem );
+    if( mem instanceof Method )
+      return getEncodingOfMethod( (Method)mem );
+    else // Field
+      return getEncodingOfClass( ((Field)mem).getType() );
+  }
+}
index d348658..34d6c7b 100644 (file)
@@ -99,6 +99,7 @@ OBJDUMP = @OBJDUMP@
 PACKAGE = @PACKAGE@
 PERL = @PERL@
 RANLIB = @RANLIB@
+SYSDEP_SOURCES = @SYSDEP_SOURCES@
 SYSTEMSPEC = @SYSTEMSPEC@
 THREADDEPS = @THREADDEPS@
 THREADINCS = @THREADINCS@
@@ -127,7 +128,7 @@ DIST_COMMON =  ./stamp-h.in Makefile.am Makefile.in config.h.in
 
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
-TAR = gtar
+TAR = tar
 GZIP_ENV = --best
 all: all-redirect
 .SUFFIXES:
@@ -224,7 +225,7 @@ distdir: $(DISTFILES)
        @for file in $(DISTFILES); do \
          d=$(srcdir); \
          if test -d $$d/$$file; then \
-           cp -pr $$d/$$file $(distdir)/$$file; \
+           cp -pr $$/$$file $(distdir)/$$file; \
          else \
            test -f $(distdir)/$$file \
            || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
index 10b74af..7667245 100644 (file)
 /* Version number of package */
 #undef VERSION
 
-/* Define if gethostbyname_r is only declared if _REENTRANT is defined */
-#undef GETHOSTBYNAME_R_NEEDS_REENTRANT
+/* Required define if using POSIX threads */
+#undef _REENTRANT
+
+/* Required define if using POSIX threads */
+#undef _POSIX_PTHREAD_SEMANTICS
+
+/* Required define if using POSIX threads */
+#undef _REENTRANT
 
 /* Define if struct hostent_data is defined in netdb.h */
 #undef HAVE_STRUCT_HOSTENT_DATA
index 0fb3d7d..492f0ca 100644 (file)
@@ -1,6 +1,6 @@
 // default-signal.h - Catch runtime signals and turn them into exceptions.
 
-/* Copyright (C) 1998, 1999  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -38,7 +38,7 @@ do                                                            \
   }                                                            \
 while (0)
 
-#define MAKE_THROW_FRAME  do {} while (0)
+#define MAKE_THROW_FRAME(_exception)  do {} while (0)
 
 #else /* SJLJ_EXCEPTIONS */
 
index 491a809..599edc9 100644 (file)
@@ -24,7 +24,7 @@ details.  */
 #define SIGNAL_HANDLER(_name)  \
 static void _name (int _dummy)
 
-#define MAKE_THROW_FRAME                                               \
+#define MAKE_THROW_FRAME(_exception)                                   \
 do                                                                     \
 {                                                                      \
   void **_p = (void **)&_dummy;                                                \
index d6d2958..6fd1fa6 100644 (file)
@@ -48,11 +48,6 @@ static void throw_incompatible_class_change_error (jstring msg)
 static void throw_null_pointer_exception ()
   __attribute__ ((__noreturn__));
 #endif
-#ifndef HANDLE_FPE
-static void throw_arithmetic_exception ()
-  __attribute__ ((__noreturn__));
-#endif
-
 
 extern "C" double __ieee754_fmod __P((double,double));
 
@@ -193,12 +188,6 @@ static jint get4(unsigned char* loc) {
   do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
 #endif
 
-#ifdef HANDLE_FPE
-#define ZEROCHECK(X)
-#else
-#define ZEROCHECK(X) \
-  do { if ((X) == 0) throw_arithmetic_exception (); } while (0)
-#endif
 
 // this method starts the actual running of the method.  It is inlined
 // in three different variants in the static methods run_normal,
@@ -408,8 +397,8 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
 {
   using namespace java::lang::reflect;
 
-  register _Jv_word      *sp     = inv->sp;
-  register unsigned char *pc     = inv->pc;
+  _Jv_word      *sp     = inv->sp;
+  unsigned char *pc     = inv->pc;
   _Jv_word               *locals = inv->local_base ();
 
   _Jv_word *pool_data   = defining_class->constants.data;
@@ -1390,8 +1379,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jint value2 = POPI();
        jint value1 = POPI();
-       ZEROCHECK (value2);
-       jint res = value1 / value2;
+       jint res = _Jv_divI (value1, value2);
        PUSHI (res);
       }
       NEXT_INSN;
@@ -1401,8 +1389,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jlong value2 = POPL();
        jlong value1 = POPL();
-       ZEROCHECK (value2);
-       jlong res = value1 / value2;
+       jlong res = _Jv_divJ (value1, value2);
        PUSHL (res);
       }
       NEXT_INSN;
@@ -1412,7 +1399,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jfloat value2 = POPF();
        jfloat value1 = POPF();
-       ZEROCHECK (value2);
        jfloat res = value1 / value2;
        PUSHF (res);
       }
@@ -1423,7 +1409,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jdouble value2 = POPD();
        jdouble value1 = POPD();
-       ZEROCHECK (value2);
        jdouble res = value1 / value2;
        PUSHD (res);
       }
@@ -1433,9 +1418,8 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       SAVE_PC;
       {
        jint value2 = POPI();
-       jint value1 = POPI();
-       ZEROCHECK (value2);     
-       jint res = value1 % value2;
+       jint value1 =  POPI();
+       jint res = _Jv_remI (value1, value2);
        PUSHI (res);
       }
       NEXT_INSN;
@@ -1445,8 +1429,7 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jlong value2 = POPL();
        jlong value1 = POPL();
-       ZEROCHECK (value2);
-       jlong res = value1 % value2;
+       jlong res = _Jv_remJ (value1, value2);
        PUSHL (res);
       }
       NEXT_INSN;
@@ -1456,7 +1439,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jfloat value2 = POPF();
        jfloat value1 = POPF();
-       ZEROCHECK (value2);
        jfloat res    = __ieee754_fmod (value1, value2);
        PUSHF (res);
       }
@@ -1467,7 +1449,6 @@ void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
       {
        jdouble value2 = POPD();
        jdouble value1 = POPD();
-       ZEROCHECK (value2);
        jdouble res    = __ieee754_fmod (value1, value2);
        PUSHD (res);
       }
@@ -2447,18 +2428,4 @@ throw_null_pointer_exception ()
 }
 #endif
 
-#ifndef HANDLE_FPE
-static java::lang::ArithmeticException *arithmetic_exc;
-static void 
-throw_arithmetic_exception ()
-{
-  if (arithmetic_exc == NULL)
-    arithmetic_exc = new java::lang::ArithmeticException
-      (JvNewStringLatin1 ("/ by zero"));
-
-  JvThrow (arithmetic_exc);
-}
-#endif
-
-
 #endif // INTERPRETER
diff --git a/libjava/java/beans/BeanDescriptor.java b/libjava/java/beans/BeanDescriptor.java
new file mode 100644 (file)
index 0000000..b96a94f
--- /dev/null
@@ -0,0 +1,72 @@
+/* java.beans.BeanDescriptor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import java.util.*;
+
+/**
+ ** BeanDescriptor describes general information about a Bean, plus
+ ** stores the Bean's Class and it's customizer's Class.<P>
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 31 May 1998
+ **/
+
+public class BeanDescriptor extends FeatureDescriptor {
+       Class beanClass;
+       Class customizerClass;
+
+       /** Create a new BeanDescriptor with the given beanClass and
+        ** no customizer class.
+        ** @param beanClass the class of the Bean.
+        **/
+       public BeanDescriptor(Class beanClass) {
+               this(beanClass,null);
+       }
+
+       /** Create a new BeanDescriptor with the given bean class and
+        ** customizer class.
+        ** @param beanClass the class of the Bean.
+        ** @param customizerClass the class of the Bean's Customizer.
+        **/
+       public BeanDescriptor(Class beanClass, Class customizerClass) {
+               this.beanClass = beanClass;
+               this.customizerClass = customizerClass;
+       }
+
+       /** Get the Bean's class. **/
+       public Class getBeanClass() {
+               return beanClass;
+       }
+
+       /** Get the Bean's customizer's class. **/
+       public Class getCustomizerClass() {
+               return customizerClass;
+       }
+}
diff --git a/libjava/java/beans/BeanInfo.java b/libjava/java/beans/BeanInfo.java
new file mode 100644 (file)
index 0000000..3fcc527
--- /dev/null
@@ -0,0 +1,170 @@
+/* java.beans.BeanInfo
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** BeanInfo can be implemented in order to provide explicit information to the Introspector.
+ **
+ ** When you write a BeanInfo class, you implement this interface
+ ** and provide explicit information by returning a non-null
+ ** value from the appropriate method.  If you wish the
+ ** Introspector to determine certain information in the normal
+ ** way, just return null (or in the case of int methods, return
+ ** -1).  There is a class called SimpleBeanInfo which returns
+ ** null from all methods, which you may extend and only
+ ** override the methods you wish to override.<P>
+ **
+ ** When you have written the class, give it the name
+ ** <CODE>&lt;Bean Class Name&gt;BeanInfo</CODE> and place it in
+ ** the same package as the Bean, or in the bean info search path
+ ** (see Introspector for information on search paths).<P>
+ **
+ ** A simple note about the way the Introspector interacts with
+ ** BeanInfo.  Introspectors look at a Bean class and determine
+ ** if there is a BeanInfo class with it.  If there is not a
+ ** BeanInfo class, it will behave as if the BeanInfo class
+ ** provided was a SimpleBeanInfo class (i.e. it will determine
+ ** all information automatically).<P>If there is a BeanInfo
+ ** class, then any methods that do *not* return null are
+ ** regarded as providing definitive information about the class
+ ** and all of its superclasses for those information types.
+ ** Even if a parent BeanInfo class explicitly returns that
+ ** information, it will not be used.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 28 Jul 1998
+ **/
+
+public interface BeanInfo {
+       /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+       public static int ICON_COLOR_16x16 = 1;
+       /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+       public static int ICON_COLOR_32x32 = 2;
+       /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+       public static int ICON_MONO_16x16 = 3;
+       /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+       public static int ICON_MONO_32x32 = 4;
+
+       /** Get the general description of this Bean type.
+        ** @return the BeanDescriptor for the Bean, or null if
+        **         the BeanDescriptor should be obtained by
+        **         Introspection.
+        **/
+       public abstract BeanDescriptor getBeanDescriptor();
+
+       /** Get the events this Bean type fires.
+        ** @return the EventDescriptors representing events this
+        **         Bean fires.  Returns <CODE>null</CODE> if the
+        **         events are to be acquired by Introspection.
+        **/
+       public abstract EventSetDescriptor[] getEventSetDescriptors();
+
+       /** Get the "default" event, basically the one a RAD tool
+        ** user is most likely to select.
+        ** @return the index into the getEventSetDescriptors()
+        **         that the user is most likely to use.  Returns
+        **         <CODE>-1</CODE> if there is no default event.
+        **/
+       public abstract int getDefaultEventIndex();
+
+       /** Get the properties (get/set method pairs) this Bean
+        ** type supports.
+        ** @return the PropertyDescriptors representing the
+        **         properties this Bean type supports.
+        **         Returns <CODE>null</CODE> if the properties
+        **         are to be obtained by Introspection.
+        **/
+       public abstract PropertyDescriptor[] getPropertyDescriptors();
+
+       /** Get the "default" property, basically the one a RAD
+        ** tool user is most likely to select.
+        ** @return the index into the getPropertyDescriptors()
+        **         that the user is most likely to use.  Returns
+        **         <CODE>-1</CODE> if there is no default event.
+        **/
+       public abstract int getDefaultPropertyIndex();
+
+       /** Get the methods this Bean type supports.
+        ** @return the MethodDescriptors representing the
+        **         methods this Bean type supports.  Returns
+        **         <CODE>null</CODE> if the methods are to be
+        **         obtained by Introspection.
+        **/
+       public abstract MethodDescriptor[] getMethodDescriptors();
+
+       /** Get additional BeanInfos representing this Bean.
+        ** In this version of JavaBeans, this method is used so
+        ** that space and time can be saved by reading a BeanInfo
+        ** for each class in the hierarchy (super, super(super),
+        ** and so on).<P>
+        **
+        ** The order of precedence when two pieces of BeanInfo
+        ** conflict (such as two PropertyDescriptors that have
+        ** the same name), in order from highest precedence to
+        ** lowest, is:
+        ** <OL>
+        ** <LI>This BeanInfo object.</LI>
+        ** <LI><CODE>getAdditionalBeanInfo()[getAdditionalBeanInfo().length]</CODE></LI>
+        ** <LI> ... </LI>
+        ** <LI><CODE>getAdditionalBeanInfo()[1]</CODE></LI>
+        ** <LI><CODE>getAdditionalBeanInfo()[0]</CODE></LI>
+        ** </OL><P>
+        **
+        ** <STRONG>Spec Note:</STRONG> It is possible that
+        ** returning <CODE>null</CODE> from this method could
+        ** stop Introspection in its tracks, but it is unclear
+        ** from the spec whether this is the case.
+        **
+        ** @return additional BeanInfos representing this Bean.
+        **         <CODE>null</CODE> may be returned (see Spec
+        **         Note, above).
+        **/
+       public abstract BeanInfo[] getAdditionalBeanInfo();
+
+       /** Get a visual icon for this Bean.
+        ** A Bean does not have to support icons, and if it does
+        ** support icons, it does not have to support every single
+        ** type.  Sun recommends that if you only support one
+        ** type, you support 16x16 color.  Sun also notes that you
+        ** should try to use a type (like GIF) that allows for
+        ** transparent pixels, so that the background of the RAD
+        ** tool can show through.<P>
+        **
+        ** <STRONG>Spec Note:</STRONG> If you do not support the
+        ** type of icon that is being asked for, but you do
+        ** support another type, it is unclear whether you should
+        ** return the other type or not.  I would presume not.
+        **
+        ** @param iconType the type of icon to get (see the
+        **        ICON_* constants in this class).
+        ** @return the icon, or null if that type of icon is
+        **         unsupported by this Bean.
+        **/
+       public abstract java.awt.Image getIcon(int iconType);
+}
diff --git a/libjava/java/beans/Beans.java b/libjava/java/beans/Beans.java
new file mode 100644 (file)
index 0000000..08e5623
--- /dev/null
@@ -0,0 +1,199 @@
+/* java.beans.Beans
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import java.io.*;
+// import java.applet.*;
+import gnu.java.io.*;
+
+/**
+ * <code>Beans</code> provides some helper methods that allow the basic operations of Bean-ness.
+ *
+ * @author John Keiser
+ * @since JDK1.1
+ * @version 1.1.0, 29 Jul 1998
+ *
+ */
+public class Beans {
+       static boolean designTime = false;
+       static boolean guiAvailable = true;
+
+
+       /**
+        * Once again, we have a java.beans class with only
+        * static methods that can be instantiated.  When
+        * will the madness end? :)
+        */
+       public Beans() {
+       }
+
+       /**
+        * Allows you to instantiate a Bean.  This method takes
+        * a ClassLoader from which to read the Bean and the
+        * name of the Bean.<P>
+        *
+        * The Bean name should be a dotted name, like a class.
+        * It can represent several things.  Beans will search
+        * for the Bean using the name like this:<P>
+        * <OL>
+        * <LI>Searches for a serialized instance of the Bean
+        * using getResource(), mangling the Bean name by
+        * replacing the dots with slashes and appending .ser
+        * (for example, gnu.beans.BlahDeBlah would cause
+        * Beans to search for gnu/beans/BlahDeBlah.ser using
+        * getResource()).</LI>
+        * <LI>Searches for the Bean class using the beanName,
+        * and then instantiates it with the no-arg constructor.
+        * At that point, if it is an Applet, it provides it
+        * with AppletContext and AppletStub, and then calls
+        * init().</LI>
+        * </OL>
+        * @param cl the ClassLoader to use, or <CODE>null</CODE>
+        *        to use the default ClassLoader.
+        * @param beanName the name of the Bean.
+        * @return the Bean.
+        * @XXX
+        */
+       public static Object instantiate(ClassLoader cl, String beanName) throws IOException, ClassNotFoundException {
+               Object bean;
+
+               InputStream serStream;
+               if(cl == null) {
+                       serStream = ClassLoader.getSystemResourceAsStream(beanName.replace('.','/')+".ser");
+               } else {
+                       serStream = cl.getResourceAsStream(beanName.replace('.','/')+".ser");
+               }
+               if(serStream != null) {
+                       if(cl == null) {
+                               ObjectInputStream ois = new ObjectInputStream(serStream);
+                               bean = ois.readObject();
+                       } else {
+                               ClassLoaderObjectInputStream ois = new ClassLoaderObjectInputStream(serStream, cl);
+                               bean = ois.readObject();
+                       }
+               } else if(cl == null) {
+                       Class beanClass = Class.forName(beanName);
+                       try {
+                               bean = beanClass.newInstance();
+                       } catch(IllegalAccessException E) {
+                               bean = null;
+                       } catch(InstantiationException E) {
+                               bean = null;
+                       }
+               } else {
+                       Class beanClass = cl.loadClass(beanName);
+                       try {
+                               bean = beanClass.newInstance();
+                       } catch(IllegalAccessException E) {
+                               bean = null;
+                       } catch(InstantiationException E) {
+                               bean = null;
+                       }
+               }
+
+/* FIXME - Turned off since java.applet doesn't exist for libgcj.
+ * FIXME               if(bean instanceof Applet) {
+ * FIXME                       Applet a = (Applet)bean;
+ * FIXME                       //a.setAppletContext(???);
+ * FIXME                       //a.setStub(???);
+ * FIXME                       if(serStream == null) {
+ * FIXME                               a.init();
+ * FIXME                       }
+ * FIXME               }
+ * FIXME ********************************************************/
+
+               return bean;
+       }
+
+       /**
+        * Get the Bean as a different class type.
+        * This should be used instead of casting to get a new
+        * type view of a Bean, because in the future there may
+        * be new types of Bean, even Beans spanning multiple
+        * Objects.
+        * @param bean the Bean to cast.
+        * @param newClass the Class to cast it to.
+        * @return the Bean as a new view, or if the operation
+        *         could not be performed, the Bean itself.
+        */
+       public static Object getInstanceOf(Object bean, Class newClass) {
+               return bean;
+       }
+
+       /**
+        * Determine whether the Bean can be cast to a different
+        * class type.
+        * This should be used instead of instanceof to determine
+        * a Bean's castability, because in the future there may
+        * be new types of Bean, even Beans spanning multiple
+        * Objects.
+        * @param bean the Bean to cast.
+        * @param newClass the Class to cast it to.
+        * @return whether the Bean can be cast to the class type
+        *         in question.
+        */
+       public static boolean isInstanceOf(Object bean, Class newBeanClass) {
+               return newBeanClass.isInstance(bean);
+       }
+
+       /**
+        * Find out whether the GUI is available to use.
+        * Defaults to true.
+        * @return whether the GUI is available to use.
+        */
+       public static boolean isGuiAvailable() {
+               return guiAvailable;
+       }
+
+       /**
+        * Find out whether it is design time.  Design time means
+        * we are in a RAD tool.
+        * Defaults to false.
+        * @return whether it is design time.
+        */
+       public static boolean isDesignTime() {
+               return designTime;
+       }
+
+       /**
+        * Set whether the GUI is available to use.
+        * @param guiAvailable whether the GUI is available to use.
+        */
+       public static void setGuiAvailable(boolean guiAvailable) throws SecurityException {
+               Beans.guiAvailable = guiAvailable;
+       }
+
+       /**
+        * Set whether it is design time.  Design time means we
+        * are in a RAD tool.
+        * @param designTime whether it is design time.
+        */
+       public static void setDesignTime(boolean designTime) throws SecurityException {
+               Beans.designTime = designTime;
+       }
+}
diff --git a/libjava/java/beans/Customizer.java b/libjava/java/beans/Customizer.java
new file mode 100644 (file)
index 0000000..1fecd4f
--- /dev/null
@@ -0,0 +1,75 @@
+/* java.beans.Customizer
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** You may explicitly provide a Customizer for your Bean
+ ** class, which allows you complete control of the editing
+ ** of the Bean.<P>
+ **
+ ** A Customizer is meant to be embedded in an RAD tool,
+ ** and thus must be a descendant of <CODE>java.awt.Component</CODE>.<P>
+ **
+ ** It must also have a constructor with no arguments.  This
+ ** is the constructor that will be called by the RAD tool to
+ ** instantiate the Customizer.<P>
+ **
+ ** Over its lifetime, an instance of a Customizer will only
+ ** customize one single Bean.  A new instance of the
+ ** Customizer will be instantiated to edit any other Beans.<P>
+ **
+ ** The Customizer is responsible for notifying its
+ ** PropertyChangeListeners of any changes that are made,
+ ** according to the rules of PropertyChangeListeners (i.e.
+ ** notify the clients <EM>after</EM> the property has
+ ** changed).
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ ** @see java.beans.BeanDescriptor.getCustomizerClass()
+ **/
+
+public interface Customizer {
+       /** Set the object to Customize.  This will always be a
+        ** Bean that had a BeanDescriptor indicating this
+        ** Customizer.
+        ** @param bean the Bean to customize.
+        **/
+       public abstract void setObject(Object bean);
+
+       /** Add a PropertyChangeListener.
+        ** @param l the PropertyChangeListener to add.
+        **/
+       public abstract void addPropertyChangeListener(PropertyChangeListener l);
+
+       /** Remove a PropertyChangeListener.
+        ** @param l the PropertyChangeListener to remove.
+        **/
+       public abstract void removePropertyChangeListener(PropertyChangeListener l);
+}
diff --git a/libjava/java/beans/DesignMode.java b/libjava/java/beans/DesignMode.java
new file mode 100644 (file)
index 0000000..b7782f9
--- /dev/null
@@ -0,0 +1,82 @@
+/* java.beans.DesignMode
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ * <code>BeanContextChild</code> implementors implement this to get information about whether they are in a design time or runtime environment.
+ * The reason this is restricted to <code>BeanContextChild</code>ren is that
+ * only things in the <code>BeanContext</code> hierarchy are given this
+ * information in the first place.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextChild
+ */
+
+public interface DesignMode {
+       /**
+        * Use this name when firing <code>PropertyChangeEvent</code>s from your Bean.  
+        * @fixme Check whether PROPERTYNAME is set to same value as Sun.
+        */
+       public static final String PROPERTYNAME = "designTime";
+
+       /**
+        * The environment will call this method on your
+        * <code>BeanContextChild</code> when it is registered in a parent
+        * <code>BeanContext</code> or when behavior needs to switch from
+        * design time to runtime behavior (or vice versa).
+        * <P>
+        *
+        * <code>BeanContext</code>s are required to fire
+        * <code>PropertyChangeEvent</code>s when properties change.
+        * <code>designTime</code> is a property, and therefore when you
+        * implement <code>setDesignTime()</code>, you need to fire a
+        * <code>PropertyChangeEvent</code> with the old value, the new
+        * value and using <code>PROPERTYNAME</code> as the property name.
+        *
+        * @param designTime the new value of design time,
+        *        <code>true</code> if it is design time,
+        *        <code>false</code> if it is runtime.
+        *
+        * @fixme I'm frankly not really sure whether it's the case that
+        *        the BeanContext can <em>change</em> the status of the Bean from
+        *        design time to runtime.  But it appears that it may be so.
+        *
+        * @see java.util.PropertyChangeEvent
+        * @see java.beans.beancontext.BeanContext
+        * @see #PROPERTYNAME
+        */
+       public void setDesignTime(boolean designTime);
+
+       /**
+        * This method should tell whether it is design time or runtime.
+        * @return <code>true</code> if design time, <code>false</code> if
+        *         runtime.
+        */
+       public boolean isDesignTime();
+}
diff --git a/libjava/java/beans/EventSetDescriptor.java b/libjava/java/beans/EventSetDescriptor.java
new file mode 100644 (file)
index 0000000..c0840fe
--- /dev/null
@@ -0,0 +1,429 @@
+/* java.beans.EventSetDescriptor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import java.util.*;
+import java.lang.reflect.*;
+import gnu.java.lang.*;
+
+/**
+ ** EventSetDescriptor describes the hookup between an event source
+ ** class and an event listener class.
+ **
+ ** EventSets have several attributes: the listener class, the events
+ ** that can be fired to the listener (methods in the listener class), and
+ ** an add and remove listener method from the event firer's class.<P>
+ **
+ ** The methods have these constraints on them:<P>
+ ** <UL>
+ ** <LI>event firing methods: must have <CODE>void</CODE> return value.  Any
+ ** parameters and exceptions are allowed.  May be public, protected or
+ ** package-protected. (Don't ask me why that is, I'm just following the spec.
+ ** The only place it is even mentioned is in the Java Beans white paper, and
+ ** there it is only implied.)</LI>
+ ** <LI>add listener method: must have <CODE>void</CODE> return value.  Must
+ ** take exactly one argument, of the listener class's type.  May fire either
+ ** zero exceptions, or one exception of type <CODE>java.util.TooManyListenersException</CODE>.
+ ** Must be public.</LI>
+ ** <LI>remove listener method: must have <CODE>void</CODE> return value.
+ ** Must take exactly one argument, of the listener class's type.  May not
+ ** fire any exceptions.  Must be public.</LI>
+ ** </UL>
+ **
+ ** A final constraint is that event listener classes must extend from EventListener.<P>
+ **
+ ** There are also various design patterns associated with some of the methods
+ ** of construction. Those are explained in more detail in the appropriate
+ ** constructors.<P>
+ **
+ ** <STRONG>Documentation Convention:</STRONG> for proper
+ ** Internalization of Beans inside an RAD tool, sometimes there
+ ** are two names for a property or method: a programmatic, or
+ ** locale-independent name, which can be used anywhere, and a
+ ** localized, display name, for ease of use.  In the
+ ** documentation I will specify different String values as
+ ** either <EM>programmatic</EM> or <EM>localized</EM> to
+ ** make this distinction clear.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 31 May 1998
+ **/
+
+public class EventSetDescriptor extends FeatureDescriptor {
+       private Method addListenerMethod;
+       private Method removeListenerMethod;
+       private Class listenerType;
+       private MethodDescriptor[] listenerMethodDescriptors;
+       private Method[] listenerMethods;
+
+       private boolean unicast;
+       private boolean inDefaultEventSet = true;
+
+       /** Create a new EventSetDescriptor.
+        ** This version of the constructor enforces the rules imposed on the methods
+        ** described at the top of this class, as well as searching for:<P>
+        ** <OL>
+        ** <LI>The event-firing method must be non-private with signature
+        ** <CODE>void &lt;listenerMethodName&gt;(&lt;eventSetName&gt;Event)</CODE>
+        ** (where <CODE>&lt;eventSetName&gt;</CODE> has its first character capitalized
+        ** by the constructor and the Event is a descendant of
+        ** <CODE>java.util.EventObject</CODE>) in class <CODE>listenerType</CODE>
+        ** (any exceptions may be thrown).
+        ** <B>Implementation note:</B> Note that there could conceivably be multiple
+        ** methods with this type of signature (example: java.util.MouseEvent vs.
+        ** my.very.own.MouseEvent).  In this implementation, all methods fitting the
+        ** description will be put into the <CODE>EventSetDescriptor</CODE>, even
+        ** though the spec says only one should be chosen (they probably weren't thinking as
+        ** pathologically as I was).  I don't like arbitrarily choosing things.
+        ** If your class has only one such signature, as most do, you'll have no problems.</LI>
+        ** <LI>The add and remove methods must be public and named
+        ** <CODE>void add&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> and
+        ** <CODE>void remove&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> in
+        ** in class <CODE>eventSourceClass</CODE>, where
+        ** <CODE>&lt;eventSetName&gt;</CODE> will have its first letter capitalized.
+        ** Standard exception rules (see class description) apply.</LI>
+        ** </OL>
+        ** @param eventSourceClass the class containing the add/remove listener methods.
+        ** @param eventSetName the programmatic name of the event set, generally starting
+        ** with a lowercase letter (i.e. fooManChu instead of FooManChu).  This will be used
+        ** to generate the name of the event object as well as the names of the add and
+        ** remove methods.
+        ** @param listenerType the class containing the event firing method.
+        ** @param listenerMethodName the name of the event firing method.
+        ** @exception IntrospectionException if listenerType is not an EventListener,
+        **                                   or if methods are not found or are invalid.
+        **/
+       public EventSetDescriptor(Class  eventSourceClass,
+                                 String eventSetName,
+                                 Class  listenerType,
+                                 String listenerMethodName) throws IntrospectionException {
+               setName(eventSetName);
+               if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+                       throw new IntrospectionException("Listener type is not an EventListener.");
+               }
+
+               String[] names = new String[1];
+               names[0] = listenerMethodName;
+
+               try {
+                       eventSetName = Character.toUpperCase(eventSetName.charAt(0)) + eventSetName.substring(1);
+               } catch(StringIndexOutOfBoundsException e) {
+                       eventSetName = "";
+               }
+
+               findMethods(eventSourceClass,listenerType,names,"add"+eventSetName+"Listener","remove"+eventSetName+"Listener",eventSetName+"Event");
+               this.listenerType = listenerType;
+               checkAddListenerUnicast();
+               if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+                       throw new IntrospectionException("Listener remove method throws exceptions.");
+               }
+       }
+
+       /** Create a new EventSetDescriptor.
+        ** This form of the constructor allows you to specify the names of the methods and adds
+        ** no new constraints on top of the rules already described at the top of the class.<P>
+        ** 
+        ** @param eventSourceClass the class containing the add and remove listener methods.
+        ** @param eventSetName the programmatic name of the event set, generally starting
+        ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+        ** @param listenerType the class containing the event firing methods.
+        ** @param listenerMethodNames the names of the even firing methods.
+        ** @param addListenerMethodName the name of the add listener method.
+        ** @param removeListenerMethodName the name of the remove listener method.
+        ** @exception IntrospectionException if listenerType is not an EventListener
+        **                                   or if methods are not found or are invalid.
+        **/
+       public EventSetDescriptor(Class eventSourceClass,
+                                  String eventSetName,
+                                  Class listenerType,
+                                  String[] listenerMethodNames,
+                                  String addListenerMethodName,
+                                  String removeListenerMethodName) throws IntrospectionException {
+               setName(eventSetName);
+               if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+                       throw new IntrospectionException("Listener type is not an EventListener.");
+               }
+
+               findMethods(eventSourceClass,listenerType,listenerMethodNames,addListenerMethodName,removeListenerMethodName,null);
+               this.listenerType = listenerType;
+               checkAddListenerUnicast();
+               if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+                       throw new IntrospectionException("Listener remove method throws exceptions.");
+               }
+       }
+
+       /** Create a new EventSetDescriptor.
+        ** This form of constructor allows you to explicitly say which methods do what, and
+        ** no reflection is done by the EventSetDescriptor.  The methods are, however,
+        ** checked to ensure that they follow the rules set forth at the top of the class.
+        ** @param eventSetName the programmatic name of the event set, generally starting
+        ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+        ** @param listenerType the class containing the listenerMethods.
+        ** @param listenerMethods the event firing methods.
+        ** @param addListenerMethod the add listener method.
+        ** @param removeListenerMethod the remove listener method.
+        ** @exception IntrospectionException if the listenerType is not an EventListener,
+        **                                   or any of the methods are invalid.
+        **/
+       public EventSetDescriptor(String eventSetName,
+                                  Class listenerType,
+                                  Method[] listenerMethods,
+                                  Method addListenerMethod,
+                                  Method removeListenerMethod) throws IntrospectionException {
+               setName(eventSetName);
+               if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+                       throw new IntrospectionException("Listener type is not an EventListener.");
+               }
+
+               this.listenerMethods = listenerMethods;
+               this.addListenerMethod = addListenerMethod;
+               this.removeListenerMethod = removeListenerMethod;
+               this.listenerType = listenerType;
+               checkMethods();
+               checkAddListenerUnicast();
+               if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+                       throw new IntrospectionException("Listener remove method throws exceptions.");
+               }
+       }
+
+       /** Create a new EventSetDescriptor.
+        ** This form of constructor allows you to explicitly say which methods do what, and
+        ** no reflection is done by the EventSetDescriptor.  The methods are, however,
+        ** checked to ensure that they follow the rules set forth at the top of the class.
+        ** @param eventSetName the programmatic name of the event set, generally starting
+        ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+        ** @param listenerType the class containing the listenerMethods.
+        ** @param listenerMethodDescriptors the event firing methods.
+        ** @param addListenerMethod the add listener method.
+        ** @param removeListenerMethod the remove listener method.
+        ** @exception IntrospectionException if the listenerType is not an EventListener,
+        **                                   or any of the methods are invalid.
+        **/
+       public EventSetDescriptor(String eventSetName,
+                                  Class listenerType,
+                                  MethodDescriptor[] listenerMethodDescriptors,
+                                  Method addListenerMethod,
+                                  Method removeListenerMethod) throws IntrospectionException {
+               setName(eventSetName);
+               if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+                       throw new IntrospectionException("Listener type is not an EventListener.");
+               }
+
+               this.listenerMethodDescriptors = listenerMethodDescriptors;
+               this.listenerMethods = new Method[listenerMethodDescriptors.length];
+               for(int i=0;i<this.listenerMethodDescriptors.length;i++) {
+                       this.listenerMethods[i] = this.listenerMethodDescriptors[i].getMethod();
+               }
+
+               this.addListenerMethod = addListenerMethod;
+               this.removeListenerMethod = removeListenerMethod;
+               this.listenerType = listenerType;
+               checkMethods();
+               checkAddListenerUnicast();
+               if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+                       throw new IntrospectionException("Listener remove method throws exceptions.");
+               }
+       }
+
+       /** Get the class that contains the event firing methods. **/
+       public Class getListenerType() {
+               return listenerType;
+       }
+
+       /** Get the event firing methods. **/
+       public Method[] getListenerMethods() {
+               return listenerMethods;
+       }
+
+       /** Get the event firing methods as MethodDescriptors. **/
+       public MethodDescriptor[] getListenerMethodDescriptors() {
+               if(listenerMethodDescriptors == null) {
+                       listenerMethodDescriptors = new MethodDescriptor[listenerMethods.length];
+                       for(int i=0;i<listenerMethods.length;i++) {
+                               listenerMethodDescriptors[i] = new MethodDescriptor(listenerMethods[i]);
+                       }
+               }
+               return listenerMethodDescriptors;
+       }
+
+       /** Get the add listener method. **/
+       public Method getAddListenerMethod() {
+               return addListenerMethod;
+       }
+
+       /** Get the remove listener method. **/
+       public Method getRemoveListenerMethod() {
+               return removeListenerMethod;
+       }
+
+       /** Set whether or not multiple listeners may be added.
+        ** @param unicast whether or not multiple listeners may be added.
+        **/
+       public void setUnicast(boolean unicast) {
+               this.unicast = unicast;
+       }
+
+       /** Get whether or not multiple listeners may be added.  (Defaults to false.) **/
+       public boolean isUnicast() {
+               return unicast;
+       }
+
+       /** Set whether or not this is in the default event set.
+        ** @param inDefaultEventSet whether this is in the default event set.
+        **/
+       public void setInDefaultEventSet(boolean inDefaultEventSet) {
+               this.inDefaultEventSet = inDefaultEventSet;
+       }
+
+       /** Get whether or not this is in the default event set.  (Defaults to true.)**/
+       public boolean isInDefaultEventSet() {
+               return inDefaultEventSet;
+       }
+
+       private void checkAddListenerUnicast() throws IntrospectionException {
+               Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
+               if(addListenerExceptions.length > 1) {
+                       throw new IntrospectionException("Listener add method throws too many exceptions.");
+               } else if(addListenerExceptions.length == 1
+                         && !java.util.TooManyListenersException.class.isAssignableFrom(addListenerExceptions[0])) {
+                       throw new IntrospectionException("Listener add method throws too many exceptions.");
+               }
+       }
+
+       private void checkMethods() throws IntrospectionException {
+               if(!addListenerMethod.getDeclaringClass().isAssignableFrom(removeListenerMethod.getDeclaringClass())
+                  && !removeListenerMethod.getDeclaringClass().isAssignableFrom(addListenerMethod.getDeclaringClass())) {
+                       throw new IntrospectionException("add and remove listener methods do not come from the same class.  This is bad.");
+               }
+               if(!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
+                   || addListenerMethod.getParameterTypes().length != 1
+                  || !listenerType.equals(addListenerMethod.getParameterTypes()[0])
+                  || !Modifier.isPublic(addListenerMethod.getModifiers())) {
+                       throw new IntrospectionException("Add Listener Method invalid.");
+               }
+               if(!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
+                   || removeListenerMethod.getParameterTypes().length != 1
+                  || !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
+                  || removeListenerMethod.getExceptionTypes().length > 0
+                  || !Modifier.isPublic(removeListenerMethod.getModifiers())) {
+                       throw new IntrospectionException("Remove Listener Method invalid.");
+               }
+
+               for(int i=0;i<listenerMethods.length;i++) {
+                       if(!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
+                          || Modifier.isPrivate(listenerMethods[i].getModifiers())) {
+                               throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " non-void or private.");
+                       }
+                       if(!listenerMethods[i].getDeclaringClass().isAssignableFrom(listenerType)) {
+                               throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " not from class " + listenerType.getName());
+                       }
+               }
+       }
+
+       private void findMethods(Class eventSourceClass,
+               Class listenerType,
+               String listenerMethodNames[],
+               String addListenerMethodName,
+               String removeListenerMethodName,
+               String absurdEventClassCheckName) throws IntrospectionException {
+
+               /* Find add listener method and remove listener method. */
+               Class[] listenerArgList = new Class[1];
+               listenerArgList[0] = listenerType;
+               try {
+                       this.addListenerMethod = eventSourceClass.getMethod(addListenerMethodName,listenerArgList);
+               } catch(SecurityException E) {
+                       throw new IntrospectionException("SecurityException trying to access method " + addListenerMethodName + ".");
+               } catch(NoSuchMethodException E) {
+                       throw new IntrospectionException("Could not find method " + addListenerMethodName + ".");
+               }
+
+               if(this.addListenerMethod == null || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+                       throw new IntrospectionException("Add listener method does not exist, is not public, or is not void.");
+               }
+
+               try {
+                       this.removeListenerMethod = eventSourceClass.getMethod(removeListenerMethodName,listenerArgList);
+               } catch(SecurityException E) {
+                       throw new IntrospectionException("SecurityException trying to access method " + removeListenerMethodName + ".");
+               } catch(NoSuchMethodException E) {
+                       throw new IntrospectionException("Could not find method " + removeListenerMethodName + ".");
+               }
+               if(this.removeListenerMethod == null || !this.removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+                       throw new IntrospectionException("Remove listener method does not exist, is not public, or is not void.");
+               }
+
+               /* Find the listener methods. */
+               Method[] methods;
+               try {
+                       methods = ClassHelper.getAllMethods(listenerType);
+               } catch(SecurityException E) {
+                       throw new IntrospectionException("Security: You cannot access fields in this class.");
+               }
+
+               Vector chosenMethods = new Vector();
+               boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
+               for(int i=0;i<methods.length;i++) {
+                       if(Modifier.isPrivate(methods[i].getModifiers())) {
+                               continue;
+                       }
+                       Method currentMethod = methods[i];
+                       Class retval = currentMethod.getReturnType();
+                       if(retval.equals(java.lang.Void.TYPE)) {
+                               for(int j=0;j<listenerMethodNames.length;j++) {
+                                       if(currentMethod.getName().equals(listenerMethodNames[j])
+                                          && (absurdEventClassCheckName == null
+                                              || (currentMethod.getParameterTypes().length == 1
+                                                  && ((currentMethod.getParameterTypes()[0]).getName().equals(absurdEventClassCheckName)
+                                                      || (currentMethod.getParameterTypes()[0]).getName().endsWith("."+absurdEventClassCheckName)
+                                                     )
+                                                 )
+                                             )
+                                         ) {
+                                               chosenMethods.addElement(currentMethod);
+                                               listenerMethodFound[j] = true;
+                                       }
+                               }
+                       }
+               }
+
+               /* Make sure we found all the methods we were looking for. */
+               for(int i=0;i<listenerMethodFound.length;i++) {
+                       if(!listenerMethodFound[i]) {
+                               throw new IntrospectionException("Could not find event method " + listenerMethodNames[i]);
+                       }
+               }
+
+               /* Now that we've chosen the listener methods we want, store them. */
+               this.listenerMethods = new Method[chosenMethods.size()];
+               for(int i=0;i<chosenMethods.size();i++) {
+                       this.listenerMethods[i] = (Method)chosenMethods.elementAt(i);
+               }
+       }
+}
diff --git a/libjava/java/beans/FeatureDescriptor.java b/libjava/java/beans/FeatureDescriptor.java
new file mode 100644 (file)
index 0000000..102a3a3
--- /dev/null
@@ -0,0 +1,155 @@
+/* java.beans.FeatureDescriptor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import java.util.*;
+
+/**
+ ** FeatureDescriptor is the common superclass for all JavaBeans Descriptor classes.
+ ** JavaBeans descriptors are abstract descriptors of properties,
+ ** events, methods, beans, etc.<P>
+ **
+ ** <STRONG>Documentation Convention:</STRONG> for proper
+ ** Internalization of Beans inside an RAD tool, sometimes there
+ ** are two names for a property or method: a programmatic, or
+ ** locale-independent name, which can be used anywhere, and a
+ ** localized, display name, for ease of use.  In the
+ ** documentation I will specify different String values as
+ ** either <EM>programmatic</EM> or <EM>localized</EM> to
+ ** make this distinction clear.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 31 May 1998
+ **/
+
+public class FeatureDescriptor {
+       String name;
+       String displayName;
+       String shortDescription;
+       boolean expert;
+       boolean hidden;
+
+       Hashtable valueHash;
+
+       /** Instantiate this FeatureDescriptor with appropriate default values.**/
+       public FeatureDescriptor() {
+               valueHash = new Hashtable();
+       }
+
+       /** Get the programmatic name of this feature. **/
+       public String getName() {
+               return name;
+       }
+
+       /** Set the programmatic name of this feature.
+        ** @param name the new name for this feature.
+        **/
+       public void setName(String name) {
+               this.name = name;
+       }
+
+       /** Get the localized (display) name of this feature. **/
+       public String getDisplayName() {
+               return displayName;
+       }
+
+       /** Set the localized (display) name of this feature.
+        ** @param displayName the new display name for this feature.
+        **/
+       public void setDisplayName(String displayName) {
+               this.displayName = displayName;
+       }
+
+       /** Get the localized short description for this feature. **/
+       public String getShortDescription() {
+               return shortDescription;
+       }
+
+       /** Set the localized short description for this feature.
+        ** @param shortDescription the new short description for this feature.
+        **/
+       public void setShortDescription(String shortDescription) {
+               this.shortDescription = shortDescription;
+       }
+
+       /** Indicates whether this feature is for expert use only.
+        ** @return true if for use by experts only, or false if anyone can use it.
+        **/
+       public boolean isExpert() {
+               return expert;
+       }
+
+       /** Set whether this feature is for expert use only.
+        ** @param expert true if for use by experts only, or false if anyone can use it.
+        **/
+       public void setExpert(boolean expert) {
+               this.expert = expert;
+       }
+
+       /** Indicates whether this feature is for use by tools only.
+        ** If it is for use by tools only, then it should not be displayed.
+        ** @return true if tools only should use it, or false if anyone can see it.
+        **/
+       public boolean isHidden() {
+               return hidden;
+       }
+
+       /** Set whether this feature is for use by tools only.
+        ** If it is for use by tools only, then it should not be displayed.
+        ** @param hidden true if tools only should use it, or false if anyone can see it.
+        **/
+       public void setHidden(boolean hidden) {
+               this.hidden = hidden;
+       }
+
+
+       /** Get an arbitrary value set with setValue().
+        ** @param name the programmatic name of the key.
+        ** @return the value associated with this name, or null if there is none.
+        **/
+       public Object getValue(String name) {
+               return valueHash.get(name);
+       }
+
+       /** Set an arbitrary string-value pair with this feature.
+        ** @param name the programmatic name of the key.
+        ** @param value the value to associate with the name.
+        **/
+       public void setValue(String name, Object value) {
+               valueHash.put(name, value);
+       }
+
+       /** Get a list of the programmatic key names set with setValue().
+        ** @return an Enumerator over all the programmatic key names associated
+        ** with this feature.
+        **/
+       public Enumeration attributeNames() {
+               return valueHash.keys();
+       }
+}
diff --git a/libjava/java/beans/IndexedPropertyDescriptor.java b/libjava/java/beans/IndexedPropertyDescriptor.java
new file mode 100644 (file)
index 0000000..daf8441
--- /dev/null
@@ -0,0 +1,296 @@
+/* java.beans.IndexedPropertyDescriptor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import java.util.*;
+import java.lang.reflect.*;
+
+/**
+ ** IndexedPropertyDescriptor describes information about a JavaBean
+ ** indexed property, by which we mean an array-like property that
+ ** has been exposed via a pair of get and set methods and another
+ ** pair that allows you to get to the property by an index.<P>
+ **
+ ** An example property would have four methods like this:<P>
+ ** <CODE>FooBar[] getFoo()</CODE><BR>
+ ** <CODE>void setFoo(FooBar[])</CODE><BR>
+ ** <CODE>FooBar getFoo(int)</CODE><BR>
+ ** <CODE>void setFoo(int,FooBar)</CODE><P>
+ **
+ ** The constraints put on get and set methods are:<P>
+ ** <OL>
+ ** <LI>There must be at least a get(int) or a set(int,...) method.
+ ** Nothing else is required.  <B>Spec note:</B>One nice restriction
+ ** would be that if there is a get() there must be a get(int), same
+ ** with set, but that is not in the spec and is fairly harmless.)</LI>
+ ** <LI>A get array method must have signature
+ **     <CODE>&lt;propertyType&gt;[] &lt;getMethodName&gt;()</CODE></LI>
+ ** <LI>A set array method must have signature
+ **     <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;[])</CODE></LI>
+ ** <LI>A get index method must have signature
+ **     <CODE>&lt;propertyType&gt; &lt;getMethodName&gt;(int)</CODE></LI>
+ ** <LI>A set index method must have signature
+ **     <CODE>void &lt;setMethodName&gt;(int,&lt;propertyType&gt;)</CODE></LI>
+ ** <LI>All these methods may throw any exception.</LI>
+ ** <LI>All these methods must be public.</LI>
+ ** </OL>
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+
+public class IndexedPropertyDescriptor extends PropertyDescriptor {
+       private Class indexedPropertyType;
+       private Method setIndex;
+       private Method getIndex;
+
+       /** Create a new IndexedPropertyDescriptor by introspection.
+        ** This form of constructor creates the PropertyDescriptor by
+        ** looking for getter methods named <CODE>get&lt;name&gt;()</CODE>
+        ** and setter methods named
+        ** <CODE>set&lt;name&gt;()</CODE> in class
+        ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
+        ** first letter capitalized by the constructor.<P>
+        **
+        ** <B>Implementation note:</B> If there is a get(int) method,
+        ** then the return type of that method is used to find the
+        ** remaining methods.  If there is no get method, then the
+        ** set(int) method is searched for exhaustively and that type
+        ** is used to find the others.<P>
+        **
+        ** <B>Spec note:</B>
+        ** If there is no get(int) method and multiple set(int) methods with
+        ** the same name and the correct parameters (different type of course),
+        ** then an IntrospectionException is thrown.  While Sun's spec
+        ** does not state this, it can make Bean behavior different on
+        ** different systems (since method order is not guaranteed) and as
+        ** such, can be treated as a bug in the spec.  I am not aware of
+        ** whether Sun's implementation catches this.
+        **
+        ** @param name the programmatic name of the property, usually
+        **             starting with a lowercase letter (e.g. fooManChu
+        **             instead of FooManChu).
+        ** @param beanClass the class the get and set methods live in.
+        ** @exception IntrospectionException if the methods are not found or invalid.
+        **/
+       public IndexedPropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
+               super(name);
+               String capitalized;
+               try {
+                       capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+               } catch(StringIndexOutOfBoundsException e) {
+                       capitalized = "";
+               }
+               findMethods(beanClass, "get" + capitalized, "set" + capitalized, "get" + capitalized, "set" + capitalized);
+       }
+
+       /** Create a new IndexedPropertyDescriptor by introspection.
+        ** This form of constructor allows you to specify the
+        ** names of the get and set methods to search for.<P>
+        **
+        ** <B>Implementation note:</B> If there is a get(int) method,
+        ** then the return type of that method is used to find the
+        ** remaining methods.  If there is no get method, then the
+        ** set(int) method is searched for exhaustively and that type
+        ** is used to find the others.<P>
+        **
+        ** <B>Spec note:</B>
+        ** If there is no get(int) method and multiple set(int) methods with
+        ** the same name and the correct parameters (different type of course),
+        ** then an IntrospectionException is thrown.  While Sun's spec
+        ** does not state this, it can make Bean behavior different on
+        ** different systems (since method order is not guaranteed) and as
+        ** such, can be treated as a bug in the spec.  I am not aware of
+        ** whether Sun's implementation catches this.
+        **
+        ** @param name the programmatic name of the property, usually
+        **             starting with a lowercase letter (e.g. fooManChu
+        **             instead of FooManChu).
+        ** @param beanClass the class the get and set methods live in.
+        ** @param getMethodName the name of the get array method.
+        ** @param setMethodName the name of the set array method.
+        ** @param getIndexName the name of the get index method.
+        ** @param setIndexName the name of the set index method.
+        ** @exception IntrospectionException if the methods are not found or invalid.
+        **/
+       public IndexedPropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
+               super(name);
+               findMethods(beanClass, getMethodName, setMethodName, getIndexName, setIndexName);
+       }
+
+       /** Create a new PropertyDescriptor using explicit Methods.
+        ** Note that the methods will be checked for conformance to standard
+        ** Property method rules, as described above at the top of this class.
+        ** 
+        ** @param name the programmatic name of the property, usually
+        **             starting with a lowercase letter (e.g. fooManChu
+        **             instead of FooManChu).
+        ** @param getMethod the get array method.
+        ** @param setMethod the set array method.
+        ** @param getIndex the get index method.
+        ** @param setIndex the set index method.
+        ** @exception IntrospectionException if the methods are not found or invalid.
+        **/
+       public IndexedPropertyDescriptor(String name, Method getMethod, Method setMethod, Method getIndex, Method setIndex) throws IntrospectionException {
+               super(name);
+               if(getMethod != null && getMethod.getParameterTypes().length > 0) {
+                       throw new IntrospectionException("get method has parameters");
+               }
+               if(getMethod != null && setMethod.getParameterTypes().length != 1) {
+                       throw new IntrospectionException("set method does not have exactly one parameter");
+               }
+               if(getMethod != null && setMethod != null) {
+                       if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
+                               throw new IntrospectionException("set and get methods do not share the same type");
+                       }
+                       if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
+                          && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
+                               throw new IntrospectionException("set and get methods are not in the same class.");
+                       }
+               }
+
+               if(getIndex != null && (getIndex.getParameterTypes().length != 1
+                  || !(getIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
+                       throw new IntrospectionException("get index method has wrong parameters");
+               }
+               if(setIndex != null && (setIndex.getParameterTypes().length != 2
+                  || !(setIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
+                       throw new IntrospectionException("set index method has wrong parameters");
+               }
+               if(getIndex != null && setIndex != null) {
+                       if(!getIndex.getReturnType().equals(setIndex.getParameterTypes()[1])) {
+                               throw new IntrospectionException("set index methods do not share the same type");
+                       }
+                       if(!getIndex.getDeclaringClass().isAssignableFrom(setIndex.getDeclaringClass())
+                          && !setIndex.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
+                               throw new IntrospectionException("get and set index methods are not in the same class.");
+                       }
+               }
+
+               if(getIndex != null && getMethod != null && !getIndex.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())
+                  && !getMethod.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
+                       throw new IntrospectionException("methods are not in the same class.");
+               }
+
+               if(getIndex != null && getMethod != null && !Array.newInstance(getIndex.getReturnType(),0).getClass().equals(getMethod.getReturnType())) {
+                       throw new IntrospectionException("array methods do not match index methods.");
+               }
+
+               this.getMethod = getMethod;
+               this.setMethod = setMethod;
+               this.getIndex = getIndex;
+               this.setIndex = getIndex;
+               this.indexedPropertyType = getIndex != null ? getIndex.getReturnType() : setIndex.getParameterTypes()[1];
+               this.propertyType = getMethod != null ? getMethod.getReturnType() : (setMethod != null ? setMethod.getParameterTypes()[0] : Array.newInstance(this.indexedPropertyType,0).getClass());
+       }
+
+       public Class getIndexedPropertyType() {
+               return indexedPropertyType;
+       }
+
+       public Method getIndexedReadMethod() {
+               return getIndex;
+       }
+
+       public Method getIndexedWriteMethod() {
+               return setIndex;
+       }
+
+       private void findMethods(Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
+               try {
+                       if(getIndexName != null) {
+                               try {
+                                       Class[] getArgs = new Class[1];
+                                       getArgs[0] = java.lang.Integer.TYPE;
+                                       getIndex = beanClass.getMethod(getIndexName,getArgs);
+                                       indexedPropertyType = getIndex.getReturnType();
+                               } catch(NoSuchMethodException E) {
+                               }
+                       }
+                       if(getIndex != null) {
+                               if(setIndexName != null) {
+                                       try {
+                                               Class[] setArgs = new Class[2];
+                                               setArgs[0] = java.lang.Integer.TYPE;
+                                               setArgs[1] = indexedPropertyType;
+                                               setIndex = beanClass.getMethod(setIndexName,setArgs);
+                                               if(!setIndex.getReturnType().equals(java.lang.Void.TYPE)) {
+                                                       throw new IntrospectionException(setIndexName + " has non-void return type");
+                                               }
+                                       } catch(NoSuchMethodException E) {
+                                       }
+                               }
+                       } else if(setIndexName != null) {
+                               Method[] m = beanClass.getMethods();
+                               for(int i=0;i<m.length;i++) {
+                                       Method current = m[i];
+                                       if(current.getName().equals(setIndexName)
+                                          && current.getParameterTypes().length == 2
+                                          && (current.getParameterTypes()[0]).equals(java.lang.Integer.TYPE)
+                                          && current.getReturnType().equals(java.lang.Void.TYPE)) {
+                                               if(setIndex != null) {
+                                                       throw new IntrospectionException("Multiple, different set methods found that fit the bill!");
+                                               } else {
+                                                       setIndex = current;
+                                                       indexedPropertyType = current.getParameterTypes()[1];
+                                               }
+                                       }
+                               }
+                               if(setIndex == null) {
+                                       throw new IntrospectionException("Cannot find get or set methods.");
+                               }
+                       } else {
+                               throw new IntrospectionException("Cannot find get or set methods.");
+                       }
+
+                       Class arrayType = Array.newInstance(indexedPropertyType,0).getClass();
+
+                       Class[] setArgs = new Class[1];
+                       setArgs[0] = arrayType;
+                       try {
+                               setMethod = beanClass.getMethod(setMethodName,setArgs);
+                               if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+                                       setMethod = null;
+                               }
+                       } catch(NoSuchMethodException E) {
+                       }
+
+                       Class[] getArgs = new Class[0];
+                       try {
+                               getMethod = beanClass.getMethod(getMethodName,getArgs);
+                               if(!getMethod.getReturnType().equals(arrayType)) {
+                                       getMethod = null;
+                               }
+                       } catch(NoSuchMethodException E) {
+                       }
+               } catch(SecurityException E) {
+                       throw new IntrospectionException("SecurityException while trying to find methods.");
+               }
+       }
+}
diff --git a/libjava/java/beans/IntrospectionException.java b/libjava/java/beans/IntrospectionException.java
new file mode 100644 (file)
index 0000000..0bbd579
--- /dev/null
@@ -0,0 +1,46 @@
+/* java.beans.IntrospectionException
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** IntrospectionException is thrown when the Introspector fails.  Surprise, surprise.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 31 May 1998
+ ** @see java.beans.Introspector
+ **/
+
+public class IntrospectionException extends Exception {
+       /** Instantiate this exception with the given message.
+        ** @param msg the message for the exception.
+        **/
+       public IntrospectionException(String msg) {
+               super(msg);
+       }
+}
diff --git a/libjava/java/beans/Introspector.java b/libjava/java/beans/Introspector.java
new file mode 100644 (file)
index 0000000..a191971
--- /dev/null
@@ -0,0 +1,427 @@
+/* java.beans.Introspector
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import gnu.java.beans.*;
+import java.util.*;
+import java.lang.reflect.*;
+import gnu.java.lang.*;
+
+/**
+ ** Introspector is the class that does the bulk of the
+ ** design-time work in Java Beans.  Every class must have
+ ** a BeanInfo in order for an RAD tool to use it; but, as
+ ** promised, you don't have to write the BeanInfo class
+ ** yourself if you don't want to.  All you have to do is
+ ** call getBeanInfo() in the Introspector and it will use
+ ** standard JavaBeans-defined method signatures to
+ ** determine the information about your class.<P>
+ **
+ ** Don't worry about it too much, though: you can provide
+ ** JavaBeans with as much customized information as you
+ ** want, or as little as you want, using the BeanInfo
+ ** interface (see BeanInfo for details).<P>
+ **
+ ** <STRONG>Order of Operations</STRONG><P>
+ **
+ ** When you call getBeanInfo(class c), the Introspector
+ ** first searches for BeanInfo class to see if you
+ ** provided any explicit information.  It searches for a
+ ** class named <bean class name>BeanInfo in different
+ ** packages, first searching the bean class's package
+ ** and then moving on to search the beanInfoSearchPath.<P>
+ **
+ ** If it does not find a BeanInfo class, it acts as though
+ ** it had found a BeanInfo class returning null from all
+ ** methods (meaning it should discover everything through
+ ** Introspection).  If it does, then it takes the
+ ** information it finds in the BeanInfo class to be
+ ** canonical (that is, the information speaks for its
+ ** class as well as all superclasses).<P>
+ **
+ ** When it has introspected the class, calls
+ ** getBeanInfo(c.getSuperclass) and adds that information
+ ** to the information it has, not adding to any information
+ ** it already has that is canonical.<P>
+ **
+ ** <STRONG>Introspection Design Patterns</STRONG><P>
+ **
+ ** When the Introspector goes in to read the class, it
+ ** follows a well-defined order in order to not leave any
+ ** methods unaccounted for.  Its job is to step over all
+ ** of the public methods in a class and determine whether
+ ** they are part of a property, an event, or a method (in
+ ** that order).
+ **
+ **
+ ** <STRONG>Properties:</STRONG><P>
+ ** 
+ ** <OL>
+ ** <LI>If there is a <CODE>public boolean isXXX()</CODE>
+ **     method, then XXX is a read-only boolean property.
+ **     <CODE>boolean getXXX()</CODE> may be supplied in
+ **     addition to this method, although isXXX() is the
+ **     one that will be used in this case and getXXX()
+ **     will be ignored.  If there is a
+ **     <CODE>public void setXXX(boolean)</CODE> method,
+ **     it is part of this group and makes it a read-write
+ **     property.</LI>
+ ** <LI>If there is a
+ **     <CODE>public &lt;type&gt; getXXX(int)</CODE>
+ **     method, then XXX is a read-only indexed property of
+ **     type &lt;type&gt;.  If there is a
+ **     <CODE>public void setXXX(int,&lt;type&gt;)</CODE>
+ **     method, then it is a read-write indexed property of
+ **     type &lt;type&gt;.  There may also be a
+ **     <CODE>public &lt;type&gt;[] getXXX()</CODE> and a
+ **     <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ **     method as well.</CODE></LI>
+ ** <LI>If there is a
+ **     <CODE>public void setXXX(int,&lt;type&gt;)</CODE>
+ **     method, then it is a write-only indexed property of
+ **     type &lt;type&gt;.  There may also be a
+ **     <CODE>public &lt;type&gt;[] getXXX()</CODE> and a
+ **     <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ **     method as well.</CODE></LI>
+ ** <LI>If there is a
+ **     <CODE>public &lt;type&gt; getXXX()</CODE> method,
+ **     then XXX is a read-only property of type
+ **     &lt;type&gt;.  If there is a
+ **     <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ **     method, then it will be used for the property and
+ **     the property will be considered read-write.</LI>
+ ** <LI>If there is a
+ **     <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ **     method, then as long as XXX is not already used as
+ **     the name of a property, XXX is assumed to be a
+ **     write-only property of type &lt;type&gt;.</LI>
+ ** <LI>In all of the above cases, if the setXXX() method
+ **     throws <CODE>PropertyVetoException</CODE>, then the
+ **     property in question is assumed to be constrained.
+ **     No properties are ever assumed to be bound
+ **     (<STRONG>Spec Note:</STRONG> this is not in the
+ **     spec, it just makes sense).  See PropertyDescriptor
+ **     for a description of bound and constrained
+ **     properties.</LI>
+ ** </OL>
+ **
+ ** <STRONG>Events:</STRONG><P>
+ **
+ ** If there is a pair of methods,
+ ** <CODE>public void addXXX(&lt;type&gt;)</CODE> and
+ ** <CODE>public void removeXXX(&lt;type&gt;)</CODE>, where
+ ** &lt;type&gt; is a descendant of
+ ** <CODE>java.util.EventListener</CODE>, then the pair of
+ ** methods imply that this Bean will fire events to
+ ** listeners of type &lt;type&gt;.<P>
+ **
+ ** If the addXXX() method throws
+ ** <CODE>java.util.TooManyListenersException</CODE>, then
+ ** the event set is assumed to be <EM>unicast</EM>.  See
+ ** EventSetDescriptor for a discussion of unicast event
+ ** sets.<P>
+ **
+ ** <STRONG>Spec Note:</STRONG> the spec seems to say that
+ ** the listener type's classname must be equal to the XXX
+ ** part of addXXX() and removeXXX(), but that is not the
+ ** case in Sun's implementation, so I am assuming it is
+ ** not the case in general.<P>
+ **
+ ** <STRONG>Methods:</STRONG><P>
+ ** 
+ ** Any public methods (including those which were used
+ ** for Properties or Events) are used as Methods.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ ** @see java.beans.BeanInfo
+ **/
+
+public class Introspector {
+       static String[] beanInfoSearchPath = {"gnu.java.beans.info", "sun.beans.infos"};
+       static Hashtable beanInfoCache = new Hashtable();
+
+       private Introspector() {}
+
+       /** Get the BeanInfo for class <CODE>beanClass</CODE>,
+        ** first by looking for explicit information, next by
+        ** using standard design patterns to determine
+        ** information about the class.
+        ** @param beanClass the class to get BeanInfo about.
+        ** @return the BeanInfo object representing the class.
+        **/
+       public static BeanInfo getBeanInfo(Class beanClass) throws IntrospectionException {
+               BeanInfo cachedInfo;
+               synchronized(beanClass) {
+               cachedInfo = (BeanInfo)beanInfoCache.get(beanClass);
+               if(cachedInfo != null) {
+                       return cachedInfo;
+               }
+               cachedInfo = getBeanInfo(beanClass,null);
+               beanInfoCache.put(beanClass,cachedInfo);
+               return cachedInfo;
+               }
+       }
+
+       /** Get the BeanInfo for class <CODE>beanClass</CODE>,
+        ** first by looking for explicit information, next by
+        ** using standard design patterns to determine
+        ** information about the class.  It crawls up the
+        ** inheritance tree until it hits <CODE>topClass</CODE>.
+        ** @param beanClass the Bean class.
+        ** @param stopClass the class to stop at.
+        ** @return the BeanInfo object representing the class.
+        **/
+       public static BeanInfo getBeanInfo(Class beanClass, Class stopClass) throws IntrospectionException {
+               ExplicitInfo explicit = new ExplicitInfo(beanClass,stopClass);
+
+               IntrospectionIncubator ii = new IntrospectionIncubator();
+               ii.setPropertyStopClass(explicit.propertyStopClass);
+               ii.setEventStopClass(explicit.eventStopClass);
+               ii.setMethodStopClass(explicit.methodStopClass);
+               ii.addMethods(beanClass.getMethods());
+
+               BeanInfoEmbryo currentInfo = ii.getBeanInfoEmbryo();
+               PropertyDescriptor[] p = explicit.explicitPropertyDescriptors;
+               if(p!=null) {
+                       for(int i=0;i<p.length;i++) {
+                               if(!currentInfo.hasProperty(p[i])) {
+                                       currentInfo.addProperty(p[i]);
+                               }
+                       }
+                       if(explicit.defaultProperty != -1) {
+                               currentInfo.setDefaultPropertyName(p[explicit.defaultProperty].getName());
+                       }
+               }
+               EventSetDescriptor[] e = explicit.explicitEventSetDescriptors;
+               if(e!=null) {
+                       for(int i=0;i<e.length;i++) {
+                               if(!currentInfo.hasEvent(e[i])) {
+                                       currentInfo.addEvent(e[i]);
+                               }
+                       }
+                       if(explicit.defaultEvent != -1) {
+                               currentInfo.setDefaultEventName(e[explicit.defaultEvent].getName());
+                       }
+               }
+               MethodDescriptor[] m = explicit.explicitMethodDescriptors;
+               if(m!=null) {
+                       for(int i=0;i<m.length;i++) {
+                               if(!currentInfo.hasMethod(m[i])) {
+                                       currentInfo.addMethod(m[i]);
+                               }
+                       }
+               }
+
+               if(explicit.explicitBeanDescriptor != null) {
+                       currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,explicit.explicitBeanDescriptor.getCustomizerClass()));
+               } else {
+                       currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,null));
+               }
+
+               currentInfo.setAdditionalBeanInfo(explicit.explicitBeanInfo);
+               currentInfo.setIcons(explicit.im);
+
+               return currentInfo.getBeanInfo();
+       }
+
+       /** Get the search path for BeanInfo classes.
+        ** @return the BeanInfo search path.
+        **/
+       public static String[] getBeanInfoSearchPath() {
+               return beanInfoSearchPath;
+       }
+
+       /** Set the search path for BeanInfo classes.
+        ** @param beanInfoSearchPath the new BeanInfo search
+        **        path.
+        **/
+       public static void setBeanInfoSearchPath(String[] beanInfoSearchPath) {
+               Introspector.beanInfoSearchPath = beanInfoSearchPath;
+       }
+
+       /** A helper method to convert a name to standard Java
+        ** naming conventions: anything with two capitals as the
+        ** first two letters remains the same, otherwise the
+        ** first letter is decapitalized.  URL = URL, I = i,
+        ** MyMethod = myMethod.
+        ** @param name the name to decapitalize.
+        ** @return the decapitalized name.
+        **/
+       public static String decapitalize(String name) {
+               try {
+                       if(!Character.isUpperCase(name.charAt(0))) {
+                               return name;
+                       } else {
+                               try {
+                                       if(Character.isUpperCase(name.charAt(1))) {
+                                               return name;
+                                       } else {
+                                               char[] c = name.toCharArray();
+                                               c[0] = Character.toLowerCase(c[0]);
+                                               return new String(c);
+                                       }
+                               } catch(StringIndexOutOfBoundsException E) {
+                                       char[] c = new char[1];
+                                       c[0] = Character.toLowerCase(name.charAt(0));
+                                       return new String(c);
+                               }
+                       }
+               } catch(StringIndexOutOfBoundsException E) {
+                       return name;
+               } catch(NullPointerException E) {
+                       return null;
+               }
+       }
+
+       static BeanInfo copyBeanInfo(BeanInfo b) {
+               java.awt.Image[] icons = new java.awt.Image[4];
+               for(int i=1;i<=4;i++) {
+                       icons[i-1] = b.getIcon(i);
+               }
+               return new ExplicitBeanInfo(b.getBeanDescriptor(),b.getAdditionalBeanInfo(),
+                                           b.getPropertyDescriptors(),b.getDefaultPropertyIndex(),
+                                           b.getEventSetDescriptors(),b.getDefaultEventIndex(),
+                                           b.getMethodDescriptors(),icons);
+       }
+}
+
+class ExplicitInfo {
+       BeanDescriptor explicitBeanDescriptor;
+       BeanInfo[] explicitBeanInfo;
+
+       PropertyDescriptor[] explicitPropertyDescriptors;
+       EventSetDescriptor[] explicitEventSetDescriptors;
+       MethodDescriptor[] explicitMethodDescriptors;
+
+       int defaultProperty;
+       int defaultEvent;
+
+       java.awt.Image[] im = new java.awt.Image[4];
+
+       Class propertyStopClass;
+       Class eventStopClass;
+       Class methodStopClass;
+
+       ExplicitInfo(Class beanClass, Class stopClass) {
+               while(beanClass != null && !beanClass.equals(stopClass)) {
+                       BeanInfo explicit = findExplicitBeanInfo(beanClass);
+                       if(explicit != null) {
+                               if(explicitBeanDescriptor == null) {
+                                       explicitBeanDescriptor = explicit.getBeanDescriptor();
+                               }
+                               if(explicitBeanInfo == null) {
+                                       explicitBeanInfo = explicit.getAdditionalBeanInfo();
+                               }
+                               if(explicitPropertyDescriptors == null) {
+                                       if(explicit.getPropertyDescriptors() != null) {
+                                               explicitPropertyDescriptors = explicit.getPropertyDescriptors();
+                                               defaultProperty = explicit.getDefaultPropertyIndex();
+                                               propertyStopClass = beanClass;
+                                       }
+                               }
+                               if(explicitEventSetDescriptors == null) {
+                                       if(explicit.getEventSetDescriptors() != null) {
+                                               explicitEventSetDescriptors = explicit.getEventSetDescriptors();
+                                               defaultEvent = explicit.getDefaultEventIndex();
+                                               eventStopClass = beanClass;
+                                       }
+                               }
+                               if(explicitMethodDescriptors == null) {
+                                       if(explicit.getMethodDescriptors() != null) {
+                                               explicitMethodDescriptors = explicit.getMethodDescriptors();
+                                               methodStopClass = beanClass;
+                                       }
+                               }
+                               if(im[0] == null
+                                  && im[1] == null
+                                  && im[2] == null
+                                  && im[3] == null) {
+                                       im[0] = explicit.getIcon(0);
+                                       im[1] = explicit.getIcon(1);
+                                       im[2] = explicit.getIcon(2);
+                                       im[3] = explicit.getIcon(3);
+                               }
+                       }
+                       beanClass = beanClass.getSuperclass();
+               }
+               if(propertyStopClass == null) {
+                       propertyStopClass = stopClass;
+               }
+               if(eventStopClass == null) {
+                       eventStopClass = stopClass;
+               }
+               if(methodStopClass == null) {
+                       methodStopClass = stopClass;
+               }
+       }
+
+       static Hashtable explicitBeanInfos = new Hashtable();
+       static Vector emptyBeanInfos = new Vector();
+
+       static BeanInfo findExplicitBeanInfo(Class beanClass) {
+               BeanInfo retval = (BeanInfo)explicitBeanInfos.get(beanClass);
+               if(retval != null) {
+                       return retval;
+               } else if(emptyBeanInfos.indexOf(beanClass) != -1) {
+                       return null;
+               } else {
+                       retval = reallyFindExplicitBeanInfo(beanClass);
+                       if(retval != null) {
+                               explicitBeanInfos.put(beanClass,retval);
+                       } else {
+                               emptyBeanInfos.addElement(beanClass);
+                       }
+                       return retval;
+               }
+       }
+
+       static BeanInfo reallyFindExplicitBeanInfo(Class beanClass) {
+               try {
+               try {
+                       return (BeanInfo)Class.forName(beanClass.getName()+"BeanInfo").newInstance();
+               } catch(ClassNotFoundException E) {
+               }
+               String newName = ClassHelper.getTruncatedClassName(beanClass) + "BeanInfo";
+               for(int i=0;i<Introspector.beanInfoSearchPath.length;i++) {
+                       try {
+                               if(Introspector.beanInfoSearchPath[i].equals("")) {
+                                       return (BeanInfo)Class.forName(newName).newInstance();
+                               } else {
+                                       return (BeanInfo)Class.forName(Introspector.beanInfoSearchPath[i] + "." + newName).newInstance();
+                               }
+                       } catch(ClassNotFoundException E) {
+                       }
+               }
+               } catch(IllegalAccessException E) {
+               } catch(InstantiationException E) {
+               }
+               return null;
+       }
+}
diff --git a/libjava/java/beans/MethodDescriptor.java b/libjava/java/beans/MethodDescriptor.java
new file mode 100644 (file)
index 0000000..bb052f7
--- /dev/null
@@ -0,0 +1,77 @@
+/* java.beans.MethodDescriptor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import java.lang.reflect.*;
+
+/** MethodDescriptor describes information about a JavaBeans method.
+ ** It's a fairly straightforward class (at least something in this
+ ** package is straightforward!).
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+public class MethodDescriptor extends FeatureDescriptor {
+       private Method m;
+       private ParameterDescriptor[] parameterDescriptors;
+
+       /** Create a new MethodDescriptor.
+        ** This method sets the name to the name of the method (Method.getName()).
+        ** @param m the method it will represent.
+        **/
+       public MethodDescriptor(Method m) {
+               setName(m.getName());
+               this.m = m;
+       }
+
+       /** Create a new MethodDescriptor.
+        ** This method sets the name to the name of the method (Method.getName()).
+        ** @param m the method it will represent.
+        ** @param parameterDescriptors descriptions of the parameters (especially names).
+        **/
+       public MethodDescriptor(Method m, ParameterDescriptor[] parameterDescriptors) {
+               setName(m.getName());
+               this.m = m;
+               this.parameterDescriptors = parameterDescriptors;
+       }
+
+       /** Get the parameter descriptors from this method.
+        ** Since MethodDescriptor has no way of determining what
+        ** the parameter names were, this defaults to null.
+        **/
+       public ParameterDescriptor[] getParameterDescriptors() {
+               return parameterDescriptors;
+       }
+
+       /** Get the method this MethodDescriptor represents. **/
+       public Method getMethod() {
+               return m;
+       }
+}
+
diff --git a/libjava/java/beans/ParameterDescriptor.java b/libjava/java/beans/ParameterDescriptor.java
new file mode 100644 (file)
index 0000000..664d5ca
--- /dev/null
@@ -0,0 +1,41 @@
+/* java.beans.MethodDescriptor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/** ParameterDescriptor represents a single parameter to a method.
+ ** As it turns out, FeatureDescriptor is sufficient to hold all
+ ** the information.  Use its constructor and methods to set
+ ** the appropriate values.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+public class ParameterDescriptor extends FeatureDescriptor {
+       
+}
diff --git a/libjava/java/beans/PropertyChangeEvent.java b/libjava/java/beans/PropertyChangeEvent.java
new file mode 100644 (file)
index 0000000..f07577c
--- /dev/null
@@ -0,0 +1,111 @@
+/* java.beans.PropertyChangeEvent
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** PropertyChangeEvents are fired in the PropertyChange
+ ** and VetoableChange event classes.  They represent the
+ ** old and new values as well as the source Bean.<P>
+ **
+ ** If the old or new value is a primitive type, it must
+ ** be wrapped in the appropriate wrapper type
+ ** (java.lang.Integer for int, etc., etc.).<P>
+ **
+ ** If the old or new values are unknown (although why
+ ** that would be I do not know), they may be null.<P>
+ **
+ ** Right now Sun put in a propagationId, reserved for
+ ** future use.  Read the comments on the constructor
+ ** and on setPropagationId for more information.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class PropertyChangeEvent extends java.util.EventObject {
+       String propertyName;
+       Object oldVal;
+       Object newVal;
+       Object propagationId;
+
+       /** Create a new PropertyChangeEvent.  Remember that if
+        ** you received a PropertyChangeEvent and are sending
+        ** a new one, you should also set the propagation ID
+        ** from the old PropertyChangeEvent.
+        ** @param source the Bean containing the property.
+        ** @param propertyName the property's name.
+        ** @param oldVal the old value of the property.
+        ** @param newVal the new value of the property.
+        **/
+       public PropertyChangeEvent(Object source, String propertyName, Object oldVal, Object newVal) {
+               super(source);
+               this.propertyName = propertyName;
+               this.oldVal = oldVal;
+               this.newVal = newVal;
+       }
+
+       /** Get the property name.
+        ** @return the property name.
+        **/
+       public String getPropertyName() {
+               return propertyName;
+       }
+
+       /** Get the property's old value.
+        ** @return the property's old value.
+        **/
+       public Object getOldValue() {
+               return oldVal;
+       }
+
+       /** Get the property's new value.
+        ** @return the property's new value.
+        **/
+       public Object getNewValue() {
+               return newVal;
+       }
+
+       /** Set the propagation ID.  This is a way for the event
+        ** to be passed from hand to hand and retain a little
+        ** extra state.  Right now it is unused, but it should
+        ** be propagated anyway so that future versions of
+        ** JavaBeans can use it, for God knows what.
+        ** @param propagationId the propagation ID.
+        **/
+       public void setPropagationId(Object propagationId) {
+               this.propagationId = propagationId;
+       }
+
+       /** Get the propagation ID.
+        ** @return the propagation ID.
+        **/
+       public Object getPropagationId() {
+               return propagationId;
+       }
+}
diff --git a/libjava/java/beans/PropertyChangeListener.java b/libjava/java/beans/PropertyChangeListener.java
new file mode 100644 (file)
index 0000000..7f1df72
--- /dev/null
@@ -0,0 +1,48 @@
+/* java.beans.PropertyChangeListener
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** PropertyChangeListener allows a class to monitor
+ ** properties of a Bean for changes.<P>
+ **
+ ** A propertyChange() event will only be fired
+ ** <EM>after</EM> the property has changed.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ ** @see java.beans.PropertyChangeSupport
+ **/
+
+public interface PropertyChangeListener {
+       /** Fired after a Bean's property has changed.
+        ** @param e the change (containing the old and new values)
+        **/
+       public abstract void propertyChange(PropertyChangeEvent e);
+}
diff --git a/libjava/java/beans/PropertyChangeSupport.java b/libjava/java/beans/PropertyChangeSupport.java
new file mode 100644 (file)
index 0000000..512c8ed
--- /dev/null
@@ -0,0 +1,203 @@
+/* java.beans.PropertyChangeSupport
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ ** PropertyChangeSupport makes it easy to fire property
+ ** change events and handle listeners.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.2.0, 15 Mar 1999
+ **/
+
+public class PropertyChangeSupport implements java.io.Serializable {
+       Hashtable propertyListeners = new Hashtable();
+       Vector listeners = new Vector();
+       Object bean;
+
+       /** Create PropertyChangeSupport to work with a specific
+        ** source bean.
+        ** @param bean the source bean to use.
+        **/
+       public PropertyChangeSupport(Object bean) {
+               this.bean = bean;
+       }
+
+       /** Adds a PropertyChangeListener to the list of listeners.
+        ** All property change events will be sent to this listener.
+        ** <P>
+        **
+        ** The listener add is not unique: that is, <em>n</em> adds with
+        ** the same listener will result in <em>n</em> events being sent
+        ** to that listener for every property change.
+        ** <P>
+        **
+        ** Adding a null listener will cause undefined behavior.
+        **
+        ** @param l the listener to add.
+        **/
+       public void addPropertyChangeListener(PropertyChangeListener l) {
+               listeners.addElement(l);
+       }
+
+       /** Adds a PropertyChangeListener listening on the specified property.
+        ** Events will be sent to the listener for that particular property.
+        ** <P>
+        **
+        ** The listener add is not unique; that is, <em>n</em> adds on a
+        ** particular property for a particular listener will result in
+        ** <em>n</em> events being sent to that listener when that
+        ** property is changed.
+        ** <P>
+        **
+        ** The effect is cumulative, too; if you are registered to listen
+        ** to receive events on all property changes, and then you
+        ** register on a particular property, you will receive change
+        ** events for that property twice.
+        ** <P>
+        **
+        ** Adding a null listener will cause undefined behavior.
+        **
+        ** @param propertyName the name of the property to listen on.
+        ** @param l the listener to add.
+        **/
+       public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
+               synchronized(propertyListeners) {
+                       Vector v = (Vector)propertyListeners.get(propertyName);
+                       try {
+                               v.addElement(l);
+                       } catch(NullPointerException e) {
+                               /* If v is not found, create a new vector. */
+                               v = new Vector();
+                               v.addElement(l);
+                               propertyListeners.put(propertyName, v);
+                       }
+               }
+       }
+
+       /** Removes a PropertyChangeListener from the list of listeners.
+        ** If any specific properties are being listened on, they must
+        ** be deregistered by themselves; this will only remove the
+        ** general listener to all properties.
+        ** <P>
+        **
+        ** If <code>add()</code> has been called multiple times for a
+        ** particular listener, <code>remove()</code> will have to be
+        ** called the same number of times to deregister it.
+        **
+        ** @param l the listener to remove.
+        **/
+       public void removePropertyChangeListener(PropertyChangeListener l) {
+               listeners.removeElement(l);
+       }
+
+       /** Removes a PropertyChangeListener from listening to a specific property.
+        ** <P>
+        **
+        ** If <code>add()</code> has been called multiple times for a
+        ** particular listener on a property, <code>remove()</code> will
+        ** have to be called the same number of times to deregister it.
+        **
+        ** @param propertyName the property to stop listening on.
+        ** @param l the listener to remove.
+        **/
+       public void removePropertyChangeListener(String propertyName, PropertyChangeListener l) {
+               synchronized(propertyListeners) {
+                       Vector v = (Vector)propertyListeners.get(propertyName);
+                       try {
+                               v.removeElement(l);
+                               if(v.size() == 0) {
+                                       propertyListeners.remove(propertyName);
+                               }
+                       } catch(NullPointerException e) {
+                               /* if v is not found, do nothing. */
+                       }
+               }
+       }
+
+       /** Fire a PropertyChangeEvent to all the listeners.
+        **
+        ** @param event the event to fire.
+        **/
+       public void firePropertyChange(PropertyChangeEvent event) {
+               for(int i=0;i<listeners.size();i++) {
+                       ((PropertyChangeListener)listeners.elementAt(i)).propertyChange(event);
+               }
+               Vector moreListeners = (Vector)propertyListeners.get(event.getPropertyName());
+               if(moreListeners != null) {
+                       for(int i=0;i<moreListeners.size();i++) {
+                               ((PropertyChangeListener)moreListeners.elementAt(i)).propertyChange(event);
+                       }
+               }
+       }
+
+       /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners.
+        **
+        ** @param propertyName the name of the property that changed.
+        ** @param oldVal the old value.
+        ** @param newVal the new value.
+        **/
+       public void firePropertyChange(String propertyName, Object oldVal, Object newVal) {
+               firePropertyChange(new PropertyChangeEvent(bean,propertyName,oldVal,newVal));
+       }
+
+       /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners.
+        **
+        ** @param propertyName the name of the property that changed.
+        ** @param oldVal the old value.
+        ** @param newVal the new value.
+        **/
+       public void firePropertyChange(String propertyName, boolean oldVal, boolean newVal) {
+               firePropertyChange(new PropertyChangeEvent(bean, propertyName, new Boolean(oldVal), new Boolean(newVal)));
+       }
+
+       /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners.
+        **
+        ** @param propertyName the name of the property that changed.
+        ** @param oldVal the old value.
+        ** @param newVal the new value.
+        **/
+       public void firePropertyChange(String propertyName, int oldVal, int newVal) {
+               firePropertyChange(new PropertyChangeEvent(bean, propertyName, new Integer(oldVal), new Integer(newVal)));
+       }
+
+       /** Tell whether the specified property is being listened on or not.
+        ** This will only return <code>true</code> if there are listeners
+        ** on all properties or if there is a listener specifically on this
+        ** property.
+        **
+        ** @param propertyName the property that may be listened on
+        ** @return whether the property is being listened on
+        **/
+        public boolean hasListeners(String propertyName) {
+               return listeners.size() > 0  || propertyListeners.get(propertyName) != null;
+        }
+}
diff --git a/libjava/java/beans/PropertyDescriptor.java b/libjava/java/beans/PropertyDescriptor.java
new file mode 100644 (file)
index 0000000..ec14312
--- /dev/null
@@ -0,0 +1,333 @@
+/* java.beans.PropertyDescriptor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import java.util.*;
+import java.lang.reflect.*;
+
+
+/**
+ ** PropertyDescriptor describes information about a JavaBean property,
+ ** by which we mean a property that has been exposed via a pair of
+ ** get and set methods.  (There may be no get method, which means
+ ** the property is write-only, or no set method, which means the
+ ** the property is read-only.)<P>
+ **
+ ** The constraints put on get and set methods are:<P>
+ ** <OL>
+ ** <LI>A get method must have signature
+ **     <CODE>&lt;propertyType&gt; &lt;getMethodName&gt;()</CODE></LI>
+ ** <LI>A set method must have signature
+ **     <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;)</CODE></LI>
+ ** <LI>Either method type may throw any exception.</LI>
+ ** <LI>Both methods must be public.</LI>
+ ** </OL>
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+
+public class PropertyDescriptor extends FeatureDescriptor {
+       Class propertyType;
+       Method getMethod;
+       Method setMethod;
+
+       Class propertyEditorClass;
+       boolean bound;
+       boolean constrained;
+
+       PropertyDescriptor(String name) {
+               setName(name);
+       }
+
+       /** Create a new PropertyDescriptor by introspection.
+        ** This form of constructor creates the PropertyDescriptor by
+        ** looking for a getter method named <CODE>get&lt;name&gt;()</CODE>
+        ** (or, optionally, if the property is boolean,
+        ** <CODE>is&lt;name&gt;()</CODE>) and
+        ** <CODE>set&lt;name&gt;()</CODE> in class
+        ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
+        ** first letter capitalized by the constructor.<P>
+        **
+        ** <B>Implementation note:</B> If there is a get method (or
+        ** boolean isXXX() method), then the return type of that method
+        ** is used to find the set method.  If there is no get method,
+        ** then the set method is searched for exhaustively.<P>
+        **
+        ** <B>Spec note:</B>
+        ** If there is no get method and multiple set methods with
+        ** the same name and a single parameter (different type of course),
+        ** then an IntrospectionException is thrown.  While Sun's spec
+        ** does not state this, it can make Bean behavior different on
+        ** different systems (since method order is not guaranteed) and as
+        ** such, can be treated as a bug in the spec.  I am not aware of
+        ** whether Sun's implementation catches this.
+        **
+        ** @param name the programmatic name of the property, usually
+        **             starting with a lowercase letter (e.g. fooManChu
+        **             instead of FooManChu).
+        ** @param beanClass the class the get and set methods live in.
+        ** @exception IntrospectionException if the methods are not found or invalid.
+        **/
+       public PropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
+               setName(name);
+               String capitalized;
+               try {
+                       capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+               } catch(StringIndexOutOfBoundsException e) {
+                       capitalized = "";
+               }
+               findMethods(beanClass, "is" + capitalized, "get" + capitalized, "set" + capitalized);
+       }
+
+       /** Create a new PropertyDescriptor by introspection.
+        ** This form of constructor allows you to specify the
+        ** names of the get and set methods to search for.<P>
+        **
+        ** <B>Implementation note:</B> If there is a get method (or
+        ** boolean isXXX() method), then the return type of that method
+        ** is used to find the set method.  If there is no get method,
+        ** then the set method is searched for exhaustively.<P>
+        **
+        ** <B>Spec note:</B>
+        ** If there is no get method and multiple set methods with
+        ** the same name and a single parameter (different type of course),
+        ** then an IntrospectionException is thrown.  While Sun's spec
+        ** does not state this, it can make Bean behavior different on
+        ** different systems (since method order is not guaranteed) and as
+        ** such, can be treated as a bug in the spec.  I am not aware of
+        ** whether Sun's implementation catches this.
+        **
+        ** @param name the programmatic name of the property, usually
+        **             starting with a lowercase letter (e.g. fooManChu
+        **             instead of FooManChu).
+        ** @param beanClass the class the get and set methods live in.
+        ** @param getMethodName the name of the get method.
+        ** @param setMethodName the name of the set method.
+        ** @exception IntrospectionException if the methods are not found or invalid.
+        **/
+       public PropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName) throws IntrospectionException {
+               setName(name);
+               findMethods(beanClass, getMethodName, null, setMethodName);
+       }
+
+       /** Create a new PropertyDescriptor using explicit Methods.
+        ** Note that the methods will be checked for conformance to standard
+        ** Property method rules, as described above at the top of this class.
+        ** 
+        ** @param name the programmatic name of the property, usually
+        **             starting with a lowercase letter (e.g. fooManChu
+        **             instead of FooManChu).
+        ** @param getMethod the get method.
+        ** @param setMethod the set method.
+        ** @exception IntrospectionException if the methods are not found or invalid.
+        **/
+       public PropertyDescriptor(String name, Method getMethod, Method setMethod) throws IntrospectionException {
+               setName(name);
+               if(getMethod != null && getMethod.getParameterTypes().length > 0) {
+                       throw new IntrospectionException("get method has parameters");
+               }
+               if(setMethod != null && setMethod.getParameterTypes().length != 1) {
+                       throw new IntrospectionException("set method does not have exactly one parameter");
+               }
+               if(getMethod != null && setMethod != null) {
+                       if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
+                               throw new IntrospectionException("set and get methods do not share the same type");
+                       }
+                       if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
+                          && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
+                               throw new IntrospectionException("set and get methods are not in the same class.");
+                       }
+               }
+               this.getMethod = getMethod;
+               this.setMethod = setMethod;
+               if(getMethod != null) {
+                       this.propertyType = getMethod.getReturnType();
+               } else {
+                       this.propertyType = setMethod.getParameterTypes()[0];
+               }
+       }
+
+       /** Get the property type.
+        ** This is the type the get method returns and the set method
+        ** takes in.
+        **/
+       public Class getPropertyType() {
+               return propertyType;
+       }
+
+       /** Get the get method.  Why they call it readMethod here and
+        ** get everywhere else is beyond me.
+        **/
+       public Method getReadMethod() {
+               return getMethod;
+       }
+
+       /** Get the set method.  Why they call it writeMethod here and
+        ** set everywhere else is beyond me.
+        **/
+       public Method getWriteMethod() {
+               return setMethod;
+       }
+
+       /** Get whether the property is bound.  Defaults to false. **/
+       public boolean isBound() {
+               return bound;
+       }
+
+       /** Set whether the property is bound.
+        ** As long as the the bean implements addPropertyChangeListener() and
+        ** removePropertyChangeListener(), setBound(true) may safely be called.<P>
+        ** If these things are not true, then the behavior of the system
+        ** will be undefined.<P>
+        **
+        ** When a property is bound, its set method is required to fire the
+        ** <CODE>PropertyChangeListener.propertyChange())</CODE event
+        ** after the value has changed.
+        ** @param bound whether the property is bound or not.
+        **/
+       public void setBound(boolean bound) {
+               this.bound = bound;
+       }
+
+       /** Get whether the property is constrained.  Defaults to false. **/
+       public boolean isConstrained() {
+               return constrained;
+       }
+
+       /** Set whether the property is constrained.
+        ** If the set method throws <CODE>java.beans.PropertyVetoException</CODE>
+        ** (or subclass thereof) and the bean implements addVetoableChangeListener()
+        ** and removeVetoableChangeListener(), then setConstrained(true) may safely
+        ** be called.  Otherwise, the system behavior is undefined.
+        ** <B>Spec note:</B> given those strict parameters, it would be nice if it
+        ** got set automatically by detection, but oh well.<P>
+        ** When a property is constrained, its set method is required to:<P>
+        ** <OL>
+        ** <LI>Fire the <CODE>VetoableChangeListener.vetoableChange()</CODE>
+        **     event notifying others of the change and allowing them a chance to
+        **     say it is a bad thing.</LI>
+        ** <LI>If any of the listeners throws a PropertyVetoException, then
+        **     it must fire another vetoableChange() event notifying the others
+        **     of a reversion to the old value (though, of course, the change
+        **     was never made).  Then it rethrows the PropertyVetoException and
+        **     exits.</LI>
+        ** <LI>If all has gone well to this point, the value may be changed.</LI>
+        ** </OL>
+        ** @param constrained whether the property is constrained or not.
+        **/
+       public void setConstrained(boolean constrained) {
+               this.constrained = constrained;
+       }
+
+       /** Get the PropertyEditor class.  Defaults to null. **/
+       public Class getPropertyEditorClass() {
+               return propertyEditorClass;
+       }
+
+       /** Set the PropertyEditor class.  If the class does not implement
+        ** the PropertyEditor interface, you will likely get an exception
+        ** late in the game.
+        ** @param propertyEditorClass the PropertyEditor class for this class to use.
+        **/
+       public void setPropertyEditorClass(Class propertyEditorClass) {
+               this.propertyEditorClass = propertyEditorClass;
+       }
+
+       private void findMethods(Class beanClass, String getMethodName1, String getMethodName2, String setMethodName) throws IntrospectionException {
+               try {
+                       if(getMethodName1 != null) {
+                               try {
+                                       getMethod = beanClass.getMethod(getMethodName1, new Class[0]);
+                               } catch(NoSuchMethodException E) {
+                               }
+                               if(getMethodName2 != null) {
+                                       if(getMethod != null && !getMethod.getReturnType().equals(java.lang.Boolean.TYPE)) {
+                                               // If the is() method exists but isn't boolean, we'll just go on and look for
+                                               // an ordinary get() method.
+                                               getMethod = null;
+                                       }
+
+                                       Method getMethod2;
+                                       try {
+                                               getMethod2 = beanClass.getMethod(getMethodName2, new Class[0]);
+                                       } catch(NoSuchMethodException E) {
+                                               getMethod2 = null;
+                                       }
+                                       if(getMethod2 != null) {
+                                               if(getMethod != null) {
+                                                       if(!getMethod.getReturnType().equals(getMethod2.getReturnType())) {
+                                                               throw new IntrospectionException("Both " + getMethodName1 + " and " + getMethodName2 + " exist, and have contradictory return types.");
+                                                       }
+                                               } else {
+                                                       getMethod = getMethod2;
+                                               }
+                                       }
+                               }
+                       }
+
+                       if(getMethod != null) {
+                               propertyType = getMethod.getReturnType();
+                               if(setMethodName != null) {
+                                       Class[] setArgs = new Class[1];
+                                       setArgs[0] = propertyType;
+                                       try {
+                                               setMethod = beanClass.getMethod(setMethodName, setArgs);
+                                               if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+                                                       throw new IntrospectionException(setMethodName + " has non-void return type");
+                                               }
+                                       } catch(NoSuchMethodException E) {
+                                       }
+                               }
+                       } else if(setMethodName != null) {
+                               Method[] m = beanClass.getMethods();
+                               for(int i=0;i<m.length;i++) {
+                                       Method current = m[i];
+                                       if(current.getName().equals(setMethodName)
+                                          && current.getParameterTypes().length == 1
+                                          && current.getReturnType().equals(java.lang.Void.TYPE)) {
+                                               if(setMethod != null) {
+                                                       throw new IntrospectionException("Multiple, different set methods found that fit the bill!");
+                                               } else {
+                                                       setMethod = current;
+                                                       propertyType = current.getParameterTypes()[0];
+                                               }
+                                       }
+                               }
+                               if(setMethod == null) {
+                                       throw new IntrospectionException("Cannot find get or set methods.");
+                               }
+                       } else {
+                               throw new IntrospectionException("Cannot find get or set methods.");
+                       }
+               } catch(SecurityException E) {
+                       throw new IntrospectionException("SecurityException thrown on attempt to access methods.");
+               }
+       }
+}
diff --git a/libjava/java/beans/PropertyEditor.java b/libjava/java/beans/PropertyEditor.java
new file mode 100644 (file)
index 0000000..b861b52
--- /dev/null
@@ -0,0 +1,198 @@
+/* java.beans.PropertyEditor
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** PropertyEditors are custom GUI editors for specific types of values.
+ **
+ ** A PropertyEditor can be used, for example, if you are editing a type of value
+ ** that can be more easily represented graphically, such as a Point, or one that
+ ** can be more easily represented by a list, such as a boolean (true/false).<P>
+ **
+ ** A PropertyEditor must be able to display its contents when asked to and
+ ** be able to allow the user to change its underlying field value.  However, it
+ ** is not the PropertyEditor's responsibility to make the change to the
+ ** underlying Object; in fact, the PropertyEditor does not even know about the
+ ** Object it is actually editing--only about the property it is currently
+ ** editing.  When a change is made to the property, the PropertyEditor must
+ ** simply fire a PropertyChangeEvent and allow the RAD tool to actually set
+ ** the property in the underlying Bean.<P>
+ **
+ ** PropertyEditors should not change the Objects they are given by setValue().
+ ** These Objects may or may not be the actual Objects which are properties of
+ ** the Bean being edited.  Instead, PropertyEditors should create a new Object
+ ** and fire a PropertyChangeEvent with the old and new values.<P>
+ **
+ ** PropertyEditors also must support the ability to return a Java
+ ** initialization string.  See the getJavaInitializationString() method for
+ ** details.<P>
+ **
+ ** There are several different ways a PropertyEditor may display and control
+ ** editing of its value.  When multiple types of input and display are
+ ** given by a single PropertyEditor, the RAD tool may decide which of the call
+ ** to support.  Some RAD tools may even be text-only, so even if you support
+ ** a graphical set and get, it may choose the text set and get whenever it can.
+ ** <OL>
+ **   <LI>Every PropertyEditor must support getValue() and setValue().  For
+ **       setValue(), the component must only support it when the argument is
+ **       the same type that the PropertyEditor supports.</LI>
+ **   <LI>Every PropertyEditor must support getJavaInitializationString().</LI>
+ **   <LI>You may support painting the value yourself if you wish.  To do this,
+ **       have isPaintable() return true and implement the paintValue() method.
+ **       This method does not determine in any way how the value is edited;
+ **       merely how it is displayed.</LI>
+ **   <LU>Let the caller of the PropertyEditor give the user a text input.  Do
+ **       this by returning a non-null String from getAsText().  If you support
+ **       text input, you *must* support setAsText().</LI>
+ **   <LI>Give the caller a set of possible values, such as "true"/"false", that
+ **       the user must select from.  To do this, return the list of Strings
+ **       from the getTags() method.  The RAD tool may choose to implement the
+ **       user input any way it wishes, and only guarantees that setAsText() will
+ **       only be called with one of the Strings returned from getTags().</LI>
+ **   <LI>You may support a whole custom editing control by supporting
+ **       getCustomEditor().  To do this, return true from supportsCustomEditor()
+ **       and return a Component that does the job.  It is the component's job,
+ **       or the PropertyEditor's job, to make sure that when the editor changes
+ **       its value, the PropertyChangeEvent is thrown.</LI>
+ ** </OL>
+ **
+ ** The PropertyEditor for a particular Bean can be found using the
+ ** PropertyEditorManager class, which goes through a series of different
+ ** checks to find the appropriate class.<P>
+ **
+ ** A PropertyChangeEvent should be thrown from the PropertyEditor whenever a
+ ** bound  property (a property PropertyDescriptor.isBound() set to true)
+ ** changes.  When this happens, the editor itself should *not* change the value
+ ** itself, but rather allow the RAD tool to call setValue() or setAsText().
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 30 June 1998
+ ** @see java.beans.PropertyEditorManager
+ ** @see java.beans.PropertyEditorSupport
+ **/
+
+public interface PropertyEditor {
+       /** Called by the RAD tool to set the value of this property for the PropertyEditor.
+        ** If the property type is native, it should be wrapped in the appropriate
+        ** wrapper type.
+        ** @param value the value to set this property to.
+        **/
+       public abstract void setValue(Object value);
+
+       /** Accessor method to get the current value the PropertyEditor is working with.
+        ** If the property type is native, it will be wrapped in the appropriate
+        ** wrapper type.
+        ** @return the current value of the PropertyEditor.
+        **/
+       public abstract Object getValue();
+
+
+       /** Set the value of this property using a String.
+        ** Whether or not this PropertyEditor is editing a String type, this converts
+        ** the String into the type of the PropertyEditor.
+        ** @param text the text to set it to.
+        ** @exception IllegalArgumentException if the String is in the wrong format or setAsText() is not supported.
+        **/
+       public abstract void setAsText(String text) throws IllegalArgumentException;
+
+       /** Get the value of this property in String format.
+        ** Many times this can simply use Object.toString().<P>
+        ** Return null if you do not support getAsText()/setAsText().
+        ** <code>setAsText(getAsText())</code> should be valid; i.e. the stuff you spit out in
+        ** getAsText() should be able to go into setAsText().
+        ** @return the value of this property in String format.
+        **/
+       public abstract String getAsText();
+
+       /** Get a list of possible Strings which this property type can have.
+        ** The value of these will be used by the RAD tool to construct some sort
+        ** of list box or to check text box input, and the resulting String passed
+        ** to setAsText() should be one of these.  Note, however, that like most things
+        ** with this mammoth, unwieldy interface, this is not guaranteed.  Thus, you
+        ** must check the value in setAsText() anyway.
+        ** @return the list of possible String values for this property type.
+        **/
+       public abstract String[] getTags();
+
+
+       /** The RAD tool calls this to find out whether the PropertyEditor can paint itself.
+        ** @return true if it can paint itself graphically, false if it cannot.
+        **/
+       public abstract boolean isPaintable();
+
+       /** The RAD tool calls this to paint the actual value of the property.
+        ** The Graphics context will have the same current font, color, etc. as the
+        ** parent Container.  You may safely change the font, color, etc. and not
+        ** change them back.<P>
+        ** This method should do a silent no-op if isPaintable() is false.
+        ** @param g the Graphics context to paint on
+        ** @param bounds the rectangle you have reserved to work in
+        **/
+       public abstract void paintValue(java.awt.Graphics g, java.awt.Rectangle bounds);
+
+
+       /** The RAD tool calls this to find out whether the PropertyEditor supports a custom component to edit and display itself.
+        ** @return true if getCustomEditor() will return a component, false if not.
+        **/
+       public abstract boolean supportsCustomEditor();
+
+       /** The RAD tool calls this to grab the component that can edit this type.
+        ** The component may be painted anywhere the RAD tool wants to paint it--
+        ** even in its own window.<P>
+        ** The component must hook up with the PropertyEditor and, whenever a
+        ** change to the value is made, fire a PropertyChangeEvent to the source.<P>
+        ** @return the custom editor for this property type.
+        **/
+       public abstract java.awt.Component getCustomEditor();
+
+
+       /** Adds a property change listener to this PropertyEditor.
+        ** @param listener the listener to add
+        **/
+       public abstract void addPropertyChangeListener(PropertyChangeListener listener);
+
+       /** Removes a property change listener from this PropertyEditor.
+        ** @param listener the listener to remove
+        **/
+       public abstract void removePropertyChangeListener(PropertyChangeListener listener);
+
+       /** Get a Java language-specific String which could be used to create an Object
+        ** of the specified type.  Every PropertyEditor must support this.<P>
+        ** The reason for this is that while most RAD tools will serialize the Beans
+        ** and deserialize them at runtime, some RAD tools will generate code that
+        ** creates the Beans.  Examples of Java initialization strings would be:<P>
+        ** <OL>
+        **     <LI><CODE>2</CODE></LI>
+        **     <LI><CODE>"I am a String"</CODE></LI>
+        **     <LI><CODE>new MyObject(2, "String", new StringBuffer())</CODE></LI>
+        ** </OL>
+        ** @return the initialization string for this object in Java.
+        **/
+       public abstract String getJavaInitializationString();
+}
diff --git a/libjava/java/beans/PropertyEditorManager.java b/libjava/java/beans/PropertyEditorManager.java
new file mode 100644 (file)
index 0000000..b64b2a8
--- /dev/null
@@ -0,0 +1,150 @@
+/* java.beans.PropertyEditorManager
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import gnu.java.lang.ClassHelper;
+
+/**
+ ** PropertyEditorManager is used to find property editors
+ ** for various types (not necessarily Beans).<P>
+ **
+ ** It first checks to see if the property editor is
+ ** already registered; if it is, that property editor is
+ ** used.  Next it takes the type's classname and appends
+ ** "Editor" to it, and searches first in the class's
+ ** package and then in the property editor search path.<P>
+ **
+ ** Default property editors are provided for:<P>
+ ** <OL>
+ ** <LI>boolean, byte, short, int, long, float, and double</LI>
+ ** <LI>java.lang.String</LI>
+ ** <LI>java.awt.Color</LI>
+ ** <LI>java.awt.Font</LI>
+ ** <OL>
+ **
+ ** <STRONG>Spec Suggestion:</STRONG> Perhaps an editor for
+ ** Filename or something like it should be provided.  As well
+ ** as char.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class PropertyEditorManager {
+       static java.util.Hashtable editors = new java.util.Hashtable();
+       static String[] editorSearchPath = {"gnu.java.beans.editors","sun.beans.editors"};
+
+       static {
+               registerEditor(java.lang.Boolean.TYPE, gnu.java.beans.editors.NativeBooleanEditor.class);
+               registerEditor(java.lang.Byte.TYPE,    gnu.java.beans.editors.NativeByteEditor.class);
+               registerEditor(java.lang.Short.TYPE,   gnu.java.beans.editors.NativeShortEditor.class);
+               registerEditor(java.lang.Integer.TYPE, gnu.java.beans.editors.NativeIntEditor.class);
+               registerEditor(java.lang.Long.TYPE,    gnu.java.beans.editors.NativeLongEditor.class);
+               registerEditor(java.lang.Float.TYPE,   gnu.java.beans.editors.NativeFloatEditor.class);
+               registerEditor(java.lang.Double.TYPE,  gnu.java.beans.editors.NativeDoubleEditor.class);
+               registerEditor(java.lang.String.class, gnu.java.beans.editors.StringEditor.class);
+               registerEditor(java.awt.Color.class,   gnu.java.beans.editors.ColorEditor.class);
+               registerEditor(java.awt.Font.class,    gnu.java.beans.editors.FontEditor.class);
+       }
+
+       /** Beats me why this class can be instantiated, but there
+        ** you have it.
+        **/
+       public PropertyEditorManager() { }
+
+       /** Register an editor for a class.  Replaces old editor
+        ** if there was one registered before.
+        ** @param editedClass the class that the property editor
+        **        will edit.
+        ** @param editorClass the PropertyEditor class.
+        **/
+       public static void registerEditor(Class editedClass, Class editorClass) {
+               editors.put(editedClass, editorClass);
+       }
+
+       /** Returns a new instance of the property editor for the
+        ** specified class.
+        ** @param editedClass the class that the property editor
+        **        will edit.
+        ** @return a PropertyEditor instance that can edit the
+        **         specified class.
+        **/
+       public static PropertyEditor findEditor(Class editedClass) {
+               try {
+
+               Class found = (Class)editors.get(editedClass);
+               if(found != null) {
+                       return (PropertyEditor)found.newInstance();
+               }
+
+               try {
+                       found = Class.forName(editedClass.getName()+"Editor");
+                       registerEditor(editedClass,found);
+                       return (PropertyEditor)found.newInstance();
+               } catch(ClassNotFoundException E) {
+               }
+
+               String appendName = "." + ClassHelper.getTruncatedClassName(editedClass) + "Editor";
+               synchronized(editorSearchPath) {
+                       for(int i=0;i<editorSearchPath.length;i++) {
+                               try {
+                                       found = Class.forName(editorSearchPath[i] + appendName);
+                                       registerEditor(editedClass,found);
+                                       return (PropertyEditor)found.newInstance();
+                               } catch(ClassNotFoundException E) {
+                               }
+                       }
+               }
+
+               } catch(InstantiationException E) {
+               } catch(IllegalAccessException E) {
+               }
+               return null;
+       }
+
+       /** Get the editor search path.
+        ** As a minor departure from the spec, the default value
+        ** for the editor search path is "gnu.java.beans.editors",
+        ** "sun.beans.editors".
+        ** @return the editor search path.
+        **/
+       public static String[] getEditorSearchPath() {
+               return editorSearchPath;
+       }
+
+       /** Set the editor search path.
+        ** @param editorSearchPath the new value for the editor
+        **        search path.
+        **/
+       public static void setEditorSearchPath(String[] editorSearchPath) {
+               synchronized(editorSearchPath) {
+                       PropertyEditorManager.editorSearchPath = editorSearchPath;
+               }
+       }
+}
diff --git a/libjava/java/beans/PropertyEditorSupport.java b/libjava/java/beans/PropertyEditorSupport.java
new file mode 100644 (file)
index 0000000..6fadacc
--- /dev/null
@@ -0,0 +1,195 @@
+/* java.beans.PropertyEditorSupport
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** PropertyEditorSupport helps with PropertyEditors,
+ ** implementing base functionality that they usually must
+ ** have but which is a pain to implement.  You may extend
+ ** from this class or use it as a standalone.<P>
+ **
+ ** This class does not do any painting or actual editing.
+ ** For that, you must use or extend it.  See the
+ ** PropertyEditor class for better descriptions of what
+ ** the various methods do.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ **/
+
+public class PropertyEditorSupport implements PropertyEditor {
+       Object eventSource;
+       Object val;
+       PropertyChangeSupport pSupport;
+
+       /** Call this constructor when you are deriving from
+        ** PropertyEditorSupport.
+        **/
+       protected PropertyEditorSupport() {
+               this.eventSource = this;
+               this.pSupport = new PropertyChangeSupport(this);
+       }
+
+       /** Call this constructor when you are using
+        ** PropertyEditorSupport as a helper object.
+        ** @param eventSource the source to use when firing
+        **        property change events.
+        **/
+       protected PropertyEditorSupport(Object eventSource) {
+               this.eventSource = eventSource;
+               this.pSupport = new PropertyChangeSupport(this);
+       }
+
+       /** Set the current value of the property.
+        ** <STRONG>Implementation Note</STRONG> Sun does not
+        ** state what exactly this version of the method does.
+        ** Thus, in this implementation, it sets the value, and
+        ** then if the old and new values are different, it
+        ** fires a property change event with no property name
+        ** and the old and new values.
+        ** @param val the new value for the property.
+        **/
+       public void setValue(Object val) {
+               Object oldVal = val;
+               this.val = val;
+               if(!oldVal.equals(val)) {
+                       pSupport.firePropertyChange(null,oldVal,val);
+               }
+       }
+
+       /** Get the current value of the property.
+        ** @return the current value of the property.
+        **/
+       public Object getValue() {
+               return val;
+       }
+
+       /** Get whether this object is paintable or not.
+        ** @return <CODE>false</CODE>
+        **/
+       public boolean isPaintable() {
+               return false;
+       }
+
+       /** Paint this object.  This class does nothing in
+        ** this method.
+        **/
+       public void paintValue(java.awt.Graphics g, java.awt.Rectangle r) {
+       }
+
+       /** Get the Java initialization String for the current
+        ** value of the Object.  This class returns gibberish or
+        ** null (though the spec does not say which).<P>
+        ** <STRONG>Implementation Note:</STRONG> This class
+        ** returns the string "@$#^" to make sure the code will
+        ** be broken, so that you will know to override it when
+        ** you create your own property editor.
+        ** @return the Java initialization string.
+        **/
+       public String getJavaInitializationString() {
+               return "@$#^";
+       }
+
+       /** Get the value as text.
+        ** In this class, you cannot count on getAsText() doing
+        ** anything useful, although in this implementation I
+        ** do toString().
+        ** @return the value as text.
+        **/
+       public String getAsText() {
+               return val != null ? val.toString() : "null";
+       }
+
+       /** Set the value as text.
+        ** In this class, you cannot count on setAsText() doing
+        ** anything useful across implementations.
+        ** <STRONG>Implementation Note:</STRONG> In this
+        ** implementation it checks if the String is "null", and
+        ** if it is, sets the value to null, otherwise it throws
+        ** an IllegalArgumentException.
+        ** @param s the text to convert to a new value.
+        ** @exception IllegalArgumentException if the text is
+        **            malformed.
+        **/
+       public void setAsText(String s) throws IllegalArgumentException {
+               if(s.equals("null")) {
+                       setValue(null);
+               } else {
+                       throw new IllegalArgumentException();
+               }
+       }
+
+       /** Returns a list of possible choices for the value.
+        ** @return <CODE>null</CODE>
+        **/
+       public String[] getTags() {
+               return null;
+       }
+
+       /** Return a custom component to edit the value.
+        ** @return <CODE>null</CODE> in this class.
+        **/
+       public java.awt.Component getCustomEditor() {
+               return null;
+       }
+
+       /** Find out whether this property editor supports a
+        ** custom component to edit its value.
+        ** @return <CODE>false</CODE> in this class.
+        **/
+       public boolean supportsCustomEditor() {
+               return false;
+       }
+
+       /** Add a property change listener to this property editor.
+        ** @param l the listener to add.
+        **/
+       public void addPropertyChangeListener(PropertyChangeListener l) {
+               pSupport.addPropertyChangeListener(l);
+       }
+
+       /** Remove a property change listener from this property editor.
+        ** @param l the listener to remove.
+        **/
+       public void removePropertyChangeListener(PropertyChangeListener l) {
+               pSupport.removePropertyChangeListener(l);
+       }
+
+
+       /** Notify people that we've changed, although we don't
+        ** tell them just how.  The only thing I can think of to
+        ** send in the event is the new value (since the old value
+        ** is unavailable and there is no property name).
+        ** I confess I do not understand the point of this method.
+        **/
+       public void firePropertyChange() {
+               pSupport.firePropertyChange(null,null,val);
+       }
+}
+
diff --git a/libjava/java/beans/PropertyVetoException.java b/libjava/java/beans/PropertyVetoException.java
new file mode 100644 (file)
index 0000000..51a5642
--- /dev/null
@@ -0,0 +1,55 @@
+/* java.beans.PropertyVetoException
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** PropertyVetoException is thrown when a VetoableChangeListener doesn't like the proposed change.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 31 May 1998
+ ** @see java.beans.VetoableChangeListener
+ **/
+
+public class PropertyVetoException extends Exception {
+       PropertyChangeEvent changeEvent;
+
+       /** Instantiate this exception with the given message and property change.
+        ** @param msg the reason for the veto.
+        ** @param changeEvent the PropertyChangeEvent that was thrown.
+        **/
+       public PropertyVetoException(String msg, PropertyChangeEvent changeEvent) {
+               super(msg);
+               this.changeEvent = changeEvent;
+       }
+
+       /** Get the PropertyChange event that was vetoed. **/
+       public PropertyChangeEvent getPropertyChangeEvent() {
+               return changeEvent;
+       }
+}
diff --git a/libjava/java/beans/SimpleBeanInfo.java b/libjava/java/beans/SimpleBeanInfo.java
new file mode 100644 (file)
index 0000000..e8b6777
--- /dev/null
@@ -0,0 +1,127 @@
+/* java.beans.SimpleBeanInfo
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+import java.awt.*;
+
+/**
+ ** SimpleBeanInfo is a class you may extend to more easily
+ ** provide select information to the Introspector.  It
+ ** implements all of the methods in BeanInfo by returning
+ ** null and forces the Introspector to behave exactly as
+ ** if there were no BeanInfo class at all (Introspecting
+ ** everything).<P>
+ **
+ ** Overriding one or two of these functions
+ ** to give explicit information on only those things you
+ ** wish to give explicit information is perfectly safe,
+ ** and even desirable.<P>
+ **
+ ** See the BeanInfo class for information on what the
+ ** various methods actually do.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ ** @see java.beans.BeanInfo
+ **/
+
+public class SimpleBeanInfo implements BeanInfo {
+       /** Force Introspection of the general bean info.
+        ** @return <CODE>null</CODE>.
+        **/
+       public BeanDescriptor getBeanDescriptor() {
+               return null;
+       }
+
+       /** Force Introspection of the events this Bean type
+        ** fires.
+        ** @return <CODE>null</CODE>
+        **/
+       public EventSetDescriptor[] getEventSetDescriptors() {
+               return null;
+       }
+
+       /** Say that there is no "default" event set.
+        ** @return <CODE>-1</CODE>.
+        **/
+       public int getDefaultEventIndex() {
+               return -1;
+       }
+
+       /** Force Introspection of the Bean properties.
+        ** @return <CODE>null</CODE>.
+        **/
+       public PropertyDescriptor[] getPropertyDescriptors() {
+               return null;
+       }
+
+       /** Say that there is no "default" property.
+        ** @return <CODE>-1</CODE>.
+        **/
+       public int getDefaultPropertyIndex() {
+               return -1;
+       }
+
+       /** Force Introspection of the Bean's methods.
+        ** @return <CODE>null</CODE>.
+        **/
+       public MethodDescriptor[] getMethodDescriptors() {
+               return null;
+       }
+
+       /** Tell the Introspector to go look for other BeanInfo
+        ** itself.
+        ** @return <CODE>null</CODE>.
+        **/
+       public BeanInfo[] getAdditionalBeanInfo() {
+               return null;
+       }
+
+       /** Say that this Bean has no icons.
+        ** @param iconType the type of icon
+        ** @return <CODE>null</CODE>.
+        **/
+       public Image getIcon(int iconType) {
+               return null;
+       }
+
+       /** Helper method to load an image using the Bean class
+        ** getResource() method on the BeanInfo class (using
+        ** getClass(), since you'll extend this class to get
+        ** the BeanInfo).  Basically it's assumed that the Bean
+        ** and its BeanInfo are both loaded by the same
+        ** ClassLoader, generally a reasonable assumption.
+        ** @param location the URL relative
+        ** @return the Image in question.
+        **/
+       public Image loadImage(String location) {
+               return Toolkit.getDefaultToolkit().getImage(getClass().getResource(location));
+       }
+}
+
diff --git a/libjava/java/beans/VetoableChangeListener.java b/libjava/java/beans/VetoableChangeListener.java
new file mode 100644 (file)
index 0000000..253d712
--- /dev/null
@@ -0,0 +1,62 @@
+/* java.beans.VetoableChangeListener
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ ** VetoableChangeListener allows a class to monitor
+ ** proposed changes to properties of a Bean and, if
+ ** desired, prevent them from occurring.<P>
+ **
+ ** A vetoableChange() event will be fired <EM>before</EM>
+ ** the property has changed.  If any listener rejects the
+ ** change by throwing the PropertyChangeException, a new
+ ** vetoableChange() event will be fired to all listeners
+ ** who received a vetoableChange() event in the first
+ ** place informing them of a reversion to the old value.
+ ** The value, of course, never actually changed.<P>
+ **
+ ** <STRONG>Note:</STRONG> This class may not be reliably
+ ** used to determine whether a property has actually
+ ** changed.  Use the PropertyChangeListener interface
+ ** for that instead.
+ **
+ ** @author John Keiser
+ ** @version 1.1.0, 29 Jul 1998
+ ** @since JDK1.1
+ ** @see java.beans.PropertyChangeListener
+ ** @see java.beans.VetoableChangeSupport
+ **/
+
+public interface VetoableChangeListener {
+       /** Fired before a Bean's property changes.
+        ** @param e the change (containing the old and new values)
+        ** @exception PropertyChangeException if the listener
+        **            does not desire the change to be made.
+        **/
+       public abstract void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException;
+}
diff --git a/libjava/java/beans/VetoableChangeSupport.java b/libjava/java/beans/VetoableChangeSupport.java
new file mode 100644 (file)
index 0000000..6d0ff0c
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * java.beans.VetoableChangeSupport: part of the Java Class Libraries project.
+ * Copyright (C) 1998 Free Software Foundation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ */
+
+package java.beans;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ ** VetoableChangeSupport makes it easy to fire vetoable
+ ** change events and handle listeners as well as reversion
+ ** of old values when things go wrong.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.2.0, 15 Mar 1998
+ **/
+
+public class VetoableChangeSupport implements java.io.Serializable {
+       Hashtable propertyListeners = new Hashtable();
+       Vector listeners = new Vector();
+       Object bean;
+
+       /** Create VetoableChangeSupport to work with a specific
+        ** source bean.
+        ** @param bean the source bean to use.
+        **/
+       public VetoableChangeSupport(Object bean) {
+               this.bean = bean;
+       }
+
+       /** Adds a VetoableChangeListener to the list of listeners.
+        ** All property change events will be sent to this listener.
+        ** <P>
+        **
+        ** The listener add is not unique: that is, <em>n</em> adds with
+        ** the same listener will result in <em>n</em> events being sent
+        ** to that listener for every property change.
+        ** <P>
+        **
+        ** Adding a null listener will cause undefined behavior.
+        **
+        ** @param l the listener to add.
+        **/
+       public void addVetoableChangeListener(VetoableChangeListener l) {
+               listeners.addElement(l);
+       }
+
+       /** Adds a VetoableChangeListener listening on the specified property.
+        ** Events will be sent to the listener for that particular property.
+        ** <P>
+        **
+        ** The listener add is not unique; that is, <em>n</em> adds on a
+        ** particular property for a particular listener will result in
+        ** <em>n</em> events being sent to that listener when that
+        ** property is changed.
+        ** <P>
+        **
+        ** The effect is cumulative, too; if you are registered to listen
+        ** to receive events on all property changes, and then you
+        ** register on a particular property, you will receive change
+        ** events for that property twice.
+        ** <P>
+        **
+        ** Adding a null listener will cause undefined behavior.
+        **
+        ** @param propertyName the name of the property to listen on.
+        ** @param l the listener to add.
+        **/
+       public void addVetoableChangeListener(String propertyName, VetoableChangeListener l) {
+               synchronized(propertyListeners) {
+                       Vector v = (Vector)propertyListeners.get(propertyName);
+                       try {
+                               v.addElement(l);
+                       } catch(NullPointerException e) {
+                               /* If v is not found, create a new vector. */
+                               v = new Vector();
+                               v.addElement(l);
+                               propertyListeners.put(propertyName, v);
+                       }
+               }
+       }
+
+       /** Removes a VetoableChangeListener from the list of listeners.
+        ** If any specific properties are being listened on, they must
+        ** be deregistered by themselves; this will only remove the
+        ** general listener to all properties.
+        ** <P>
+        **
+        ** If <code>add()</code> has been called multiple times for a
+        ** particular listener, <code>remove()</code> will have to be
+        ** called the same number of times to deregister it.
+        **
+        ** @param l the listener to remove.
+        **/
+       public void removeVetoableChangeListener(VetoableChangeListener l) {
+               listeners.removeElement(l);
+       }
+
+       /** Removes a VetoableChangeListener from listening to a specific property.
+        ** <P>
+        **
+        ** If <code>add()</code> has been called multiple times for a
+        ** particular listener on a property, <code>remove()</code> will
+        ** have to be called the same number of times to deregister it.
+        **
+        ** @param propertyName the property to stop listening on.
+        ** @param l the listener to remove.
+        **/
+       public void removeVetoableChangeListener(String propertyName, VetoableChangeListener l) {
+               synchronized(propertyListeners) {
+                       Vector v = (Vector)propertyListeners.get(propertyName);
+                       try {
+                               v.removeElement(l);
+                               if(v.size() == 0) {
+                                       propertyListeners.remove(propertyName);
+                               }
+                       } catch(NullPointerException e) {
+                               /* if v is not found, do nothing. */
+                       }
+               }
+       }
+
+
+       /** Fire a VetoableChangeEvent to all the listeners.
+        ** If any listener objects, a reversion event will be sent to
+        ** those listeners who received the initial event.
+        **
+        ** @param proposedChange the event to send.
+        ** @exception PropertyVetoException if the change is vetoed.
+        **/
+       public void fireVetoableChange(PropertyChangeEvent proposedChange) throws PropertyVetoException {
+               int currentListener=0;
+               try {
+                       for(;currentListener<listeners.size();currentListener++) {
+                               ((VetoableChangeListener)listeners.elementAt(currentListener)).vetoableChange(proposedChange);
+                       }
+               } catch(PropertyVetoException e) {
+                       PropertyChangeEvent reversion = new PropertyChangeEvent(proposedChange.getSource(),proposedChange.getPropertyName(),proposedChange.getNewValue(),proposedChange.getOldValue());
+                       for(int sendAgain=0;sendAgain<currentListener;sendAgain++) {
+                               try {
+                                       ((VetoableChangeListener)listeners.elementAt(sendAgain)).vetoableChange(reversion);
+                               } catch(PropertyVetoException e2) {
+                               }
+                       }
+                       throw e;
+               }
+
+               Vector moreListeners = (Vector)propertyListeners.get(proposedChange.getPropertyName());
+               if(moreListeners != null) {
+                       try {
+                               for(currentListener = 0; currentListener < moreListeners.size(); currentListener++) {
+                                       ((VetoableChangeListener)moreListeners.elementAt(currentListener)).vetoableChange(proposedChange);
+                               }
+                       } catch(PropertyVetoException e) {
+                               PropertyChangeEvent reversion = new PropertyChangeEvent(proposedChange.getSource(),proposedChange.getPropertyName(),proposedChange.getNewValue(),proposedChange.getOldValue());
+                               for(int sendAgain=0;sendAgain<listeners.size();sendAgain++) {
+                                       try {
+                                               ((VetoableChangeListener)listeners.elementAt(currentListener)).vetoableChange(proposedChange);
+                                       } catch(PropertyVetoException e2) {             
+                                       }
+                               }
+
+                               for(int sendAgain=0;sendAgain<currentListener;sendAgain++) {
+                                       try {
+                                               ((VetoableChangeListener)moreListeners.elementAt(sendAgain)).vetoableChange(reversion);
+                                       } catch(PropertyVetoException e2) {
+                                       }
+                               }
+                               throw e;
+                       }
+               }
+       }
+
+       /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners.
+        ** If any listener objects, a reversion event will be sent to
+        ** those listeners who received the initial event.
+        **
+        ** @param propertyName the name of the property that
+        ** changed.
+        ** @param oldVal the old value.
+        ** @param newVal the new value.
+        ** @exception PropertyVetoException if the change is vetoed.
+        **/
+       public void fireVetoableChange(String propertyName, Object oldVal, Object newVal) throws PropertyVetoException {
+               fireVetoableChange(new PropertyChangeEvent(bean,propertyName,oldVal,newVal));
+       }
+
+       /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners.
+        ** If any listener objects, a reversion event will be sent to
+        ** those listeners who received the initial event.
+        **
+        ** @param propertyName the name of the property that
+        ** changed.
+        ** @param oldVal the old value.
+        ** @param newVal the new value.
+        ** @exception PropertyVetoException if the change is vetoed.
+        **/
+       public void fireVetoableChange(String propertyName, boolean oldVal, boolean newVal) throws PropertyVetoException {
+               fireVetoableChange(new PropertyChangeEvent(bean,propertyName,new Boolean(oldVal),new Boolean(newVal)));
+       }
+
+       /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners.
+        ** If any listener objects, a reversion event will be sent to
+        ** those listeners who received the initial event.
+        **
+        ** @param propertyName the name of the property that
+        ** changed.
+        ** @param oldVal the old value.
+        ** @param newVal the new value.
+        ** @exception PropertyVetoException if the change is vetoed.
+        **/
+       public void fireVetoableChange(String propertyName, int oldVal, int newVal) throws PropertyVetoException {
+               fireVetoableChange(new PropertyChangeEvent(bean,propertyName,new Integer(oldVal),new Integer(newVal)));
+       }
+
+
+       /** Tell whether the specified property is being listened on or not.
+        ** This will only return <code>true</code> if there are listeners
+        ** on all properties or if there is a listener specifically on this
+        ** property.
+        **
+        ** @param propertyName the property that may be listened on
+        ** @return whether the property is being listened on
+        **/
+       public boolean hasListeners(String propertyName) {
+               return listeners.size() > 0  || propertyListeners.get(propertyName) != null;
+       }
+}
diff --git a/libjava/java/beans/Visibility.java b/libjava/java/beans/Visibility.java
new file mode 100644 (file)
index 0000000..ca8c404
--- /dev/null
@@ -0,0 +1,74 @@
+/* java.beans.Visibility
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans;
+
+/**
+ * Visibility is an interface a Bean may implement so that the environment
+ * can tell the Bean whether there is a GUI or not, and so that the Bean
+ * can tell the environment whether it needs one or can run without one.
+ * <P>
+ *
+ * Sun decided not to use standard Introspection patterns so that these
+ * methods did not get included when the Introspector made its sweep on
+ * the class.
+ *
+ * @author John Keiser
+ * @since JDK1.1
+ * @version 1.1.0, 29 Jul 1998
+ */
+
+public interface Visibility {
+       /**
+        * Tells whether the Bean can run without a GUI or not.
+        * @return false if Bean can run without a GUI, else true.
+        */
+       public abstract boolean needsGui();
+
+       /**
+        * Tells whether Bean is trying not to use the GUI.
+        * If needsGui() is true, this method should always return false.
+        * @return true if definitely not using GUI, otherwise false.
+        */
+       public abstract boolean avoidingGui();
+
+       /**
+        * Tells the Bean not to use GUI methods.
+        * If needsGUI() is false, then after this method is called,
+        * avoidingGui() should return true.
+        */
+       public abstract void dontUseGui();
+
+       /**
+        * Tells the Bean it may use the GUI.
+        * The Bean is not required to use the GUI in this case, it is
+        * merely being <EM>permitted</EM> to use it.  If needsGui() is
+        * false, avoidingGui() may return true or false after this method
+        * is called.
+        */
+       public abstract void okToUseGui();
+}
diff --git a/libjava/java/beans/beancontext/BeanContext.java b/libjava/java/beans/beancontext/BeanContext.java
new file mode 100644 (file)
index 0000000..d5274d8
--- /dev/null
@@ -0,0 +1,261 @@
+/* java.beans.beancontext.BeanContext
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.util.Collection;
+import java.beans.Visibility;
+import java.beans.DesignMode;
+import java.net.URL;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * Acts as a container for sub-beans and as a sub-bean,
+ * so that an entire hierarchy of beans can be made up of
+ * <code>BeanContext</code>s.
+ * <P>
+ *
+ * Since I can't sprinkle the <code>Collections</code> interface
+ * documentation with special information for <code>BeanContext</code>
+ * implementors, I'll have to document special requirements for
+ * implementors of those functions here.
+ * <P>
+ *
+ * <code><strong>add()</strong></code> or <code>addAll()</code>:
+ * <br>
+ * <OL>
+ *   <LI>
+ *     May add any <code>Object</code> into the hierarchy as well as a
+ *     <code>BeanContextChild</code>, <code>BeanContext</code> or
+ *     <code>BeanContextProxy</code> object.
+ *     This way, any Bean can be in the hierarchy.
+ *   </LI>
+ *   <LI>
+ *     Must synchronize on <code>BeanContext.globalHierarchyLock</code>.
+ *   </LI>
+ *   <LI>
+ *     Don't add the <code>Object</code> if it's already there (only once
+ *     per <code>BeanContext</code>).
+ *   </LI>
+ *   <LI>
+ *     If it is a <code>BeanContextChild</code> implementor, call
+ *     <code>setBeanContext()</code> on it.  If it's a
+ *     <code>BeanContextProxy</code> implementor, call
+ *     <code>getBeanContextProxy().setBeanContext()</code> on it.
+ *     If <code>setBeanContext()</code> vetoes the change, back out
+ *     all changes so far and throw <code>IllegalStateException</code>.
+ *   </LI>
+ *   <LI>
+ *     If it (or its proxy) implements <code>Visibility</code>, call
+ *     <code>dontUseGui()</code> or <code>okToUseGui()</code> on it,
+ *     depending on whether you (the <code>BeanContext</code>) feel like
+ *     allowing it to use the GUI or not.
+ *   </LI>
+ *   <LI>
+ *     If it implements <code>BeanContextChild</code> or
+ *     <code>BeanContextProxy</code>, register yourself (the
+ *     <code>BeanContext</code>) as both a
+ *     <code>PropertyChangeListener</code> and
+ *     <code>VetoableChangeListener</code> on the "beanContext"
+ *     property (it may also add itself on any other properties it wishes
+ *     to).
+ *   </LI>
+ *   <LI>
+ *     If it is a listener or event source that you (the
+ *     <code>BeanContext</code>) are interested in, you may register
+ *     yourself to it or register it to you.
+ *   </LI>
+ *   <LI>
+ *     Fire a <code>java.beans.beancontext.BeanContextMembershipEvent</code>
+ *     before exiting.  <code>addAll()</code> should wait until everything
+ *     is done changing before firing the event (or events) so that if a
+ *     failure occurs, the backing-out process can proceed without any
+ *     events being fired at all.
+ *   </LI>
+ * </OL>
+ * <P>
+ *
+ * <code><strong>remove()</strong></code> or <code>removeAll()</code>:
+ * <br>
+ * <OL>
+ *   <LI>
+ *     Must synchronize on <code>BeanContext.globalHierarchyLock</code>.
+ *   </LI>
+ *   <LI>
+ *     If the specified <code>Object</code> is not a child of this
+ *     <code>BeanContext</code>, just exit without performing any actions.
+ *   </LI>
+ *   <LI>
+ *     Remove the <code>Object</code> from your collection of children.
+ *   </LI>
+ *   <LI>
+ *     If it is a <code>BeanContextChild</code> implementor, call
+ *     <code>setBeanContext(null)</code> on it.  If it's a
+ *     <code>BeanContextProxy</code> implementor, call
+ *     <code>getBeanContextProxy().setBeanContext(null)</code> on it.
+ *     If <code>setBeanContext()</code> vetoes the change, back out
+ *     all changes so far and throw <code>IllegalStateException</code>.
+ *   </LI>
+ *   <LI>
+ *     If you registered the <code>Object</code> to listen to you or
+ *     registered yourself as a listener on the <code>Object</code> during
+ *     <code>add()</code> or <code>addAll()</code>, undo the registration
+ *     bycalling the appropriate <code>removeListener()</code> method.
+ *   </LI>
+ *   <LI>
+ *     Fire a <code>java.beans.beancontext.BeanContextMembershipEvent</code>
+ *     before exiting.  <code>removeAll()</code> should wait until
+ *     everything is done changing before firing the event (or events) so
+ *     that if a failure occurs, the backing-out process can proceed
+ *     without any events being fired at all.
+ *   </LI>
+ * </OL>
+ * <P>
+ *
+ * <code>addAll()</code>, <code>removeAll()</code>,
+ * <code>retainAll()</code> and <code>clear()</code> do not need to be
+ * implemented, but may be if so desired.
+ * <P>
+ *
+ * Similarly, <code>Visibility</code> and <code>DesignMode</code> methods
+ * should propagate changed values to children that implement interfaces
+ * of the same name.
+ * <P>
+ *
+ * A hierarchy of beans is mainly useful so that different sets of beans
+ * can be established, each with their own set of resources.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContext
+       extends Collection, BeanContextChild, Visibility, DesignMode {
+
+       /**
+        * The global lock on changing any BeanContext hierarchy.
+        * It kinda sucks that there is only one lock, since there can be
+        * multiple hierarchies.  Oh well, I didn't design, I just code.
+        * <P>
+        *
+        * Methods that must (or do) synchronize on the global lock:
+        * <BR>
+        * <UL>
+        *   <LI>
+        *     Implementors of <CODE>BeanContext.add()</CODE> and <code>addAll()</code>
+        *   </LI>
+        * </UL>
+        * @fixme fill in the rest of the methods which use the global lock.
+        */
+       public static final Object globalHierarchyLock = new Object();
+
+       /** 
+        * Instantiate a Bean using this Bean's <code>ClassLoader</code>
+        * and this <code>BeanContext</code> as the parent.
+        * <P>
+        *
+        * This method exists mainly so that <code>BeanContext</code>
+        * implementations can perform extra actions on Beans that are
+        * created within them.
+        *
+        * @param beanName the name of the bean to instantiate
+        * @return the created Bean
+        *
+        * @see java.beans.Beans#instantiate(java.lang.ClassLoader,java.lang.String)
+        * @see java.beans.Beans#instantiate(java.lang.ClassLoader,java.lang.String,java.lang.BeanContext)
+        * @exception IOException if there is an I/O problem during
+        *            instantiation.
+        * @exception ClassNotFoundException if a serialized Bean's class
+        *            is not found.
+        */
+       public Object instantiateChild(String beanName)
+                        throws IOException,
+                               ClassNotFoundException;
+
+       /**
+        * Get a resource.  The <code>BeanContext</code> will typically
+        * call <code>ClassLoader.getResource()</code>, but may do it any
+        * way it wants to.  This allows a <code>BeanContext</code> to
+        * have its own set of resources separate from the rest of the
+        * system.
+        * <P>
+        *
+        * Beans should call this method on their parent rather than the
+        * associated <code>ClassLoader</code> method.
+        * <P>
+        *
+        * I am assuming, but am not entirely sure, that if a
+        * <code>BeanContext</code> cannot find a resource, its
+        * responsibility is to call the <code>getResource</code> method
+        * of its parent <code>BeanContext</code>.
+        *
+        * @return a URL to the requested resource.
+        * @param resourceName the name of the resource requested.
+        * @param requestor a reference to the child requesting the resource.
+        * @see java.lang.ClassLoader#getResource(java.lang.String)
+        */
+       public URL getResource(String resourceName, BeanContextChild requestor);
+
+       /**
+        * Get a resource as a stream.  The <code>BeanContext</code> will
+        * typically call <code>ClassLoader.getResourceAsStream()</code>,
+        * but may do it any way it wants to.  This allows a
+        * <code>BeanContext</code>'s children to have their own set of
+        * resources separate from the rest of the system.
+        * <P>
+        *
+        * Beans should call this method on their parent rather than the
+        * associated <code>ClassLoader</code> method.
+        * <P>
+        *
+        * I am assuming, but am not entirely sure, that if a
+        * <code>BeanContext</code> cannot find a resource, its
+        * responsibility is to call the <code>getResourceAsStream</code>
+        * method of its parent <code>BeanContext</code>.
+        *
+        * @return the requested resource as a stream.
+        * @param resourceName the name of the resource requested.
+        * @param requestor a reference to the child requesting the resource.
+        * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
+        */
+       public InputStream getResourceAsStream(String resourceName, BeanContextChild requestor);
+
+       /**
+        * Add a listener on changes to the membership of this
+        * <code>BeanContext</code> object.
+        * @param listener the listener to add.
+        */
+       public void addBeanContextMembershipListener(BeanContextMembershipListener listener);
+
+       /**
+        * Remove a listener on changes to the membership of this
+        * <code>BeanContext</code> object.
+        * @param listener the listener to remove.
+        */
+       public void removeBeanContextMembershipListener(BeanContextMembershipListener listener);
+}
diff --git a/libjava/java/beans/beancontext/BeanContextChild.java b/libjava/java/beans/beancontext/BeanContextChild.java
new file mode 100644 (file)
index 0000000..d8bcb5e
--- /dev/null
@@ -0,0 +1,162 @@
+/* java.beans.beancontext.BeanContextChild
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.beans.PropertyChangeListener;
+import java.beans.VetoableChangeListener;
+import java.beans.PropertyVetoException;
+
+/**
+ * Beans implement this to get information about the execution environment and its services and to be placed in the hierarchy.
+ * <P>
+ *
+ * The difference between a <code>BeanContext</code> and a
+ * <code>BeanContextChild</code>, mainly, is that a
+ * <code>BeanContext</code> may be a parent.
+ * <P>
+ *
+ * <code>BeanContextChild</code> instances will be serialized at some
+ * point in their life, but you need to make sure your bean context does
+ * not contain a serializable reference (directly or indirectly) to the
+ * parent <code>BeanContext</code>, to any of the other
+ * <code>BeanContext</code>s in the tree, or to any resources obtained
+ * via the <code>BeanContextServices</code> interface.  One way to do this
+ * is to mark any fields that contain such references as
+ * <code>transient</code>.  Another way is to use a custom serializer.
+ * <P>
+ *
+ * If you do not do this, when the <code>BeanContext</code> is serialized,
+ * all the other <code>BeanContext</code>s and other unnecessary things
+ * will be serialized along with it.
+ * <P>
+ *
+ * Before dying, a <code>BeanContextChild</code> should call
+ * <code>getBeanContext().remove(this)</code> to detach from the
+ * hierarchy and exit cleanly.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContext
+ */
+
+public interface BeanContextChild {
+       /**
+        * Set the parent <code>BeanContext</code>.
+        * <P>
+        *
+        * This method is called from <code>BeanContext.add()</code> and
+        * should not be called directly.
+        * <P>
+        *
+        * When this Object is being added to a new BeanContext or moved
+        * from an old one, a non-null value will be passed in.
+        * <P>
+        *
+        * When this Object is being removed from the current
+        * <code>BeanContext</code>, <code>setBeanContext()</code> will
+        * receive the parameter <code>null</code>.
+        * <P>
+        *
+        * When being removed from the current <code>BeanContext</code>,
+        * it is the <code>BeanContextChild</code>'s responsibility to
+        * release all services it has obtained.
+        * <P>
+        *
+        * This change should generate <code>PropertyChangeEvent</code>
+        * and <code>VetoableChangeEvent</code>s with the property name
+        * "beanContext".  If the change is vetoed, it must re-throw the
+        * exception and not change anything.  In this way, the parent
+        * <code>BeanContextChild</code>, who has registered himself with
+        * you, will have a chance to remove this child from its
+        * collection.
+        * <P>
+        *
+        * If the Bean does not wish to change the parent or be removed
+        * from one, it may throw the <code>PropertyVetoException</code>.
+        * If you veto a <code>setBeanContext(null)</code> call, then you
+        * should try your hardest to remedy whatever problem is keeping
+        * you from being removed from the <code>BeanContext</code> so
+        * that you can <em>not</em> veto it the next time.
+        * Otherwise, nasty pathological recursion stuff could occur in
+        * certain situations.
+        * <P>
+        *
+        * If you do veto the change, you must first back out any changes
+        * you made prior to the veto.  Best not to make any such changes
+        * prior to the veto in the first place.
+        * <P>
+        *
+        * This method is called from <code>BeanContext.add()</code> and
+        * should not be called directly.
+        *
+        * @param parent the new parent for the <code>BeanContextChild</code>,
+        *        or <code>null</code> to signify removal from a tree.
+        * @exception PropertyVetoException if the
+        *            <code>BeanContextChild</code> implementor does not
+        *            wish to have its parent changed.
+        */
+       public void setBeanContext(BeanContext parent)
+               throws PropertyVetoException;
+
+       /**
+        * Get the parent <code>BeanContext</code>.
+        * @return the parent <code>BeanContext</code>.
+        */
+       public BeanContext getBeanContext();
+
+       /**
+        * Add a listener that will be notified when a specific property changes.
+        * @param prop the name of the property to listen on
+        * @param listener the listener to listen on the property.
+        */
+       public void addPropertyChangeListener(String prop, PropertyChangeListener listener);
+
+       /**
+        * Remove a listener to a certain property.
+        * @param prop the name of the property being listened on
+        * @param listener the listener listening on the property.
+        */
+       public void removePropertyChangeListener(String prop, PropertyChangeListener listener);
+
+       /**
+        * Add a listener that will be notified when a specific property
+        * change is requested (a PropertyVetoException may be thrown) as
+        * well as after the change is successfully made.
+        *
+        * @param prop the name of the property to listen on
+        * @param listener the listener to listen on the property.
+        */
+       public void addVetoableChangeListener(String prop, VetoableChangeListener listener);
+
+       /**
+        * Remove a listener to a certain property.
+        * @param prop the name of the property being listened on
+        * @param listener the listener listening on the property.
+        */
+       public void removeVetoableChangeListener(String prop, VetoableChangeListener listener);
+}
diff --git a/libjava/java/beans/beancontext/BeanContextChildComponentProxy.java b/libjava/java/beans/beancontext/BeanContextChildComponentProxy.java
new file mode 100644 (file)
index 0000000..f8ef7ca
--- /dev/null
@@ -0,0 +1,49 @@
+/* java.beans.beancontext.BeanContextChildComponentProxy
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.awt.Component;
+
+/**
+ * Interface for <code>BeanContextChild</code>s which wish to associate an
+ * AWT component with them.  The proxy is provided because the
+ * <code>addPropertyChangeListener()</code> method would conflict with
+ * <code>Component</code> if you tried to extend.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextChildComponentProxy {
+       /**
+        * Get the <code>Component</code> associated with this <code>BeanContextChild</code>.
+        * @return the <code>Component</code> associated with this
+        * <code>BeanContextChild</code>.
+        */
+       public Component getComponent();
+}
diff --git a/libjava/java/beans/beancontext/BeanContextChildSupport.java b/libjava/java/beans/beancontext/BeanContextChildSupport.java
new file mode 100644 (file)
index 0000000..08d2a71
--- /dev/null
@@ -0,0 +1,356 @@
+/* java.beans.beancontext.BeanContextChildSupport
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.beans.PropertyChangeListener;
+import java.beans.VetoableChangeListener;
+import java.beans.PropertyVetoException;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeSupport;
+import java.beans.VetoableChangeSupport;
+import java.io.Serializable;
+
+/**
+ * Support for creating a <code>BeanContextChild</code>.
+ * This class contains the most common implementations of the methods in
+ * the <code>BeanContextChild</code>
+ *
+ * @specnote This class is not very well specified.  I had to "fill in the
+ *           blanks" in most places with what I thought was reasonable
+ *           behavior.  If there are problems, let me know.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextChild
+ */
+
+public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable {
+       /**
+        * The peer on which to perform <code>set</code> actions.
+        * This is here so that this class can be used as a peer.
+        * <P>
+        *
+        * When extending this class, this variable will be set to
+        * <code>this</code>.
+        */
+       public BeanContextChild beanContextChildPeer;
+
+       /**
+        * The parent <code>BeanContext</code>.
+        */
+       protected transient BeanContext beanContext;
+
+       /**
+        * If <code>setBeanContext()</code> was vetoed once before, this
+        * is set to <code>true</code> so that the next time, vetoes will
+        * be ignored.
+        */
+       protected transient boolean rejectedSetBCOnce;
+
+       /**
+        * Listeners are registered here and events are fired through here.
+        */
+       protected PropertyChangeSupport pcSupport;
+
+       /**
+        * Listeners are registered here and events are fired through here.
+        */
+       protected VetoableChangeSupport vcSupport;
+
+
+       /**
+        * Create a new <code>BeanContextChildSupport</code> with itself as the peer.
+        * This is meant to be used when you subclass
+        * <code>BeanContextChildSupport</code> to create your child.
+        */
+       public BeanContextChildSupport() {
+               this(null);
+       };
+
+       /**
+        * Create a new <code>BeanContextChildSupport</code> with the specified peer.
+        * @param peer the peer to use, or <code>null</code> to specify
+        *        <code>this</code>.
+        */
+       public BeanContextChildSupport(BeanContextChild peer) {
+               if(peer == null) {
+                       peer = this;
+               }
+
+               beanContextChildPeer = peer;
+               pcSupport = new PropertyChangeSupport(peer);
+               vcSupport = new VetoableChangeSupport(peer);
+       }
+
+       /**
+        * Set the parent <code>BeanContext</code>.
+        * <P>
+        *
+        * When this Object is being added to a new BeanContext or moved
+        * from an old one, a non-null value will be passed in.
+        * <P>
+        *
+        * When this Object is being removed from the current
+        * <code>BeanContext</code>, <code>setBeanContext()</code> will
+        * receive the parameter <code>null</code>.
+        * <P>
+        *
+        * Order of events:
+        * <OL>
+        *   <LI>
+        *     If the new <code>BeanContext</code> is the same as the old
+        *     one, nothing happens.
+        *   </LI>
+        *   <LI>
+        *     If the change has not been rejected or vetoed before, call
+        *     <code>validatePendingSetBeanContext()</code>.  If this call
+        *     returns <code>false</code>, the change is rejected and a
+        *     <code>PropertyVetoException</code> is thrown.
+        *   </LI>
+        *   <LI>
+        *     If the change has not been rejected or vetoed before,
+        *     <code>VetoableChangeEvent</code>s are fired with the name
+        *     <code>"beanContext"</code>, using the
+        *     <code>fireVetoableChange()</code> method.  If a veto
+        *     occurs, reversion events are fired using the same method,
+        *     the change is rejected, and the veto is rethrown.
+        *   </LI>
+        *   <LI>
+        *     <code>releaseBeanContextResources()</code> is called.
+        *   </LI>
+        *   <LI>
+        *     The change is made.
+        *   </LI>
+        *   <LI>
+        *     <code>PropertyChangeEvent</code>s are fired using the
+        *     <code>firePropertyChange()</code> method.
+        *   </LI>
+        *   <LI>
+        *     <code>initializeBeanContextResources()</code> is called.
+        *   </LI>
+        * </OL>
+        * <P>
+        *
+        * @param newBeanContext the new parent for the
+        *        <code>BeanContextChild</code>, or <code>null</code> to
+        *        signify removal from a tree.
+        * @exception PropertyVetoException if the
+        *            <code>BeanContextChild</code> implementor does not
+        *            wish to have its parent changed.
+        */
+       public void setBeanContext(BeanContext newBeanContext)
+               throws PropertyVetoException {
+               synchronized(beanContextChildPeer) {
+                       if(newBeanContext == beanContext)
+                               return;
+
+                       if(!rejectedSetBCOnce) {
+                               if(!validatePendingSetBeanContext(newBeanContext)) {
+                                       rejectedSetBCOnce = true;
+                                       throw new PropertyVetoException("validatePendingSetBeanContext() rejected change",
+                                               new PropertyChangeEvent(beanContextChildPeer, "beanContext", beanContext, newBeanContext));
+                               }
+                               try {
+                                       fireVetoableChange("beanContext", beanContext, newBeanContext);
+                               } catch(PropertyVetoException e) {
+                                       rejectedSetBCOnce = true;
+                                       throw e;
+                               }
+                       }
+
+                       releaseBeanContextResources();
+
+                       beanContext = newBeanContext;
+                       rejectedSetBCOnce = false;
+
+                       firePropertyChange("beanContext", beanContext, newBeanContext);
+
+                       initializeBeanContextResources();
+               }
+       }
+
+       /**
+        * Get the parent <code>BeanContext</code>.
+        * @return the parent <code>BeanContext</code>.
+        */
+       public BeanContext getBeanContext() {
+               return beanContext;
+       }
+
+       /**
+        * Get the peer (or <code>this</code> if there is no peer).
+        * @return the peer, or <code>this</code> if there is no peer.
+        */
+       public BeanContextChild getBeanContextChildPeer() {
+               return beanContextChildPeer;
+       }
+
+       /**
+        * Determine whether there is a peer.
+        * This is true iff <code>getBeanContextChildPeer() == this</code>.
+        * @return whether there is a peer.
+        */
+       public boolean isDelegated() {
+               return beanContextChildPeer == this;
+       }
+
+       /**
+        * Add a listener that will be notified when a specific property changes.
+        * @param propertyName the name of the property to listen on.
+        * @param listener the listener to listen on the property.
+        */
+       public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+               pcSupport.addPropertyChangeListener(propertyName, listener);
+       }
+
+       /**
+        * Remove a listener to a certain property.
+        * 
+        * @param propertyName the name of the property being listened on.
+        * @param listener the listener listening on the property.
+        */
+       public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+               pcSupport.removePropertyChangeListener(propertyName, listener);
+       }
+
+       /**
+        * Add a listener that will be notified when a specific property
+        * change is requested (a PropertyVetoException may be thrown) as
+        * well as after the change is successfully made.
+        *
+        * @param propertyName the name of the property to listen on.
+        * @param listener the listener to listen on the property.
+        */
+       public void addVetoableChangeListener(String propertyName, VetoableChangeListener listener) {
+               vcSupport.addVetoableChangeListener(propertyName, listener);
+       }
+
+       /**
+        * Remove a listener to a certain property.
+        *
+        * @param propertyName the name of the property being listened on
+        * @param listener the listener listening on the property.
+        */
+       public void removeVetoableChangeListener(String propertyName, VetoableChangeListener listener) {
+               vcSupport.removeVetoableChangeListener(propertyName, listener);
+       }
+
+       /**
+        * Fire a property change.
+        *
+        * @param propertyName the name of the property that changed
+        * @param oldVal the old value of the property
+        * @param newVal the new value of the property
+        */
+       public void firePropertyChange(String propertyName, Object oldVal, Object newVal) {
+               pcSupport.firePropertyChange(propertyName, oldVal, newVal);
+       }
+
+       /**
+        * Fire a vetoable property change.
+        *
+        * @param propertyName the name of the property that changed
+        * @param oldVal the old value of the property
+        * @param newVal the new value of the property
+        * @exception PropertyVetoException if the change is vetoed.
+        */
+       public void fireVetoableChange(String propertyName, Object oldVal, Object newVal)
+                        throws PropertyVetoException {
+               vcSupport.fireVetoableChange(propertyName, oldVal, newVal);
+       }
+
+       /**
+        * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked.
+        * If you have a reference to such a service, it should be
+        * discarded and may no longer function properly.
+        * <code>getService()</code> will no longer work on the specified
+        * service class after this event has been fired.
+        * <P>
+        *
+        * <EM>This method is meant to be overriden.</EM>
+        * <code>BeanContextChildSupport</code>'s implementation does
+        * nothing.
+        *
+        * @param event the service revoked event.
+        * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean)
+        */
+       public void serviceRevoked(BeanContextServiceRevokedEvent event) {
+       }
+
+       /**
+        * Called by <code>BeanContextServices</code> whenever a service is made available.
+        * <P>
+        *
+        * <EM>This method is meant to be overriden.</EM>
+        * <code>BeanContextChildSupport</code>'s implementation does
+        * nothing.
+        *
+        * @param event the service revoked event, with useful information
+        *        about the new service.
+        */
+       public void serviceAvailable(BeanContextServiceAvailableEvent event) {
+       }
+
+       /**
+        * Called by <code>setBeanContext()</code> to determine whether the set should be rejected.
+        * <P>
+        *
+        * <EM>This method is meant to be overriden.</EM>
+        * <code>BeanContextChildSupport</code>'s implementation simply
+        * returns <code>true</code>.
+        *
+        * @param newBeanContext the new parent.
+        * @return whether to allow the parent to be changed to the new
+        *         value.
+        */
+       public boolean validatePendingSetBeanContext(BeanContext newBeanContext) {
+               return true;
+       }
+
+       /**
+        * Called by <code>setBeanContext()</code> to release resources of a what will soon no longer be the parent.
+        * <P>
+        *
+        * <EM>This method is meant to be overriden.</EM>
+        * <code>BeanContextChildSupport</code>'s implementation does
+        * nothing.
+        */
+       protected void releaseBeanContextResources() {
+       }
+
+       /**
+        * Called by <code>setBeanContext()</code> to grab resources when the parent has been set.
+        * <P>
+        *
+        * <EM>This method is meant to be overriden.</EM>
+        * <code>BeanContextChildSupport</code>'s implementation does
+        * nothing.
+        */
+       protected void initializeBeanContextResources() {
+       }
+}
diff --git a/libjava/java/beans/beancontext/BeanContextContainerProxy.java b/libjava/java/beans/beancontext/BeanContextContainerProxy.java
new file mode 100644 (file)
index 0000000..28d967b
--- /dev/null
@@ -0,0 +1,52 @@
+/* java.beans.beancontext.BeanContextContainerProxy
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.awt.Container;
+
+/**
+ * Interface for <code>BeanContext</code>s which wish to associate an
+ * AWT container with them.  The proxy is provided because the
+ * <code>addPropertyChangeListener()</code> and <code>add()</code> methods
+ * would conflict with <code>Component</code> and <code>Container</code>
+ * if you tried to extend.
+ *
+ * @specnote It is unclear whether anything besides <code>BeanContext</code>s
+ *           are allowed to implement this interface.
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextContainerProxy {
+       /**
+        * Get the <code>Container</code> associated with this <code>BeanContext</code>.
+        * @return the <code>Container</code> associated with this
+        * <code>BeanContext</code>.
+        */
+       public Container getContainer();
+}
diff --git a/libjava/java/beans/beancontext/BeanContextEvent.java b/libjava/java/beans/beancontext/BeanContextEvent.java
new file mode 100644 (file)
index 0000000..0e4f20a
--- /dev/null
@@ -0,0 +1,91 @@
+/* java.beans.beancontext.BeanContextEvent
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.util.EventObject;
+
+/**
+ * Generic superclass for events fired by <code>BeanContext</code>s.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public abstract class BeanContextEvent extends EventObject {
+       /**
+        * The <code>BeanContext</code> that most recently passed this
+        * event on.
+        */
+       protected BeanContext propagatedFrom;
+
+       /**
+        * Create a new event, from the specified <code>BeanContext</code>.
+        * <code>propagatedFrom</code> will be initialized to
+        * <code>null</code>.
+        *
+        * @param source the source of the event.
+        */
+       protected BeanContextEvent(BeanContext source) {
+               super(source);
+       }
+
+       /**
+        * Get the <code>BeanContext</code> that originated this event.
+        * @return the originator of this event.
+        */
+       public BeanContext getBeanContext() {
+               return (BeanContext)getSource();
+       }
+
+       /**
+        * Get the most recent propagator of this event.
+        * If this value is <code>null</code>, you have received the event
+        * straight from the source.
+        *
+        * @return the most recent propagator of this event.
+        */
+       public BeanContext getPropagatedFrom() {
+               return propagatedFrom;
+       }
+
+       /**
+        * Tell whether this event has been propagated.
+        * @return <code>true</code> iff <code>getPropagatedFrom() != null</code>.
+        */
+       public boolean isPropagated() {
+               return propagatedFrom != null;
+       }
+
+       /**
+        * Set the most recent propagator of this event.
+        * @param propagator the most recent propagator of this event.
+        */
+       public void setPropagatedFrom(BeanContext propagator) {
+               propagatedFrom = propagator;
+       }
+}
diff --git a/libjava/java/beans/beancontext/BeanContextMembershipEvent.java b/libjava/java/beans/beancontext/BeanContextMembershipEvent.java
new file mode 100644 (file)
index 0000000..d808735
--- /dev/null
@@ -0,0 +1,102 @@
+/* java.beans.beancontext.BeanContextMembershipEvent
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.util.Collection;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * Event fired when children are added to or removed from a <code>BeanContext</code>.
+ * Whether they were added or removed depends entirely on which method
+ * of the listener interface was called.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextMembershipListener
+ */
+
+public class BeanContextMembershipEvent extends BeanContextEvent {
+       /**
+        * The children that were added or removed.
+        */
+       protected Collection children;
+
+       /**
+        * Create a new membership event.
+        * @param context the event source.
+        * @param children the children added to or removed from the source.
+        */
+       public BeanContextMembershipEvent(BeanContext context, Collection children) {
+               super(context);
+               this.children = children;
+       }
+
+       /**
+        * Create a new membership event.
+        * @param context the event source.
+        * @param children the children added to or removed from the source.
+        */
+       public BeanContextMembershipEvent(BeanContext context, Object[] children) {
+               super(context);
+               this.children = Arrays.asList(children);
+       }
+
+       /**
+        * The number of children removed or added.
+        * @return the number of children removed or added.
+        */
+       public int size() {
+               return children.size();
+       }
+
+       /**
+        * An iterator that will step through all the children.
+        * @return an iterator over all the children.
+        */
+       public Iterator iterator() {
+               return children.iterator();
+       }
+
+       /**
+        * An array of the children.
+        * @return an array of the children.
+        */
+       public Object[] toArray() {
+               return children.toArray();
+       }
+
+       /**
+        * Tell whether the <code>Object</code> is one of the children added or removed.
+        * @param child the child to check.
+        * @return whether the <code>Object</code> is added or removed.
+        */
+       public boolean contains(Object child) {
+               return children.contains(child);
+       }
+}
diff --git a/libjava/java/beans/beancontext/BeanContextMembershipListener.java b/libjava/java/beans/beancontext/BeanContextMembershipListener.java
new file mode 100644 (file)
index 0000000..fc0b5b6
--- /dev/null
@@ -0,0 +1,59 @@
+/* java.beans.beancontext.BeanContextMembershipListener
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.util.EventListener;
+
+/**
+ * This is the interface to which <code>BeanContextMembershipEvent</code>s are sent.
+ * This happens when children are added to or removed from a
+ * <code>BeanContext</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextMembershipListener extends EventListener {
+       /**
+        * When beans are added to a <code>BeanContext</code>,
+        * this method is called to fire the event.
+        *
+        * @param event the event, including which children were added.
+        * @see java.beans.beancontext.BeanContext#add(java.lang.Object)
+        */
+       public void childrenAdded(BeanContextMembershipEvent event);
+
+       /**
+        * When beans are removed from a <code>BeanContext</code>,
+        * this method is called to fire the event.
+        *
+        * @param event the event, including which children were removed.
+        * @see java.beans.beancontext.BeanContext#remove(java.lang.Object)
+        */
+       public void childrenRemoved(BeanContextMembershipEvent event);
+}
diff --git a/libjava/java/beans/beancontext/BeanContextProxy.java b/libjava/java/beans/beancontext/BeanContextProxy.java
new file mode 100644 (file)
index 0000000..129e4f8
--- /dev/null
@@ -0,0 +1,54 @@
+/* java.beans.beancontext.BeanContextProxy
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+/**
+ * Beans that wish to have a <code>BeanContextChild</code> or <code>BeanContext</code> associated with them
+ * but do not wish to implement those interfaces directly, can implement this interface.
+ * <P>
+ *
+ * Don't shoot yourself in the foot: if you already implement
+ * <code>BeanContextChild</code>, directly or indirectly, the whole
+ * workings of this package will be unpredictable because it is
+ * indeterminate as to whether the <code>BeanContextChild</code> is used
+ * in preference to its proxy or vice versa.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextProxy {
+       /**
+        * Return the <code>BeanContextChild</code> associated with this
+        * <code>Object</code>.
+        *
+        * @return the <code>BeanContextChild</code> associated with this
+        * <code>Object</code>.
+        */
+       public BeanContextChild getBeanContextProxy();
+}
diff --git a/libjava/java/beans/beancontext/BeanContextServiceAvailableEvent.java b/libjava/java/beans/beancontext/BeanContextServiceAvailableEvent.java
new file mode 100644 (file)
index 0000000..933ef3d
--- /dev/null
@@ -0,0 +1,84 @@
+/* java.beans.beancontext.BeanContextServiceAvailableEvent
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.util.Iterator;
+
+/**
+ * Event fired when new services become available through a <code>BeanContextServices</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextServicesListener
+ */
+
+public class BeanContextServiceAvailableEvent extends BeanContextEvent {
+       /**
+        * The <code>Class</code> representing the service which is now
+        * available.
+        */
+       protected Class serviceClass;
+
+       /**
+        * Create a new service available event.
+        * @param services the <code>BeanContextServices</code> through
+        *        which the service is available.  This is also the source
+        *        of the event.
+        * @param serviceClass the service class that is now available.
+        */
+       public BeanContextServiceAvailableEvent(BeanContextServices services, Class serviceClass) {
+               super(services);
+               this.serviceClass = serviceClass;
+       }
+
+       /**
+        * Get the current service selectors of the service class.
+        * This is identical to <code>getSourceAsBeanContextServices().getCurrentServiceSelectors(getServiceClass())</code>
+        * @return the current service selectors of the service class.
+        */
+       public Iterator getCurrentServiceSelectors() {
+               return getSourceAsBeanContextServices().getCurrentServiceSelectors(serviceClass);
+       }
+
+       /**
+        * Get the newly available service class.
+        * @return the service class.
+        */
+       public Class getServiceClass() {
+               return serviceClass;
+       }
+
+       /**
+        * Get the <code>BeanContextServices</code> through which the new service is available.
+        * @return the <code>BeanContextServices</code> through which the
+        *         new service is available.
+        */
+       public BeanContextServices getSourceAsBeanContextServices() {
+               return (BeanContextServices)getSource();
+       }
+}
diff --git a/libjava/java/beans/beancontext/BeanContextServiceProvider.java b/libjava/java/beans/beancontext/BeanContextServiceProvider.java
new file mode 100644 (file)
index 0000000..c7a570e
--- /dev/null
@@ -0,0 +1,129 @@
+/* java.beans.beancontext.BeanContextServiceProvider
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.util.Iterator;
+
+/**
+ * An actual factory for services.
+ * <P>
+ *
+ * It is the <code>BeanContextServiceProvider</code>'s responsibility to
+ * register itself with whatever <code>BeanContextServices</code> object
+ * it wishes to provide services through using the
+ * <code>addService()</code> method.
+ * <P>
+ *
+ * If for some reason it can no longer provide services for a particular
+ * class, this class must invoke
+ * <code>BeanContextServices.revokeService(serviceClass,this,true)</code>
+ * for all the places it has registered the service.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServiceProvider {
+       /**
+        * Get a service.
+        * Called from <code>BeanContextServices.getService().
+        * <P>
+        *
+        * If the requested service class is not available, or if this
+        * <code>BeanContextServiceProvider</code> chooses not honor the
+        * request for some reason, then this method will return
+        * <code>null</code>.
+        * <P>
+        *
+        * This method may throw unchecked exceptions, so watch out.
+        *
+        * @param services the <code>BeanContextServices</code> that wants
+        *        to get the service.  Only weak references to this will
+        *        be retained, and it will never be changed, only queried
+        *        in a read-only manner.
+        * @param requestor the actual requestor of the service.  Only
+        *        weak references to this will be retained, and it will
+        *        never be changed, only queried in a read-only manner.
+        * @param serviceClass the <code>Class</code> of the service being
+        *        requested.
+        * @param serviceSelector a parameter to customize the service
+        *        returned with.
+        * @return an instance of <code>serviceClass</code> (such that
+        *        <code>instanceof</code> serviceClass is true), or
+        *        <code>null</code>.
+        * @see java.beans.beancontext.BeanContextServices#getService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Class,java.lang.Object,java.beans.beancontext.BeanContextServiceRevokedListener)
+        */
+       public Object getService(BeanContextServices services, Object requestor, Class serviceClass, Object serviceSelector);
+
+       /**
+        * Release the service.
+        * <P>
+        *
+        * Called by <code>BeanContextServices.releaseService()</code>.
+        * <P>
+        *
+        * Most <code>BeanContextServiceProvider</code>s won't have to do
+        * anything here.
+        *
+        * @param services the <code>BeanContextServices</code> that wants
+        *        to release the service.  Only weak references to this will
+        *        be retained, and it will never be changed, only queried
+        *        in a read-only manner.
+        * @param requestor the original requestor of the service.
+        * @param service the service to relinquish
+        * @see java.beans.beancontext.BeanContextServices#releaseService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Object)
+        */
+       public void releaseService(BeanContextServices services, Object requestor, Object service);
+
+       /**
+        * Get a list of valid service selectors for the specified service class.
+        * This method is called from
+        * <code>BeanContextServices.getCurrentServiceSelectors()</code>.
+        * <P>
+        *
+        * If the specified service class does not have a finite number of
+        * valid service selectors, it should return <code>null</code>.
+        * If it takes a general <code>Integer</code> parameter, for
+        * example, you may as well return <code>null</code> or the poor
+        * soul who called this method will be iterating all day.
+        * <P>
+        *
+        * If it has no valid service selectors, it should still return an empty
+        * <code>Iterator</code>.
+        *
+        * @param services the <code>BeanContextServices</code> that wants
+        *        to get the service selectors.  Only weak references to this will
+        *        be retained, and it will never be changed, only queried
+        *        in a read-only manner.
+        * @param serviceClass the service class to get selectors for.
+        * @return a list of valid service selectors for the service
+        *         class, or <code>null</code>.
+        * @see java.beans.beancontext.BeanContextServices#getCurrentServiceSelectors(java.lang.Class)
+        */
+       public Iterator getCurrentServiceSelectors(BeanContextServices services, Class serviceClass);
+}
diff --git a/libjava/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java b/libjava/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java
new file mode 100644 (file)
index 0000000..d751f70
--- /dev/null
@@ -0,0 +1,49 @@
+/* java.beans.beancontext.BeanContextServiceProviderBeanInfo
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.beans.BeanInfo;
+
+/**
+ * <code>BeanContextServiceProvider</code>s implement this to provide information about all of the services they provide.
+ * <P>
+ *
+ * This is apparently so that you can import a bunch of services into a
+ * RAD tool and it will know about all of them and export them to the
+ * user in a readable manner.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+public interface BeanContextServiceProviderBeanInfo extends BeanInfo {
+       /**
+        * Get <code>BeanInfo</code>s for all of the service classes of this <code>BeanInfoServiceProvider</code>.
+        * @return <code>BeanInfo</code>s for all provided service classes.
+        */
+       public BeanInfo[] getServicesBeanInfo();
+}
diff --git a/libjava/java/beans/beancontext/BeanContextServiceRevokedEvent.java b/libjava/java/beans/beancontext/BeanContextServiceRevokedEvent.java
new file mode 100644 (file)
index 0000000..32520bc
--- /dev/null
@@ -0,0 +1,99 @@
+/* java.beans.beancontext.BeanContextServiceRevokedEvent
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+/**
+ * Event fired when services are revoked from a <code>BeanContextServices</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextServiceRevokedListener
+ */
+
+public class BeanContextServiceRevokedEvent extends BeanContextEvent {
+       /**
+        * The <code>Class</code> representing the service which is now
+        * available.
+        */
+       protected Class serviceClass;
+       private boolean revokeNow;
+
+       /**
+        * Create a new service revoked event.
+        * @param services the <code>BeanContextServices</code> through
+        *        which the service was available.  This is also the source
+        *        of the event.
+        * @param serviceClass the service class that is now revoked.
+        * @param revokeNow whether the revocation is immediate for all
+        *        classes or just a suggestion.
+        */
+       public BeanContextServiceRevokedEvent(BeanContextServices services, Class serviceClass, boolean revokeNow) {
+               super(services);
+               this.serviceClass = serviceClass;
+               this.revokeNow = revokeNow;
+       }
+
+       /**
+        * Get the revoked service class.
+        * @return the service class.
+        */
+       public Class getServiceClass() {
+               return serviceClass;
+       }
+
+       /**
+        * Tell whether the revoked service class is the same as the specified class.
+        * Identical to <code>getServiceClass().equals(c)</code>.
+        * @param c the class to compare.
+        * @return whether the clases are equal.
+        */
+       public boolean isServiceClass(Class c) {
+               return serviceClass.equals(c);
+       }
+
+       /**
+        * Get the <code>BeanContextServices</code> through which the service was available.
+        * @return the <code>BeanContextServices</code> through which the
+        *         service was available.
+        */
+       public BeanContextServices getSourceAsBeanContextServices() {
+               return (BeanContextServices)getSource();
+       }
+
+       /**
+        * Tell whether current instances of the revoked service are usable or not.
+        * This is determined by whether the service was revoked
+        * immediately.
+        *
+        * @return whether current instances of the revoked service are
+        *         usable.
+        */
+       public boolean isCurrentServiceInvalidNow() {
+               return revokeNow;
+       }
+}
diff --git a/libjava/java/beans/beancontext/BeanContextServiceRevokedListener.java b/libjava/java/beans/beancontext/BeanContextServiceRevokedListener.java
new file mode 100644 (file)
index 0000000..8caf357
--- /dev/null
@@ -0,0 +1,51 @@
+/* java.beans.beancontext.BeanContextServiceRevokedListener
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.util.EventListener;
+
+/**
+ * Listens for service revoke events.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServiceRevokedListener extends EventListener {
+       /**
+        * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked.
+        * If you have a reference to such a service, it should be
+        * discarded and may no longer function properly.
+        * <code>getService()</code> will no longer work on the specified
+        * service class after this event has been fired.
+        *
+        * @param event the service revoked event.
+        * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean)
+        */
+       public void serviceRevoked(BeanContextServiceRevokedEvent event);
+}
diff --git a/libjava/java/beans/beancontext/BeanContextServices.java b/libjava/java/beans/beancontext/BeanContextServices.java
new file mode 100644 (file)
index 0000000..e67687b
--- /dev/null
@@ -0,0 +1,195 @@
+/* java.beans.beancontext.BeanContextServices
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+import java.util.Iterator;
+
+/**
+ * Allows a <code>BeanContext</code> to provide services to its children.
+ *
+ * @specnote it is unclear whether a <code>BeanContextServices</code>
+ *           should delegate unhandled requests to parents.  I assume so.
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServices extends BeanContext, BeanContextServicesListener {
+       /**
+        * Register a service to make it available to others.
+        * This class may refuse to add the service based on whatever
+        * information it can gather, including whether the service
+        * provider is trusted.
+        *
+        * @param serviceClass the service class.
+        * @param provider the factory that will actually provide the service.
+        * @return whether the service was added or not.
+        */
+       public boolean addService(Class serviceClass, BeanContextServiceProvider provider);
+
+       /**
+        * Make it so that no one else can use this service.
+        * <P>
+        *
+        * If <code>revokeNow</code> is <code>false</code>, the only
+        * effect of this method is to make all subsequent calls to
+        * <code>getService()</code> on this service class fail.
+        * <P>
+        *
+        * If it is <code>true</code>, a message is also sent out to all
+        * listeners on the service and all references to it are released.
+        *
+        * @param serviceClass the service class to revoke.
+        * @param provider the service provider providing the service class.
+        * @param revokeNow whether to release all current references to
+        *        the service.
+        */
+       public void revokeService(Class serviceClass, BeanContextServiceProvider provider, boolean revokeNow);
+
+       /**
+        * Release your copy of this service.
+        * <P>
+        *
+        * If all copies of the service's class have been relinquished by
+        * the requestor, the <code>BeanContextServiceRevokedListener</code>
+        * previously registered by <code>getService()</code> will be
+        * unregistered.
+        *
+        * @param requestorChild the original <code>BeanContextChild</code>
+        *        requesting the service.
+        * @param requestor the original requestor of the service.
+        * @param service the service to relinquish
+        * @see #getService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Class,java.lang.Object,java.beans.beancontext.BeanContextServiceRevokedListener)
+        */
+       public void releaseService(BeanContextChild requestorChild, Object requestor, Object service);
+
+       /**
+        * Get a service from this <code>BeanContextServices</code>.
+        * <P>
+        *
+        * The specified listener will be registered to receive a
+        * revocation notice for the specified serviceClass.  One
+        * notification per service class per requestor object will be
+        * sent.
+        * <P>
+        *
+        * The listener will be unregistered when all services that were
+        * obtained by that requestor for that service class are released.
+        * <P>
+        *
+        * If the requested service class is not available, or if this
+        * <code>BeanContextServices</code> object chooses not honor the
+        * request because the service class has been revoked or for some
+        * other reason, then this method will return <code>null</code>.
+        * <P>
+        *
+        * This method may throw unchecked exceptions, so watch out.
+        *
+        * @specnote it is not specified what happens when two subsequent
+        *           calls are made to <code>getService()</code> with the
+        *           same requestor object and service class but different
+        *           listeners.  Which listener is to be notified?
+        *
+        * @param requestorChild the <code>BeanContextChild</code>
+        *        associated with the requestor.  Typically this will be
+        *        the same as the requestor itself, but since any
+        *        <code>Object</code>, even one outside the hierarchy, may
+        *        make a request, this parameter is necessary.  Only weak
+        *        references to this will be retained, and it will never
+        *        be changed, only queried in a read-only manner.
+        * @param requestor the actual requestor of the service.  Only
+        *        weak references to this will be retained, and it will
+        *        never be changed, only queried in a read-only manner.
+        * @param serviceClass the <code>Class</code> of the service being
+        *        requested.
+        * @param serviceSelector a parameter to customize the service
+        *        returned with.
+        * @param listener a listener that will be notified if the service
+        *        being requested is revoked.
+        * @return an instance of <code>serviceClass</code> (such that
+        *        <code>instanceof</code> serviceClass is true), or
+        *        <code>null</code>.
+        */
+       public Object getService(BeanContextChild requestorChild, Object requestor, Class serviceClass, Object serviceSelector, BeanContextServiceRevokedListener listener);
+
+       /**
+        * Get a list of all service classes supported.
+        * <P>
+        *
+        * This method must synchronize on
+        * <code>BeanContext.globalHierarchyLock</code>.
+        *
+        * @return a list of all service classes supported.
+        * @see java.beans.beancontext.BeanContext#globalHierarchyLock
+        */
+       public Iterator getCurrentServiceClasses();
+
+       /**
+        * Get a list of valid service selectors for the specified service class.
+        * <P>
+        *
+        * If the specified service class does not have a finite number of
+        * valid service selectors, it should return <code>null</code>.
+        * If it takes a general <code>Integer</code> parameter, for
+        * example, you may as well return <code>null</code> or the poor
+        * soul who called this method will be iterating all day.
+        * <P>
+        *
+        * If it has no valid service selectors, it should still return an empty
+        * <code>Iterator</code>.
+        *
+        * @param serviceClass the service class to get selectors for.
+        * @return a list of valid service selectors for the service
+        *         class, or <code>null</code>.
+        */
+       public Iterator getCurrentServiceSelectors(Class serviceClass);
+
+       /**
+        * Tell whether the specified service class is available.
+        * Iff getService() could return a non-null value for the
+        * specified service, this method will return <code>true</code>.
+        *
+        * @param serviceClass the service class to check on.
+        * @return whether the specified service class is availabe.
+        */
+       public boolean hasService(Class serviceClass);
+
+       /**
+        * Add a listener on all adds and removes of services.
+        * @param listener the listener to add.
+        */
+       public void addBeanContextServicesListener(BeanContextServicesListener listener);
+
+       /**
+        * Remove a listener on all adds and removes of services.
+        * @specnote it is not certain whether this should remove this
+        *           listener if it was specified in
+        *           <code>getService()</code>.
+        * @param listener the listener to add.
+        */
+       public void removeBeanContextServicesListener(BeanContextServicesListener listener);
+}
diff --git a/libjava/java/beans/beancontext/BeanContextServicesListener.java b/libjava/java/beans/beancontext/BeanContextServicesListener.java
new file mode 100644 (file)
index 0000000..bb55f8d
--- /dev/null
@@ -0,0 +1,45 @@
+/* java.beans.beancontext.BeanContextServicesListener
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.beans.beancontext;
+
+/**
+ * Listens for service add and revoke events.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServicesListener extends BeanContextServiceRevokedListener {
+       /**
+        * Called by <code>BeanContextServices</code> whenever a service is made available.
+        *
+        * @param event the service revoked event, with useful information
+        *        about the new service.
+        */
+       public void serviceAvailable(BeanContextServiceAvailableEvent event);
+}
diff --git a/libjava/java/io/BlockDataException.java b/libjava/java/io/BlockDataException.java
new file mode 100644 (file)
index 0000000..ef70f54
--- /dev/null
@@ -0,0 +1,39 @@
+/* BlockDataException.java -- Class used to store name and class of fields
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+//TODO: check 1.2 API to make sure this mathces
+
+class BlockDataException extends IOException
+{
+  public BlockDataException( int bytes )
+  {
+    super( bytes + " bytes are available in the next data block" );
+  }
+}
+
diff --git a/libjava/java/io/Externalizable.java b/libjava/java/io/Externalizable.java
new file mode 100644 (file)
index 0000000..045df86
--- /dev/null
@@ -0,0 +1,98 @@
+/* Externalizable.java -- Interface for saving and restoring object data
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This interface provides a way that classes can completely control how
+  * the data of their object instances  are written and read to and from 
+  * streams.  It has two methods which are used to write the data to a stream 
+  * and to read the data from a stream.  The read method must read the data 
+  * in exactly the way it was written by the write method. 
+  * <p>
+  * Note that classes which implement this interface must take into account
+  * that all superclass data must also be written to the stream as well.  
+  * The class implementing this interface must figure out how to make that
+  * happen.
+  * <p>
+  * This interface can be used to provide object persistence.  When an 
+  * object is to be stored externally, the <code>writeExternal</code> method is
+  * called to save state.  When the object is restored, an instance is
+  * created using the default no-argument constructor and the 
+  * <code>readExternal</code> method is used to restore the state.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public abstract interface Externalizable extends Serializable
+{
+
+/**
+  * This method restores an object's state by reading in the instance data
+  * for the object from the passed in stream.  Note that this stream is not
+  * a subclass of <code>InputStream</code>, but rather is a class that implements
+  * the <code>ObjectInput</code> interface.  That interface provides a mechanism for
+  * reading in Java data types from a stream.
+  * <p>
+  * Note that this method must be compatible with <code>writeExternal</code>.
+  * It must read back the exact same types that were written by that
+  * method in the exact order they were written.
+  * <p>
+  * If this method needs to read back an object instance, then the class
+  * for that object must be found and loaded.  If that operation fails,
+  * then this method throws a <code>ClassNotFoundException</code>
+  *
+  * @param in An <code>ObjectInput</code> instance for reading in the object state
+  *
+  * @exception ClassNotFoundException If the class of an object being restored cannot be found
+  * @exception IOException If any other error occurs
+  */
+public abstract void
+readExternal(ObjectInput in) throws ClassNotFoundException, IOException;
+
+/*************************************************************************/
+
+/**
+  * This method is responsible for writing the instance data of an object
+  * to the passed in stream.  Note that this stream is not a subclass of
+  * <code>OutputStream</code>, but rather is a class that implements the
+  * <code>ObjectOutput</code> interface.  That interface provides a number of methods
+  * for writing Java data values to a stream.
+  * <p>
+  * Not that the implementation of this method must be coordinated with
+  * the implementation of <code>readExternal</code>.
+  *
+  * @param out An <code>ObjectOutput</code> instance for writing the object state
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract void
+writeExternal(ObjectOutput out) throws IOException;
+
+} // interface Externalizable
+
diff --git a/libjava/java/io/InvalidClassException.java b/libjava/java/io/InvalidClassException.java
new file mode 100644 (file)
index 0000000..fd03154
--- /dev/null
@@ -0,0 +1,110 @@
+/* InvalidClassException.java -- An I/O operation was interrupted.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This exception is thrown when there is some sort of problem with a
+  * class during a serialization operation.  This could be that the
+  * versions don't match, that there are unknown datatypes in the class
+  * or that the class doesn't have a default no-arg constructor.
+  * <p>
+  * The field <code>classname</code> will contain the name of the
+  * class that caused the problem if known.  The getMessage() method
+  * for this exception will always include the name of that class
+  * if known.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public class InvalidClassException extends ObjectStreamException
+{
+
+/*
+ * Instance Variables
+ */
+
+/**
+  * The name of the class which encountered the error.
+  */
+public String classname;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+  * Create a new InvalidClassException with a descriptive error message String
+  *
+  * @param message The descriptive error message
+  */
+public
+InvalidClassException(String message)
+{
+  super(message);
+}
+
+/*************************************************************************/
+
+/**
+  * Create a new InvalidClassException with a descriptive error message 
+  * String, and the name of the class that caused the problem.
+  * 
+  * @param classname The number of bytes tranferred before the interruption
+  * @param message The descriptive error message
+  */
+public
+InvalidClassException(String classname, String message)
+{
+  super(message);
+  this.classname = classname;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+  * Returns the descriptive error message for this exception.  It will
+  * include the class name that caused the problem if known.  This method
+  * overrides Throwable.getMessage()
+  *
+  * @return A descriptive error message
+  */
+public String
+getMessage()
+{
+  return(super.getMessage() + ": " + classname);
+}
+
+} // class InvalidClassException
+
diff --git a/libjava/java/io/InvalidObjectException.java b/libjava/java/io/InvalidObjectException.java
new file mode 100644 (file)
index 0000000..705082a
--- /dev/null
@@ -0,0 +1,57 @@
+/* InvalidObjectException.java -- An I/O operation was interrupted.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This exception is thrown when an object fails a validation test
+  * during serialization.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public class InvalidObjectException extends ObjectStreamException
+{
+
+/*
+ * Constructors
+ */
+
+/**
+  * Create a new InvalidObjectException with a descriptive error message String
+  *
+  * @param message The descriptive error message
+  */
+public
+InvalidObjectException(String message)
+{
+  super(message);
+}
+
+} // class InvalidObjectException
+
diff --git a/libjava/java/io/NotActiveException.java b/libjava/java/io/NotActiveException.java
new file mode 100644 (file)
index 0000000..f628a3b
--- /dev/null
@@ -0,0 +1,68 @@
+/* NotActiveException.java -- Unexpected end of file exception
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This exception is thrown when a problem occurs due to the fact that
+  * serialization is not active.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public class NotActiveException extends ObjectStreamException
+{
+
+/*
+ * Constructors
+ */
+
+/**
+  * Create a new NotActiveException without a descriptive error message
+  */
+public
+NotActiveException()
+{
+  super();
+}
+
+/*************************************************************************/
+
+/**
+  * Create a new NotActiveException with a descriptive error message String
+  *
+  * @param message The descriptive error message
+  */
+public
+NotActiveException(String message)
+{
+  super(message);
+}
+
+} // class NotActiveException
+
diff --git a/libjava/java/io/NotSerializableException.java b/libjava/java/io/NotSerializableException.java
new file mode 100644 (file)
index 0000000..d1e0bd2
--- /dev/null
@@ -0,0 +1,69 @@
+/* NotSerializableException.java -- Unexpected end of file exception
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This exception is thrown when a class may not be serialized.  The
+  * descriptive message will consist of the name of the class in question.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public class NotSerializableException extends ObjectStreamException
+{
+
+/*
+ * Constructors
+ */
+
+/**
+  * Create a new NotSerializableException without a descriptive error message
+  */
+public
+NotSerializableException()
+{
+  super();
+}
+
+/*************************************************************************/
+
+/**
+  * Create a new NotSerializableException with a descriptive error message String
+  * This should be the name of the class that cannot be serialized.
+  *
+  * @param message The descriptive error message
+  */
+public
+NotSerializableException(String message)
+{
+  super(message);
+}
+
+} // class NotSerializableException
+
diff --git a/libjava/java/io/ObjectInput.java b/libjava/java/io/ObjectInput.java
new file mode 100644 (file)
index 0000000..ef23fa9
--- /dev/null
@@ -0,0 +1,147 @@
+/* ObjectInput.java -- Read object data from a stream
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io; 
+
+/**
+  * This interface extends the <code>DataInput</code> interface to provide a
+  * facility to read objects as well as primitive types from a stream.  It
+  * also has methods that allow input to be done in a manner similar to
+  * <code>InputStream</code>
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public abstract interface ObjectInput extends DataInput
+{
+
+/**
+  * This method returns the number of bytes that can be read without
+  * blocking.
+  *
+  * @return The number of bytes available before blocking
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract int
+available() throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method reading a byte of data from a stream.  It returns that byte
+  * as an int.  This method blocks if no data is available to be read.
+  * 
+  * @return The byte of data read
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract int
+read() throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method reads raw bytes and stores them them a byte array buffer.
+  * Note that this method will block if no data is available.  However, 
+  * it will not necessarily block until it fills the entire buffer.  That is,
+  * a "short count" is possible.
+  *
+  * @param buf The byte array to receive the data read
+  *
+  * @return The actual number fo bytes read or -1 if end of stream
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract int
+read(byte[] buf) throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method reads raw bytes and stores them in a byte array buffer
+  * <code>buf</code> starting at position <code>offset</code> into the buffer.  A 
+  * maximum of <code>len</code> bytes will be read.  Note that this method
+  * blocks if no data is available, but will not necessarily block until
+  * it can read <code>len</code> bytes of data.  That is, a "short count" is
+  * possible.
+  *
+  * @param buf The byte array to receive the data read
+  * @param offset The offset into @code{buf} to start storing data
+  * @param len The maximum number of bytes to read
+  *
+  * @return The actual number fo bytes read or -1 if end of stream
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract int
+read(byte[] buf, int offset, int len) throws IOException;
+
+/*************************************************************************/
+
+/**
+  * Reads an object instance and returns it.  If the class for the object
+  * being read cannot be found, then a ClassNotFoundException will
+  * be thrown.
+  *
+  * @return The object instance that was read
+  *
+  * @exception ClassNotFoundException If a class for the object cannot be found
+  * @exception IOException If an error occurs
+  */
+public abstract Object
+readObject() throws ClassNotFoundException, IOException;
+
+/*************************************************************************/
+
+/**
+  * This method causes the specified number of bytes to be read and
+  * discarded.  It is possible that fewer than the requested number of bytes
+  * will actually be skipped.
+  *
+  * @param num_bytes The number of bytes to skip
+  *
+  * @return The actual number of bytes skipped
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract long
+skip(long num_bytes) throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method closes the input source
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract void
+close() throws IOException;
+
+} // interface ObjectInput
+
diff --git a/libjava/java/io/ObjectInputStream.java b/libjava/java/io/ObjectInputStream.java
new file mode 100644 (file)
index 0000000..7855480
--- /dev/null
@@ -0,0 +1,1467 @@
+/* ObjectInputStream.java -- Class used to read serialized objects
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import gnu.java.io.ObjectIdentityWrapper;
+import gnu.java.lang.reflect.TypeSignature;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+
+
+public class ObjectInputStream extends InputStream
+  implements ObjectInput, ObjectStreamConstants
+{
+  /**
+     Creates a new <code>ObjectInputStream</code> that will do all of
+     its reading from <code>in</code>.  This method also checks
+     the stream by reading the header information (stream magic number
+     and stream version).
+
+     @exception IOException Reading stream header from underlying
+     stream cannot be completed.
+
+     @exception StreamCorruptedException An invalid stream magic
+     number or stream version was read from the stream.
+
+     @see readStreamHeader ()
+  */
+  public ObjectInputStream (InputStream in)
+    throws IOException, StreamCorruptedException
+  {
+    this.resolveEnabled = false;
+    this.isDeserializing = false;
+    this.blockDataPosition = 0;
+    this.blockDataBytes = 0;
+    this.blockData = new byte[BUFFER_SIZE];
+    this.blockDataInput = new DataInputStream (this);
+    this.realInputStream = new DataInputStream (in);
+    this.nextOID = baseWireHandle;
+    this.objectLookupTable = new Hashtable ();
+    this.validators = new Vector ();
+    setBlockDataMode (true);
+    readStreamHeader ();
+  }
+
+
+  /**
+     Returns the next deserialized object read from the underlying stream.
+
+     This method can be overriden by a class by implementing
+     <code>private void readObject (ObjectInputStream)</code>.
+
+     If an exception is thrown from this method, the stream is left in
+     an undefined state.
+
+     @exception ClassNotFoundException The class that an object being
+     read in belongs to cannot be found.
+
+     @exception IOException Exception from underlying
+     <code>InputStream</code>.
+  */
+  public final Object readObject () throws ClassNotFoundException, IOException
+  {
+    if (this.useSubclassMethod)
+      return readObjectOverride ();
+
+    boolean was_deserializing;
+
+    Object ret_val;
+    was_deserializing = this.isDeserializing;
+
+    if (! was_deserializing)
+      setBlockDataMode (false);
+
+    this.isDeserializing = true;
+
+//    DEBUG ("MARKER ");
+    byte marker = this.realInputStream.readByte ();
+
+    switch (marker)
+    {
+      case TC_BLOCKDATA:
+      case TC_BLOCKDATALONG:
+       readNextBlock (marker);
+       throw new BlockDataException (this.blockDataBytes);
+
+      case TC_NULL:
+       ret_val = null;
+       break;
+
+      case TC_REFERENCE:
+      {
+//     DEBUG ("REFERENCE ");
+       Integer oid = new Integer (this.realInputStream.readInt ());
+       ret_val = ((ObjectIdentityWrapper)
+                  this.objectLookupTable.get (oid)).object;
+       break;
+      }
+
+      case TC_CLASS:
+      {
+       ObjectStreamClass osc = (ObjectStreamClass)readObject ();
+       Class clazz = osc.forClass ();
+       assignNewHandle (clazz);
+       ret_val = clazz;
+       break;
+      }
+
+      case TC_CLASSDESC:
+      {
+//     DEBUG ("CLASSDESC NAME ");
+       String name = this.realInputStream.readUTF ();
+//     DEBUG ("UID ");
+       long uid = this.realInputStream.readLong ();
+//     DEBUG ("FLAGS ");
+       byte flags = this.realInputStream.readByte ();
+//     DEBUG ("FIELD COUNT ");
+       short field_count = this.realInputStream.readShort ();
+       ObjectStreamField[] fields = new ObjectStreamField[field_count];
+
+       ObjectStreamClass osc = new ObjectStreamClass (name, uid,
+                                                      flags, fields);
+       assignNewHandle (osc);
+
+       for (int i=0; i < field_count; i++)
+       {
+//       DEBUG ("TYPE CODE ");
+         char type_code = (char)this.realInputStream.readByte ();
+//       DEBUG ("FIELD NAME ");
+         String field_name = this.realInputStream.readUTF ();
+         String class_name;
+
+         if (type_code == 'L' || type_code == '[')
+           class_name = (String)readObject ();
+         else
+           class_name = String.valueOf (type_code);
+
+         fields[i] =
+           new ObjectStreamField (field_name,
+                                  TypeSignature.getClassForEncoding
+                                  (class_name));
+       }
+
+       setBlockDataMode (true);
+       osc.setClass (resolveClass (osc));
+       setBlockDataMode (false);
+
+//     DEBUG ("ENDBLOCKDATA ");
+       if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
+         throw new IOException ("Data annotated to class was not consumed.");
+
+       osc.setSuperclass ((ObjectStreamClass)readObject ());
+       ret_val = osc;
+       break;
+      }
+
+      case TC_STRING:
+      {
+//     DEBUG ("STRING ");
+       String s = this.realInputStream.readUTF ();
+       ret_val = processResoultion (s, assignNewHandle (s));
+       break;
+      }
+
+      case TC_ARRAY:
+      {
+       ObjectStreamClass osc = (ObjectStreamClass)readObject ();
+       Class componenetType = osc.forClass ().getComponentType ();
+//     DEBUG ("ARRAY LENGTH ");
+       int length = this.realInputStream.readInt ();
+       Object array = Array.newInstance (componenetType, length);
+       int handle = assignNewHandle (array);
+       readArrayElements (array, componenetType);
+       ret_val = processResoultion (array, handle);
+       break;
+      }
+
+      case TC_OBJECT:
+      {
+       ObjectStreamClass osc = (ObjectStreamClass)readObject ();
+       Class clazz = osc.forClass ();
+
+       if (!Serializable.class.isAssignableFrom (clazz))
+         throw new NotSerializableException (clazz + " is not Serializable, and thus cannot be deserialized.");
+
+       if (Externalizable.class.isAssignableFrom (clazz))
+       {
+         Externalizable obj = null;
+
+         try
+         {
+           obj = (Externalizable)clazz.newInstance ();
+         }
+         catch (InstantiationException e)
+         {
+           throw new ClassNotFoundException ("Instance of " + clazz
+                                             + " could not be created");
+         }
+         catch (IllegalAccessException e)
+         {
+           throw new ClassNotFoundException ("Instance of " + clazz
+                                             + " could not be created because class or zero-argument constructor is not accessible");
+         }
+         catch (NoSuchMethodError e)
+         {
+           throw new ClassNotFoundException ("Instance of " + clazz
+                                             + " could not be created because zero-argument constructor is not defined");
+         }
+
+         int handle = assignNewHandle (obj);
+
+         boolean read_from_blocks = ((osc.getFlags () & SC_BLOCK_DATA) != 0);
+
+         if (read_from_blocks)
+           setBlockDataMode (true);
+
+         obj.readExternal (this);
+
+         if (read_from_blocks)
+           setBlockDataMode (false);
+
+         ret_val = processResoultion (obj, handle);
+         break;
+       } // end if (Externalizable.class.isAssignableFrom (clazz))
+
+       // find the first non-serializable, non-abstract
+       // class in clazz's inheritance hierarchy
+       Class first_nonserial = clazz.getSuperclass ();
+       while (Serializable.class.isAssignableFrom (first_nonserial)
+              || Modifier.isAbstract (first_nonserial.getModifiers ()))
+         first_nonserial = first_nonserial.getSuperclass ();
+
+//     DEBUGln ("Using " + first_nonserial
+//              + " as starting point for constructing " + clazz);
+
+       Object obj = null;
+       obj = newObject (clazz, first_nonserial);
+
+       if (obj == null)
+         throw new ClassNotFoundException ("Instance of " + clazz +
+                                           " could not be created");
+
+       int handle = assignNewHandle (obj);
+       this.currentObject = obj;
+       ObjectStreamClass[] hierarchy =
+         ObjectStreamClass.getObjectStreamClasses (clazz);
+
+//     DEBUGln ("Got class hierarchy of depth " + hierarchy.length);
+
+       boolean has_read;
+       for (int i=0; i < hierarchy.length; i++)
+       {
+         this.currentObjectStreamClass = hierarchy[i];
+
+//       DEBUGln ("Reading fields of "
+//                + this.currentObjectStreamClass.getName ());
+
+         has_read = true;
+
+         try
+         {
+           this.currentObjectStreamClass.forClass ().
+             getDeclaredMethod ("readObject", readObjectParams);
+         }
+         catch (NoSuchMethodException e)
+         {
+           has_read = false;
+         }
+
+         // XXX: should initialize fields in classes in the hierarchy
+         // that aren't in the stream
+         // should skip over classes in the stream that aren't in the
+         // real classes hierarchy
+         readFields (obj, this.currentObjectStreamClass.fields,
+                     has_read, this.currentObjectStreamClass);
+
+         if (has_read)
+         {
+//         DEBUG ("ENDBLOCKDATA? ");
+           if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
+             throw new IOException ("No end of block data seen for class with readObject (ObjectInputStream) method.");
+         }
+       }
+
+       this.currentObject = null;
+       this.currentObjectStreamClass = null;
+       ret_val = processResoultion (obj, handle);
+       break;
+      }
+
+      case TC_RESET:
+       clearHandles ();
+       ret_val = readObject ();
+       break;
+
+      case TC_EXCEPTION:
+      {
+       Exception e = (Exception)readObject ();
+       clearHandles ();
+       throw new WriteAbortedException ("Exception thrown during writing of stream", e);
+      }
+
+      default:
+       throw new IOException ("Unknown marker on stream");
+    }
+
+    this.isDeserializing = was_deserializing;
+
+    if (! was_deserializing)
+    {
+      setBlockDataMode (true);
+
+      if (validators.size () > 0)
+       invokeValidators ();
+    }
+
+    return ret_val;
+  }
+
+
+  /**
+     Reads the current objects non-transient, non-static fields from
+     the current class from the underlying output stream.
+
+     This method is intended to be called from within a object's
+     <code>private void readObject (ObjectInputStream)</code>
+     method.
+
+     @exception ClassNotFoundException The class that an object being
+     read in belongs to cannot be found.
+
+     @exception NotActiveException This method was called from a
+     context other than from the current object's and current class's
+     <code>private void readObject (ObjectInputStream)</code>
+     method.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+  */
+  public void defaultReadObject ()
+    throws ClassNotFoundException, IOException, NotActiveException
+  {
+    if (this.currentObject == null || this.currentObjectStreamClass == null)
+      throw new NotActiveException ("defaultReadObject called by non-active class and/or object");
+
+    if (fieldsAlreadyRead)
+      throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");
+
+    readFields (this.currentObject,
+               this.currentObjectStreamClass.fields,
+               false, this.currentObjectStreamClass);
+
+    fieldsAlreadyRead = true;
+  }
+
+
+  /**
+     Registers a <code>ObjectInputValidation</code> to be carried out
+     on the object graph currently being deserialized before it is
+     returned to the original caller of <code>readObject ()</code>.
+     The order of validation for multiple
+     <code>ObjectInputValidation</code>s can be controled using
+     <code>priority</code>.  Validators with higher priorities are
+     called first.
+
+     @see java.io.ObjectInputValidation
+
+     @exception InvalidObjectException <code>validator</code> is
+     <code>null</code>
+
+     @exception NotActiveException an attempt was made to add a
+     validator outside of the <code>readObject</code> method of the
+     object currently being deserialized
+  */
+  public void registerValidation (ObjectInputValidation validator,
+                                 int priority)
+    throws InvalidObjectException, NotActiveException
+  {
+    if (this.currentObject == null || this.currentObjectStreamClass == null)
+      throw new NotActiveException ("registerValidation called by non-active class and/or object");
+
+    if (validator == null)
+      throw new InvalidObjectException ("attempt to add a null ObjectInputValidation object");
+
+    this.validators.addElement (new ValidatorAndPriority (validator,
+                                                         priority));
+  }
+
+
+  /**
+     Called when a class is being deserialized.  This is a hook to
+     allow subclasses to read in information written by the
+     <code>annotateClass (Class)</code> method of an
+     <code>ObjectOutputStream</code>.
+
+     This implementation looks up the active call stack for a
+     <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,
+     it is used to load the class associated with <code>osc</code>,
+     otherwise, the default system <code>ClassLoader</code> is used.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+
+     @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
+  */
+  protected Class resolveClass (ObjectStreamClass osc)
+    throws ClassNotFoundException, IOException
+  {
+//    DEBUGln ("Resolving " + osc);
+
+    SecurityManager sm = System.getSecurityManager ();
+
+    if (sm == null)
+      sm = new SecurityManager () {};
+
+    ClassLoader cl = currentClassLoader (sm);
+
+    if (cl == null)
+    {
+//      DEBUGln ("No class loader found");
+      return Class.forName (osc.getName ());
+    }
+    else
+    {
+//      DEBUGln ("Using " + cl);
+      return cl.loadClass (osc.getName ());
+    }
+  }
+
+
+  /**
+     Allows subclasses to resolve objects that are read from the
+     stream with other objects to be returned in their place.  This
+     method is called the first time each object is encountered.
+
+     This method must be enabled before it will be called in the
+     serialization process.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+
+     @see enableResolveObject (boolean)
+  */
+  protected Object resolveObject (Object obj) throws IOException
+  {
+    return obj;
+  }
+
+
+  /**
+     If <code>enable</code> is <code>true</code> and this object is
+     trusted, then <code>resolveObject (Object)</code> will be called
+     in subsequent calls to <code>readObject (Object)</code>.
+     Otherwise, <code>resolveObject (Object)</code> will not be called.
+
+     @exception SecurityException This class is not trusted.
+  */
+  protected boolean enableResolveObject (boolean enable)
+    throws SecurityException
+  {
+    if (enable)
+      if (getClass ().getClassLoader () != null)
+       throw new SecurityException ("Untrusted ObjectInputStream subclass attempted to enable object resolution");
+
+    boolean old_val = this.resolveEnabled;
+    this.resolveEnabled = enable;
+    return old_val;
+  }
+
+
+  /**
+     Reads stream magic and stream version information from the
+     underlying stream.
+
+     @exception IOException Exception from underlying stream.
+
+     @exception StreamCorruptedException An invalid stream magic
+     number or stream version was read from the stream.
+  */
+  protected void readStreamHeader ()
+    throws IOException, StreamCorruptedException
+  {
+//    DEBUG ("STREAM MAGIC ");
+    if (this.realInputStream.readShort () != STREAM_MAGIC)
+      throw new StreamCorruptedException ("Invalid stream magic number");
+
+//    DEBUG ("STREAM VERSION ");
+    if (this.realInputStream.readShort () != STREAM_VERSION)
+      throw new StreamCorruptedException ("Invalid stream version number");
+  }
+
+
+  public int read () throws IOException
+  {
+    if (this.readDataFromBlock)
+    {
+      if (this.blockDataPosition >= this.blockDataBytes)
+       readNextBlock ();
+      return this.blockData[this.blockDataPosition++];
+    }
+    else
+      return this.realInputStream.read ();
+  }
+
+  public int read (byte data[], int offset, int length) throws IOException
+  {
+    if (this.readDataFromBlock)
+    {
+      if (this.blockDataPosition + length >= this.blockDataBytes)
+       readNextBlock ();
+
+      System.arraycopy (this.blockData, this.blockDataPosition,
+                       data, offset, length);
+      return length;
+    }
+    else
+      return this.realInputStream.read (data, offset, length);
+  }
+
+  public int available () throws IOException
+  {
+    if (this.readDataFromBlock)
+    {
+      if (this.blockDataPosition >= this.blockDataBytes)
+       readNextBlock ();
+
+      return this.blockDataBytes - this.blockDataPosition;
+    }
+    else
+      return this.realInputStream.available ();
+  }
+
+  public void close () throws IOException
+  {
+    this.realInputStream.close ();
+  }
+
+  public boolean readBoolean () throws IOException
+  {
+    return this.dataInputStream.readBoolean ();
+  }
+
+  public byte readByte () throws IOException
+  {
+    return this.dataInputStream.readByte ();
+  }
+
+  public int readUnsignedByte () throws IOException
+  {
+    return this.dataInputStream.readUnsignedByte ();
+  }
+
+  public short readShort () throws IOException
+  {
+    return this.dataInputStream.readShort ();
+  }
+
+  public int readUnsignedShort () throws IOException
+  {
+    return this.dataInputStream.readUnsignedShort ();
+  }
+
+  public char readChar () throws IOException
+  {
+    return this.dataInputStream.readChar ();
+  }
+
+  public int readInt () throws IOException
+  {
+    return this.dataInputStream.readInt ();
+  }
+
+  public long readLong () throws IOException
+  {
+    return this.dataInputStream.readLong ();
+  }
+
+  public float readFloat () throws IOException
+  {
+    return this.dataInputStream.readFloat ();
+  }
+
+  public double readDouble () throws IOException
+  {
+    return this.dataInputStream.readDouble ();
+  }
+
+  public void readFully (byte data[]) throws IOException
+  {
+    this.dataInputStream.readFully (data);
+  }
+
+  public void readFully (byte data[], int offset, int size)
+    throws IOException
+  {
+    this.dataInputStream.readFully (data, offset, size);
+  }
+
+  public int skipBytes (int len) throws IOException
+  {
+    return this.dataInputStream.skipBytes (len);
+  }
+
+  /**
+     @deprecated
+     @see java.io.DataInputStream#readLine ()
+  */
+  public String readLine () throws IOException
+  {
+    return this.dataInputStream.readLine ();
+  }
+
+  public String readUTF () throws IOException
+  {
+    return this.dataInputStream.readUTF ();
+  }
+
+
+  /**
+     This class allows a class to specify exactly which fields should
+     be read, and what values should be read for these fields.
+
+     XXX: finish up comments
+  */
+  public static abstract class GetField
+  {
+    public abstract ObjectStreamClass getObjectStreamClass ();
+
+    public abstract boolean defaulted (String name)
+      throws IOException, IllegalArgumentException;
+
+    public abstract boolean get (String name, boolean defvalue)
+      throws IOException, IllegalArgumentException;
+
+    public abstract char get (String name, char defvalue)
+      throws IOException, IllegalArgumentException;
+
+    public abstract byte get (String name, byte defvalue)
+      throws IOException, IllegalArgumentException;
+
+    public abstract short get (String name, short defvalue)
+      throws IOException, IllegalArgumentException;
+
+    public abstract int get (String name, int defvalue)
+      throws IOException, IllegalArgumentException;
+
+    public abstract long get (String name, long defvalue)
+      throws IOException, IllegalArgumentException;
+
+    public abstract float get (String name, float defvalue)
+      throws IOException, IllegalArgumentException;
+
+    public abstract double get (String name, double defvalue)
+      throws IOException, IllegalArgumentException;
+
+    public abstract Object get (String name, Object defvalue)
+      throws IOException, IllegalArgumentException;
+  }
+
+  public GetField readFields ()
+    throws IOException, ClassNotFoundException, NotActiveException
+  {
+    if (this.currentObject == null || this.currentObjectStreamClass == null)
+      throw new NotActiveException ("readFields called by non-active class and/or object");
+
+    if (fieldsAlreadyRead)
+      throw new NotActiveException ("readFields called but fields already read from stream (by defaultReadObject or readFields)");
+
+    final ObjectStreamClass clazz = this.currentObjectStreamClass;
+    final byte[] prim_field_data = new byte[clazz.primFieldSize];
+    final Object[] objs = new Object[clazz.objectFieldCount];
+    readFully (prim_field_data);
+    for (int i = 0; i < objs.length; ++ i)
+      objs[i] = readObject ();
+
+    return new GetField ()
+    {
+      public ObjectStreamClass getObjectStreamClass ()
+      {
+       return clazz;
+      }
+
+      public boolean defaulted (String name)
+       throws IOException, IllegalArgumentException
+      {
+       return clazz.getField (name) == null;
+      }
+
+      public boolean get (String name, boolean defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, Boolean.TYPE);
+
+       if (field == null)
+         return defvalue;
+
+       return prim_field_data[field.getOffset ()] == 0 ? false : true;
+      }
+
+      public char get (String name, char defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, Character.TYPE);
+
+       if (field == null)
+         return defvalue;
+
+       int off = field.getOffset ();
+
+       return (char)(((prim_field_data[off++] & 0xFF) << 8)
+                     | (prim_field_data[off] & 0xFF));
+      }
+
+      public byte get (String name, byte defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, Byte.TYPE);
+
+       if (field == null)
+         return defvalue;
+
+       return prim_field_data[field.getOffset ()];
+      }
+
+      public short get (String name, short defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, Short.TYPE);
+
+       if (field == null)
+         return defvalue;
+
+       int off = field.getOffset ();
+
+       return (short)(((prim_field_data[off++] & 0xFF) << 8)
+                      | (prim_field_data[off] & 0xFF));
+      }
+
+      public int get (String name, int defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, Integer.TYPE);
+
+       if (field == null)
+         return defvalue;
+
+       int off = field.getOffset ();
+
+       return ((prim_field_data[off++] & 0xFF) << 24)
+         | ((prim_field_data[off++] & 0xFF) << 16)
+         | ((prim_field_data[off++] & 0xFF) << 8)
+         | (prim_field_data[off] & 0xFF);
+      }
+
+      public long get (String name, long defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, Long.TYPE);
+
+       if (field == null)
+         return defvalue;
+
+       int off = field.getOffset ();
+
+       return (long)(((prim_field_data[off++] & 0xFF) << 56)
+                     | ((prim_field_data[off++] & 0xFF) << 48)
+                     | ((prim_field_data[off++] & 0xFF) << 40)
+                     | ((prim_field_data[off++] & 0xFF) << 32)
+                     | ((prim_field_data[off++] & 0xFF) << 24)
+                     | ((prim_field_data[off++] & 0xFF) << 16)
+                     | ((prim_field_data[off++] & 0xFF) << 8)
+                     | (prim_field_data[off] & 0xFF));
+      }
+
+      public float get (String name, float defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, Float.TYPE);
+
+       if (field == null)
+         return defvalue;
+
+       int off = field.getOffset ();
+
+       return Float.intBitsToFloat (((prim_field_data[off++] & 0xFF) << 24)
+                                   | ((prim_field_data[off++] & 0xFF) << 16)
+                                   | ((prim_field_data[off++] & 0xFF) << 8)
+                                   | (prim_field_data[off] & 0xFF));
+      }
+
+      public double get (String name, double defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, Double.TYPE);
+
+       if (field == null)
+         return defvalue;
+
+       int off = field.getOffset ();
+
+       return Double.longBitsToDouble (
+         (long)(((prim_field_data[off++] & 0xFF) << 56)
+                | ((prim_field_data[off++] & 0xFF) << 48)
+                | ((prim_field_data[off++] & 0xFF) << 40)
+                | ((prim_field_data[off++] & 0xFF) << 32)
+                | ((prim_field_data[off++] & 0xFF) << 24)
+                | ((prim_field_data[off++] & 0xFF) << 16)
+                | ((prim_field_data[off++] & 0xFF) << 8)
+                | (prim_field_data[off] & 0xFF)));
+      }
+
+      public Object get (String name, Object defvalue)
+       throws IOException, IllegalArgumentException
+      {
+       ObjectStreamField field = getField (name, null);
+
+       if (field == null)
+         return defvalue;
+
+       return objs[field.getOffset ()];
+      }
+
+      private ObjectStreamField getField (String name, Class type)
+       throws IllegalArgumentException
+      {
+       ObjectStreamField field = clazz.getField (name);
+
+       if (field == null)
+         return null;
+
+       Class field_type = field.getType ();
+
+       if (type == field_type ||
+           (type != null && field_type.isPrimitive ()))
+         return field;
+
+       throw new IllegalArgumentException ("Field requested is of type "
+                                           + field_type.getName ()
+                                           + ", but requested type was "
+                                           + (type == null ?
+                                              "Object" : type.getName ()));
+      }
+    };
+
+  }
+
+
+  /**
+     Protected constructor that allows subclasses to override
+     deserialization.  This constructor should be called by subclasses
+     that wish to override <code>readObject (Object)</code>.  This
+     method does a security check <i>NOTE: currently not
+     implemented</i>, then sets a flag that informs
+     <code>readObject (Object)</code> to call the subclasses
+     <code>readObjectOverride (Object)</code> method.
+
+     @see readObjectOverride (Object)
+  */
+  protected ObjectInputStream ()
+    throws IOException, SecurityException
+  {
+    SecurityManager sec_man = System.getSecurityManager ();
+    if (sec_man != null)
+      sec_man.checkPermission (SUBCLASS_IMPLEMENTATION_PERMISSION);
+    this.useSubclassMethod = true;
+  }
+
+
+  /**
+     This method allows subclasses to override the default
+     de serialization mechanism provided by
+     <code>ObjectInputStream</code>.  To make this method be used for
+     writing objects, subclasses must invoke the 0-argument
+     constructor on this class from there constructor.
+
+     @see ObjectInputStream ()
+  */
+  protected Object readObjectOverride ()
+    throws ClassNotFoundException, IOException, OptionalDataException
+  {
+    throw new IOException ("Subclass of ObjectInputStream must implement readObjectOverride");
+  }
+
+
+  // assigns the next availible handle to OBJ
+  private int assignNewHandle (Object obj)
+  {
+    this.objectLookupTable.put (new Integer (this.nextOID),
+                            new ObjectIdentityWrapper (obj));
+
+//    try
+//    {
+//      DEBUG ("Assigning handle " + this.nextOID);
+//      DEBUGln (" to " + obj);
+//    }
+//    catch (Throwable t) {}
+
+    return this.nextOID++;
+  }
+
+
+  private Object processResoultion (Object obj, int handle)
+    throws IOException
+  {
+    if (obj instanceof Resolvable)
+      obj = ((Resolvable)obj).readResolve ();
+
+    if (this.resolveEnabled)
+      obj = resolveObject (obj);
+
+    this.objectLookupTable.put (new Integer (handle),
+                               new ObjectIdentityWrapper (obj));
+
+    return obj;
+  }
+
+
+  private void clearHandles ()
+  {
+    this.objectLookupTable.clear ();
+    this.nextOID = baseWireHandle;
+  }
+
+
+  private void readNextBlock () throws IOException
+  {
+//    DEBUG ("MARKER ");
+    readNextBlock (this.realInputStream.readByte ());
+  }
+
+
+  private void readNextBlock (byte marker) throws IOException
+  {
+    if (marker == TC_BLOCKDATA)
+    {
+//      DEBUG ("BLOCK DATA SIZE ");
+      this.blockDataBytes = this.realInputStream.readUnsignedByte ();
+    }
+    else if (marker == TC_BLOCKDATALONG)
+    {
+//      DEBUG ("BLOCK DATA LONG SIZE ");
+      this.blockDataBytes = this.realInputStream.readInt ();
+    }
+    else
+    {
+      throw new EOFException ("Attempt to read primitive data, but no data block is active.");
+    }
+
+    if (this.blockData.length < this.blockDataBytes)
+      this.blockData = new byte[this.blockDataBytes];
+
+    this.realInputStream.readFully (this.blockData, 0, this.blockDataBytes);
+    this.blockDataPosition = 0;
+  }
+
+
+  private void readArrayElements (Object array, Class clazz)
+    throws ClassNotFoundException, IOException
+  {
+    if (clazz.isPrimitive ())
+    {
+      if (clazz == Boolean.TYPE)
+      {
+       boolean[] cast_array = (boolean[])array;
+       for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = this.realInputStream.readBoolean ();
+       return;
+      }
+      if (clazz == Byte.TYPE)
+      {
+       byte[] cast_array = (byte[])array;
+       for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = this.realInputStream.readByte ();
+       return;
+      }
+      if (clazz == Character.TYPE)
+      {
+       char[] cast_array = (char[])array;
+       for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = this.realInputStream.readChar ();
+       return;
+      }
+      if (clazz == Double.TYPE)
+      {
+       double[] cast_array = (double[])array;
+       for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = this.realInputStream.readDouble ();
+       return;
+      }
+      if (clazz == Float.TYPE)
+      {
+       float[] cast_array = (float[])array;
+       for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = this.realInputStream.readFloat ();
+       return;
+      }
+      if (clazz == Integer.TYPE)
+      {
+       int[] cast_array = (int[])array;
+       for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = this.realInputStream.readInt ();
+       return;
+      }
+      if (clazz == Long.TYPE)
+      {
+       long[] cast_array = (long[])array;
+       for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = this.realInputStream.readLong ();
+       return;
+      }
+      if (clazz == Short.TYPE)
+      {
+       short[] cast_array = (short[])array;
+       for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = this.realInputStream.readShort ();
+       return;
+      }
+    }
+    else
+    {
+      Object[] cast_array = (Object[])array;
+      for (int i=0; i < cast_array.length; i++)
+         cast_array[i] = readObject ();
+    }
+  }
+
+
+  private void readFields (Object obj, ObjectStreamField[] stream_fields,
+                          boolean call_read_method,
+                          ObjectStreamClass stream_osc)
+    throws ClassNotFoundException, IOException
+  {
+    if (call_read_method)
+    {
+      fieldsAlreadyRead = false;
+      setBlockDataMode (true);
+      callReadMethod (obj, stream_osc.forClass ());
+      setBlockDataMode (false);
+      return;
+    }
+
+    ObjectStreamField[] real_fields =
+      ObjectStreamClass.lookup (stream_osc.forClass ()).fields;
+
+    boolean default_initialize, set_value;
+    String field_name = null;
+    Class type = null;
+    ObjectStreamField stream_field = null;
+    ObjectStreamField real_field = null;
+    int stream_idx = 0;
+    int real_idx = 0;
+
+    while (stream_idx < stream_fields.length
+          && real_idx < real_fields.length)
+    {
+      default_initialize = false;
+      set_value = true;
+
+      if (stream_idx == stream_fields.length)
+       default_initialize = true;
+      else
+      {
+       stream_field = stream_fields[stream_idx];
+       type = stream_field.getType ();
+      }
+
+      if (real_idx == real_fields.length)
+       set_value = false;
+      else
+      {
+       real_field = real_fields[real_idx];
+       type = real_field.getType ();
+       field_name = real_field.getName ();
+      }
+
+      if (set_value && !default_initialize)
+      {
+       int comp_val =
+         real_field.compareTo (stream_field);
+
+       if (comp_val < 0)
+       {
+         default_initialize = true;
+         real_idx++;
+       }
+       else if (comp_val > 0)
+       {
+         set_value = false;
+         stream_idx++;
+       }
+       else
+       {
+         real_idx++;
+         stream_idx++;
+       }
+      }
+
+      if (type == Boolean.TYPE)
+      {
+       boolean value =
+         default_initialize ? false : this.realInputStream.readBoolean ();
+       if (set_value)
+         setBooleanField (obj, field_name, value);
+      }
+      else if (type == Byte.TYPE)
+      {
+       byte value =
+         default_initialize ? 0 : this.realInputStream.readByte ();
+       if (set_value)
+         setByteField (obj, field_name, value);
+      }
+      else if (type == Character.TYPE)
+      {
+       char value =
+         default_initialize ? (char)0 : this.realInputStream.readChar ();
+       if (set_value)
+         setCharField (obj, field_name, value);
+      }
+      else if (type == Double.TYPE)
+      {
+       double value =
+         default_initialize ? 0 : this.realInputStream.readDouble ();
+       if (set_value)
+         setDoubleField (obj, field_name, value);
+      }
+      else if (type == Float.TYPE)
+      {
+       float value =
+         default_initialize ? 0 : this.realInputStream.readFloat ();
+       if (set_value)
+         setFloatField (obj, field_name, value);
+      }
+      else if (type == Integer.TYPE)
+      {
+       int value =
+         default_initialize ? 0 : this.realInputStream.readInt ();
+       if (set_value)
+         setIntField (obj, field_name, value);
+      }
+      else if (type == Long.TYPE)
+      {
+       long value =
+         default_initialize ? 0 : this.realInputStream.readLong ();
+       if (set_value)
+         setLongField (obj, field_name, value);
+      }
+      else if (type == Short.TYPE)
+      {
+       short value =
+         default_initialize ? (short)0 : this.realInputStream.readShort ();
+       if (set_value)
+         setShortField (obj, field_name, value);
+      }
+      else
+      {
+       Object value =
+         default_initialize ? null : readObject ();
+       if (set_value)
+         setObjectField (obj, field_name,
+                         real_field.getTypeString (), value);
+      }
+    }
+  }
+
+
+  // Toggles writing primitive data to block-data buffer.
+  private void setBlockDataMode (boolean on)
+  {
+//    DEBUGln ("Setting block data mode to " + on);
+
+    this.readDataFromBlock = on;
+
+    if (on)
+      this.dataInputStream = this.blockDataInput;
+    else
+      this.dataInputStream = this.realInputStream;
+  }
+
+
+  // returns a new instance of REAL_CLASS that has been constructed
+  // only to th level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
+  private Object newObject (Class real_class, Class constructor_class)
+  {
+    try
+    {
+      Object obj = allocateObject (real_class);
+      callConstructor (constructor_class, obj);
+      return obj;
+    }
+    catch (InstantiationException e)
+    {
+      return null;
+    }
+  }
+
+
+  // runs all registered ObjectInputValidations in prioritized order
+  // on OBJ
+  private void invokeValidators () throws InvalidObjectException
+  {
+    Object[] validators = new Object[this.validators.size ()];
+    this.validators.copyInto (validators);
+    Arrays.sort (validators);
+
+    try
+    {
+      for (int i=0; i < validators.length; i++)
+       ((ObjectInputValidation)validators[i]).validateObject ();
+    }
+    finally
+    {
+      this.validators.removeAllElements ();
+    }
+  }
+
+
+  // this native method is used to get access to the protected method
+  // of the same name in SecurityManger
+  private static ClassLoader currentClassLoader (SecurityManager sm)
+  {
+    // FIXME: This is too simple.
+    return ClassLoader.getSystemClassLoader ();
+  }
+
+  private static native Field getField (Class klass, String name)
+    throws java.lang.NoSuchFieldException;
+
+  private static native Method getMethod (Class klass, String name, Class args[])
+    throws java.lang.NoSuchMethodException;
+
+  private void callReadMethod (Object obj, Class klass) throws IOException
+  {
+    try
+      {
+       Class classArgs[] = {Class.forName ("java.io.ObjectInputStream")};
+       Method m = getMethod (klass, "readObject", classArgs);
+       if (m == null)
+         return;
+       Object args[] = {this};
+       m.invoke (obj, args);   
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }
+  }
+    
+  private native Object allocateObject (Class clazz)
+    throws InstantiationException;
+
+  private native void callConstructor (Class clazz, Object obj);
+
+  private void setBooleanField (Object obj, String field_name,
+                               boolean val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       f.setBoolean (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+  private void setByteField (Object obj, String field_name,
+                               byte val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       f.setByte (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+  private void setCharField (Object obj, String field_name,
+                            char val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       f.setChar (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+  private void setDoubleField (Object obj, String field_name,
+                              double val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       f.setDouble (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+  private void setFloatField (Object obj, String field_name,
+                             float val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       f.setFloat (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+  private void setIntField (Object obj, String field_name,
+                             int val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       f.setInt (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+
+  private void setLongField (Object obj, String field_name,
+                             long val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       f.setLong (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+
+  private void setShortField (Object obj, String field_name,
+                             short val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       f.setShort (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+
+  private void setObjectField (Object obj, String field_name, String type_code,
+                              Object val)
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       // FIXME: We should check the type_code here
+       f.set (obj, val);
+      }
+    catch (Exception _)
+      {
+      }    
+  }
+
+  private static final int BUFFER_SIZE = 1024;
+  private static final Class[] readObjectParams = { ObjectInputStream.class };
+
+  private DataInputStream realInputStream;
+  private DataInputStream dataInputStream;
+  private DataInputStream blockDataInput;
+  private int blockDataPosition;
+  private int blockDataBytes;
+  private byte[] blockData;
+  private boolean useSubclassMethod;
+  private int nextOID;
+  private boolean resolveEnabled;
+  private Hashtable objectLookupTable;
+  private Object currentObject;
+  private ObjectStreamClass currentObjectStreamClass;
+  private boolean readDataFromBlock;
+  private boolean isDeserializing;
+  private boolean fieldsAlreadyRead;
+  private Vector validators;
+
+
+/* FIXME: These 2 methods cause a build error on i686-pc-linux-gnu.
+  private void DEBUG (String msg)
+  {
+    System.out.print (msg);
+  }
+
+
+  private void DEBUGln (String msg)
+  {
+    System.out.println (msg);
+  }
+* end FIXME */
+}
+
+
+// used to keep a prioritized list of object validators
+class ValidatorAndPriority implements Comparable
+{
+  int priority;
+  ObjectInputValidation validator;
+
+  ValidatorAndPriority (ObjectInputValidation validator, int priority)
+  {
+    this.priority = priority;
+    this.validator = validator;
+  }
+
+  public int compareTo (Object o)
+  {
+    ValidatorAndPriority vap = (ValidatorAndPriority)o;
+    return this.priority - vap.priority;
+  }
+}
diff --git a/libjava/java/io/ObjectInputValidation.java b/libjava/java/io/ObjectInputValidation.java
new file mode 100644 (file)
index 0000000..cf3508e
--- /dev/null
@@ -0,0 +1,50 @@
+/* ObjectInputValidation.java -- Validate an object 
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io; 
+
+/**
+  * What does this interface really do?
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public abstract interface ObjectInputValidation
+{
+
+/**
+  * This method is called to validate an object.  If the object is invalid
+  * an exception is thrown.
+  *
+  * @exception InvalidObjectException If the object is invalid
+  */
+public abstract void
+validateObject() throws InvalidObjectException;
+
+} // interface ObjectInputValidation
+
diff --git a/libjava/java/io/ObjectOutput.java b/libjava/java/io/ObjectOutput.java
new file mode 100644 (file)
index 0000000..56b3390
--- /dev/null
@@ -0,0 +1,116 @@
+/* ObjectOutput.java -- Interface for writing objects to a stream
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This interface extends <code>DataOutput</code> to provide the additional
+  * facility of writing object instances to a stream.  It also adds some
+  * additional methods to make the interface more <code>OutputStream</code> like.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public abstract interface ObjectOutput extends DataOutput
+{
+
+
+/**
+  * This method writes the specified byte to the output stream.
+  *
+  * @param b The byte to write.
+  *
+  * @exception IOException If an error occurs.
+  */
+public abstract void
+write(int b) throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method writes all the bytes in the specified byte array to the
+  * output stream.
+  *
+  * @param buf The array of bytes to write.
+  * 
+  * @exception IOException If an error occurs.
+  */
+public abstract void
+write(byte[] buf) throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method writes <code>len</code> bytes from the specified array
+  * starting at index <code>offset</code> into that array.
+  *
+  * @param buf The byte array to write from.
+  * @param offset The index into the byte array to start writing from.
+  * @param len The number of bytes to write.
+  *
+  * @exception IOException If an error occurs.
+  */
+public abstract void
+write(byte[] buf, int offset, int len) throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method writes a object instance to a stream.  The format of the
+  * data written is determined by the actual implementation of this method
+  *
+  * @param obj The object to write
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract void
+writeObject(Object obj) throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method causes any buffered data to be flushed out to the underlying
+  * stream
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract void
+flush() throws IOException;
+
+/*************************************************************************/
+
+/**
+  * This method closes the underlying stream.
+  *
+  * @exception IOException If an error occurs
+  */
+public abstract void
+close() throws IOException;
+
+} // interface ObjectOutput
+
diff --git a/libjava/java/io/ObjectOutputStream.java b/libjava/java/io/ObjectOutputStream.java
new file mode 100644 (file)
index 0000000..a98b55b
--- /dev/null
@@ -0,0 +1,1335 @@
+/* ObjectOutputStream.java -- Class used to write serialized objects
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+
+import gnu.java.io.ObjectIdentityWrapper;
+import gnu.java.lang.reflect.TypeSignature;
+
+/**
+   An <code>ObjectOutputStream</code> can be used to write objects
+   as well as primitive data in a platform-independent manner to an
+   <code>OutputStream</code>.
+
+   The data produced by an <code>ObjectOutputStream</code> can be read
+   and reconstituted by an <code>ObjectInputStream</code>.
+
+   <code>writeObject (Object)</code> is used to write Objects, the
+   <code>write&lt;type&gt;</code> methods are used to write primitive
+   data (as in <code>DataOutputStream</code>). Strings can be written
+   as objects or as primitive data.
+
+   Not all objects can be written out using an
+   <code>ObjectOutputStream</code>.  Only those objects that are an
+   instance of <code>java.io.Serializable</code> can be written.
+
+   Using default serialization, information about the class of an
+   object is written, all of the non-transient, non-static fields of
+   the object are written, if any of these fields are objects, the are
+   written out in the same manner.
+
+   An object is only written out the first time it is encountered.  If
+   the object is encountered later, a reference to it is written to
+   the underlying stream.  Thus writing circular object graphs
+   does not present a problem, nor are relationships between objects
+   in a graph lost.
+
+   Example usage:
+     <pre>
+     Hashtable map = new Hashtable ();
+     map.put ("one", new Integer (1));
+     map.put ("two", new Integer (2));
+
+     ObjectOutputStream oos =
+       new ObjectOutputStream (new FileOutputStream ("numbers"));
+     oos.writeObject (map);
+     oos.close ();
+
+     ObjectInputStream ois =
+       new ObjectInputStream (new FileInputStream ("numbers"));
+     Hashtable newmap = (Hashtable)ois.readObject ();
+
+     System.out.println (newmap);
+     </pre>
+
+   The default serialization can be overriden in two ways.
+
+   By defining a method <code>private void
+   writeObject (ObjectOutputStream)</code>, a class can dictate exactly
+   how information about itself is written.
+   <code>defaultWriteObject ()</code> may be called from this method to
+   carry out default serialization.  This method is not
+   responsible for dealing with fields of super-classes or subclasses.
+
+   By implementing <code>java.io.Externalizable</code>.  This gives
+   the class complete control over the way it is written to the
+   stream.  If this approach is used the burden of writing superclass
+   and subclass data is transfered to the class implementing
+   <code>java.io.Externalizable</code>.
+
+   @see java.io.DataOutputStream
+   @see java.io.Externalizable
+   @see java.io.ObjectInputStream
+   @see java.io.Serializable
+   @see XXX: java serialization spec
+*/
+public class ObjectOutputStream extends OutputStream
+  implements ObjectOutput, ObjectStreamConstants
+{
+  /**
+     Creates a new <code>ObjectOutputStream</code> that will do all of
+     its writing onto <code>out</code>.  This method also initializes
+     the stream by writing the header information (stream magic number
+     and stream version).
+
+     @exception IOException Writing stream header to underlying
+     stream cannot be completed.
+
+     @see writeStreamHeader ()
+  */
+  public ObjectOutputStream (OutputStream out) throws IOException
+  {
+    realOutput = new DataOutputStream (out);
+    blockData = new byte[ BUFFER_SIZE ];
+    blockDataCount = 0;
+    blockDataOutput = new DataOutputStream (this);
+    setBlockDataMode (true);
+    replacementEnabled = false;
+    isSerializing = false;
+    nextOID = baseWireHandle;
+    OIDLookupTable = new Hashtable ();
+    protocolVersion = defaultProtocolVersion;
+    useSubclassMethod = false;
+    writeStreamHeader ();
+  }
+
+
+  /**
+     Writes a representation of <code>obj</code> to the underlying
+     output stream by writing out information about its class, then
+     writing out each of the objects non-transient, non-static
+     fields.  If any of these fields are other objects,
+     the are written out in the same manner.
+
+     This method can be overriden by a class by implementing
+     <code>private void writeObject (ObjectOutputStream)</code>.
+
+     If an exception is thrown from this method, the stream is left in
+     an undefined state.
+
+     @exception NotSerializableException An attempt was made to
+     serialize an <code>Object</code> that is not serializable.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+  */
+  public final void writeObject (Object obj) throws IOException
+  {
+    if (useSubclassMethod)
+    {
+      writeObjectOverride (obj);
+      return;
+    }
+
+    boolean was_serializing = isSerializing;
+
+    if (! was_serializing)
+      setBlockDataMode (false);
+
+    try
+    {
+      isSerializing = true;
+      boolean replaceDone = false;
+
+      drain ();
+
+      while (true)
+      {
+       if (obj == null)
+       {
+         realOutput.writeByte (TC_NULL);
+         break;
+       }
+
+       Integer handle = findHandle (obj);
+       if (handle != null)
+       {
+         realOutput.writeByte (TC_REFERENCE);
+         realOutput.writeInt (handle.intValue ());
+         break;
+       }
+
+       if (obj instanceof Class)
+       {
+         realOutput.writeByte (TC_CLASS);
+         writeObject (ObjectStreamClass.lookup ((Class)obj));
+         assignNewHandle (obj);
+         break;
+       }
+
+       if (obj instanceof ObjectStreamClass)
+       {
+         ObjectStreamClass osc = (ObjectStreamClass)obj;
+         realOutput.writeByte (TC_CLASSDESC);
+         realOutput.writeUTF (osc.getName ());
+         realOutput.writeLong (osc.getSerialVersionUID ());
+         assignNewHandle (obj);
+
+         int flags = osc.getFlags ();
+
+         if (protocolVersion == PROTOCOL_VERSION_2
+             && osc.isExternalizable ())
+           flags |= SC_BLOCK_DATA;
+
+         realOutput.writeByte (flags);
+
+         ObjectStreamField[] fields = osc.fields;
+         realOutput.writeShort (fields.length);
+
+         ObjectStreamField field;
+         for (int i=0; i < fields.length; i++)
+         {
+           field = fields[i];
+           realOutput.writeByte (field.getTypeCode ());
+           realOutput.writeUTF (field.getName ());
+
+           if (! field.isPrimitive ())
+             writeObject (field.getTypeString ());
+         }
+
+         setBlockDataMode (true);
+         annotateClass (osc.forClass ());
+         setBlockDataMode (false);
+         realOutput.writeByte (TC_ENDBLOCKDATA);
+
+         if (osc.isSerializable ())
+           writeObject (osc.getSuper ());
+         else
+           writeObject (null);
+         break;
+       }
+
+
+       Object replacedObject = null;
+
+       if ((replacementEnabled || obj instanceof Replaceable)
+           && ! replaceDone)
+       {
+         replacedObject = obj;
+
+         if (obj instanceof Replaceable)
+           obj = ((Replaceable)obj).writeReplace ();
+
+         if (replacementEnabled)
+           obj = replaceObject (obj);
+
+         replaceDone = true;
+         continue;
+       }
+
+       if (obj instanceof String)
+       {
+         realOutput.writeByte (TC_STRING);
+         assignNewHandle (obj);
+         realOutput.writeUTF ((String)obj);
+         break;
+       }
+
+       Class clazz = obj.getClass ();
+       ObjectStreamClass osc = ObjectStreamClass.lookup (clazz);
+       if (osc == null)
+         throw new NotSerializableException ("The class "
+                                             + clazz.getName ()
+                                             + " is not Serializable");
+
+       if (clazz.isArray ())
+       {
+         realOutput.writeByte (TC_ARRAY);
+         writeObject (osc);
+         assignNewHandle (obj);
+         writeArraySizeAndElements (obj, clazz);
+         break;
+       }
+
+       realOutput.writeByte (TC_OBJECT);
+       writeObject (osc);
+
+       if (replaceDone)
+         assignNewHandle (replacedObject);
+       else
+         assignNewHandle (obj);
+
+       if (obj instanceof Externalizable)
+       {
+         if (protocolVersion == PROTOCOL_VERSION_2)
+           setBlockDataMode (true);
+
+         ((Externalizable)obj).writeExternal (this);
+
+         if (protocolVersion == PROTOCOL_VERSION_2)
+         {
+           setBlockDataMode (false);
+           drain ();
+         }
+
+         break;
+       }
+
+       if (obj instanceof Serializable)
+       {
+         currentObject = obj;
+         ObjectStreamClass[] hierarchy =
+           ObjectStreamClass.getObjectStreamClasses (clazz);
+
+         boolean has_write;
+         for (int i=0; i < hierarchy.length; i++)
+         {
+           currentObjectStreamClass = hierarchy[i];
+
+           has_write = currentObjectStreamClass.hasWriteMethod ();
+           writeFields (obj, currentObjectStreamClass.fields,
+                        has_write);
+
+           fieldsAlreadyWritten = false;
+
+           if (has_write)
+           {
+             drain ();
+             realOutput.writeByte (TC_ENDBLOCKDATA);
+           }
+         }
+
+         currentObject = null;
+         currentObjectStreamClass = null;
+         currentPutField = null;
+         break;
+       }
+
+       throw new NotSerializableException ("Instances of the class "
+                                           + clazz.getName ()
+                                           + " are not Serializable");
+      } // end pseudo-loop
+    }
+    catch (IOException e)
+    {
+      realOutput.writeByte (TC_EXCEPTION);
+      reset (true);
+
+      try
+      {
+       writeObject (e);
+      }
+      catch (IOException ioe)
+      {
+       throw new StreamCorruptedException ("Exception " + ioe + " thrown while exception was being written to stream.");
+      }
+
+      reset (true);
+    }
+    finally
+    {
+      isSerializing = was_serializing;
+
+      if (! was_serializing)
+       setBlockDataMode (true);
+    }
+  }
+
+
+  /**
+     Writes the current objects non-transient, non-static fields from
+     the current class to the underlying output stream.
+
+     This method is intended to be called from within a object's
+     <code>private void writeObject (ObjectOutputStream)</code>
+     method.
+
+     @exception NotActiveException This method was called from a
+     context other than from the current object's and current class's
+     <code>private void writeObject (ObjectOutputStream)</code>
+     method.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+  */
+  public void defaultWriteObject ()
+    throws IOException, NotActiveException
+  {
+    markFieldsWritten ();
+    writeFields (currentObject, currentObjectStreamClass.fields, false);
+  }
+
+
+  private void markFieldsWritten () throws IOException
+  {
+    if (currentObject == null || currentObjectStreamClass == null)
+      throw new NotActiveException ("defaultWriteObject called by non-active class and/or object");
+
+    if (fieldsAlreadyWritten)
+      throw new IOException ("Only one of putFields and defalutWriteObject may be called, and it may only be called once");
+
+    fieldsAlreadyWritten = true;
+  }
+
+
+  /**
+     Resets stream to state equivalent to the state just after it was
+     constructed.
+
+     Causes all objects previously written to the stream to be
+     forgotten.  A notification of this reset is also written to the
+     underlying stream.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code> or reset called while serialization is
+     in progress.
+  */
+  public void reset () throws IOException
+  {
+    reset (false);
+  }
+
+
+  private void reset (boolean internal) throws IOException
+  {
+    if (!internal)
+    {
+      if (isSerializing)
+       throw new IOException ("Reset called while serialization in progress");
+
+      realOutput.writeByte (TC_RESET);
+    }
+
+    clearHandles ();
+  }
+
+
+  /**
+     Informs this <code>ObjectOutputStream</code> to write data
+     according to the specified protocol.  There are currently two
+     different protocols, specified by <code>PROTOCOL_VERSION_1</code>
+     and <code>PROTOCOL_VERSION_2</code>.  This implementation writes
+     data using <code>PROTOCOL_VERSION_1</code> by default, as is done
+     by the JDK 1.1.
+
+     A non-portable method, <code>setDefaultProtocolVersion (int
+     version)</code> is provided to change the default protocol
+     version.
+
+     For an explination of the differences beween the two protocols
+     see XXX: the Java ObjectSerialization Specification.
+
+     @exception IOException if <code>version</code> is not a valid
+     protocol
+
+     @see setDefaultProtocolVersion (int)
+  */
+  public void useProtocolVersion (int version) throws IOException
+  {
+    if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
+      throw new IOException ("Invalid protocol version requested.");
+
+    protocolVersion = version;
+  }
+
+
+  /**
+     <em>GNU $classpath specific</em>
+
+     Changes the default stream protocol used by all
+     <code>ObjectOutputStream</code>s.  There are currently two
+     different protocols, specified by <code>PROTOCOL_VERSION_1</code>
+     and <code>PROTOCOL_VERSION_2</code>.  The default default is
+     <code>PROTOCOL_VERSION_1</code>.
+
+     @exception IOException if <code>version</code> is not a valid
+     protocol
+
+     @see useProtocolVersion (int)
+  */
+  public static void setDefaultProtocolVersion (int version)
+    throws IOException
+  {
+    if (version != PROTOCOL_VERSION_1 && version != PROTOCOL_VERSION_2)
+      throw new IOException ("Invalid protocol version requested.");
+
+    defaultProtocolVersion = version;
+  }
+
+
+  /**
+     An empty hook that allows subclasses to write extra information
+     about classes to the stream.  This method is called the first
+     time each class is seen, and after all of the standard
+     information about the class has been written.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+
+     @see java.io.ObjectInputStream#resolveClass (java.io.ObjectStreamClass)
+  */
+  protected void annotateClass (Class cl) throws IOException
+  {}
+
+
+  /**
+     Allows subclasses to replace objects that are written to the
+     stream with other objects to be written in their place.  This
+     method is called the first time each object is encountered
+     (modulo reseting of the stream).
+
+     This method must be enabled before it will be called in the
+     serialization process.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+
+     @see enableReplaceObject (boolean)
+  */
+  protected Object replaceObject (Object obj) throws IOException
+  {
+    return obj;
+  }
+
+
+  /**
+     If <code>enable</code> is <code>true</code> and this object is
+     trusted, then <code>replaceObject (Object)</code> will be called
+     in subsequent calls to <code>writeObject (Object)</code>.
+     Otherwise, <code>replaceObject (Object)</code> will not be called.
+
+     @exception SecurityException This class is not trusted.
+  */
+  protected boolean enableReplaceObject (boolean enable)
+    throws SecurityException
+  {
+    if (enable)
+      if (getClass ().getClassLoader () != null)
+       throw new SecurityException ("Untrusted ObjectOutputStream subclass attempted to enable object replacement");
+
+    boolean old_val = replacementEnabled;
+    replacementEnabled = enable;
+    return old_val;
+  }
+
+
+  /**
+     Writes stream magic and stream version information to the
+     underlying stream.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+  */
+  protected void writeStreamHeader () throws IOException
+  {
+    realOutput.writeShort (STREAM_MAGIC);
+    realOutput.writeShort (STREAM_VERSION);
+  }
+
+
+
+  /**
+     Protected constructor that allows subclasses to override
+     serialization.  This constructor should be called by subclasses
+     that wish to override <code>writeObject (Object)</code>.  This
+     method does a security check <i>NOTE: currently not
+     implemented</i>, then sets a flag that informs
+     <code>writeObject (Object)</code> to call the subclasses
+     <code>writeObjectOverride (Object)</code> method.
+
+     @see writeObjectOverride (Object)
+  */
+  protected ObjectOutputStream () throws IOException, SecurityException
+  {
+    SecurityManager sec_man = System.getSecurityManager ();
+    if (sec_man != null)
+      sec_man.checkPermission (SUBCLASS_IMPLEMENTATION_PERMISSION);
+    useSubclassMethod = true;
+  }
+
+
+  /**
+     This method allows subclasses to override the default
+     serialization mechanism provided by
+     <code>ObjectOutputStream</code>.  To make this method be used for
+     writing objects, subclasses must invoke the 0-argument
+     constructor on this class from there constructor.
+
+     @see ObjectOutputStream ()
+
+     @exception NotActiveException Subclass has arranged for this
+     method to be called, but did not implement this method.
+  */
+  protected void writeObjectOverride (Object obj) throws NotActiveException,
+    IOException
+  {
+    throw new NotActiveException ("Subclass of ObjectOutputStream must implement writeObjectOverride");
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#write (int)
+  */
+  public void write (int data) throws IOException
+  {
+    if (writeDataAsBlocks)
+    {
+      if (blockDataCount == BUFFER_SIZE)
+       drain ();
+
+      blockData[ blockDataCount++ ] = (byte)data;
+    }
+    else
+      realOutput.write (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#write (byte[])
+  */
+  public void write (byte b[]) throws IOException
+  {
+    write (b, 0, b.length);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#write (byte[],int,int)
+  */
+  public void write (byte b[], int off, int len) throws IOException
+  {
+    if (writeDataAsBlocks)
+    {
+      if (len < 0)
+       throw new IndexOutOfBoundsException ();
+
+      if (blockDataCount + len < BUFFER_SIZE)
+      {
+       System.arraycopy (b, off, blockData, blockDataCount, len);
+       blockDataCount += len;
+      }
+      else
+      {
+       drain ();
+       writeBlockDataHeader (len);
+       realOutput.write (b, off, len);
+      }
+    }
+    else
+      realOutput.write (b, off, len);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#flush ()
+  */
+  public void flush () throws IOException
+  {
+    drain ();
+    realOutput.flush ();
+  }
+
+
+  /**
+     Causes the block-data buffer to be written to the underlying
+     stream, but does not flush underlying stream.
+
+     @exception IOException Exception from underlying
+     <code>OutputStream</code>.
+  */
+  protected void drain () throws IOException
+  {
+    if (blockDataCount == 0)
+      return;
+
+    writeBlockDataHeader (blockDataCount);
+    realOutput.write (blockData, 0, blockDataCount);
+    blockDataCount = 0;
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#close ()
+  */
+  public void close () throws IOException
+  {
+    drain ();
+    realOutput.close ();
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeBoolean (boolean)
+  */
+  public void writeBoolean (boolean data) throws IOException
+  {
+    dataOutput.writeBoolean (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeByte (int)
+  */
+  public void writeByte (int data) throws IOException
+  {
+    dataOutput.writeByte (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeShort (int)
+  */
+  public void writeShort (int data) throws IOException
+  {
+    dataOutput.writeShort (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeChar (int)
+  */
+  public void writeChar (int data) throws IOException
+  {
+    dataOutput.writeChar (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeInt (int)
+  */
+  public void writeInt (int data) throws IOException
+  {
+    dataOutput.writeInt (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeLong (long)
+  */
+  public void writeLong (long data) throws IOException
+  {
+    dataOutput.writeLong (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeFloat (float)
+  */
+  public void writeFloat (float data) throws IOException
+  {
+    dataOutput.writeFloat (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeDouble (double)
+  */
+  public void writeDouble (double data) throws IOException
+  {
+    dataOutput.writeDouble (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeBytes (java.lang.String)
+  */
+  public void writeBytes (String data) throws IOException
+  {
+    dataOutput.writeBytes (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeChars (java.lang.String)
+  */
+  public void writeChars (String data) throws IOException
+  {
+    dataOutput.writeChars (data);
+  }
+
+
+  /**
+     @see java.io.DataOutputStream#writeUTF (java.lang.String)
+  */
+  public void writeUTF (String data) throws IOException
+  {
+    dataOutput.writeUTF (data);
+  }
+
+
+  /**
+     This class allows a class to specify exactly which fields should
+     be written, and what values should be written for these fields.
+
+     XXX: finish up comments
+  */
+  public static abstract class PutField
+  {
+    public abstract void put (String name, boolean value)
+      throws IOException, IllegalArgumentException;
+    public abstract void put (String name, byte value)
+      throws IOException, IllegalArgumentException;
+    public abstract void put (String name, char value)
+      throws IOException, IllegalArgumentException;
+    public abstract void put (String name, double value)
+      throws IOException, IllegalArgumentException;
+    public abstract void put (String name, float value)
+      throws IOException, IllegalArgumentException;
+    public abstract void put (String name, int value)
+      throws IOException, IllegalArgumentException;
+    public abstract void put (String name, long value)
+      throws IOException, IllegalArgumentException;
+    public abstract void put (String name, short value)
+      throws IOException, IllegalArgumentException;
+    public abstract void put (String name, Object value)
+      throws IOException, IllegalArgumentException;
+    public abstract void write (ObjectOutput out) throws IOException;
+  }
+
+
+  public PutField putFields () throws IOException
+  {
+    markFieldsWritten ();
+
+    currentPutField = new PutField ()
+      {
+       private byte[] prim_field_data
+         = new byte[currentObjectStreamClass.primFieldSize];
+       private Object[] objs
+         = new Object[currentObjectStreamClass.objectFieldCount];
+
+       public void put (String name, boolean value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           checkType (field, 'Z');
+           prim_field_data[field.getOffset ()] = (byte)(value ? 1 : 0);
+         }
+
+       public void put (String name, byte value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           checkType (field, 'B');
+           prim_field_data[field.getOffset ()] = value;
+         }
+
+       public void put (String name, char value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           checkType (field, 'B');
+           int off = field.getOffset ();
+           prim_field_data[off++] = (byte)(value >>> 8);
+           prim_field_data[off] = (byte)value;
+         }
+
+       public void put (String name, double value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           checkType (field, 'B');
+           int off = field.getOffset ();
+           long l_value = Double.doubleToLongBits (value);
+           prim_field_data[off++] = (byte)(l_value >>> 52);
+           prim_field_data[off++] = (byte)(l_value >>> 48);
+           prim_field_data[off++] = (byte)(l_value >>> 40);
+           prim_field_data[off++] = (byte)(l_value >>> 32);
+           prim_field_data[off++] = (byte)(l_value >>> 24);
+           prim_field_data[off++] = (byte)(l_value >>> 16);
+           prim_field_data[off++] = (byte)(l_value >>> 8);
+           prim_field_data[off] = (byte)l_value;
+         }
+
+       public void put (String name, float value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           checkType (field, 'B');
+           int off = field.getOffset ();
+           int i_value = Float.floatToIntBits (value);
+           prim_field_data[off++] = (byte)(i_value >>> 24);
+           prim_field_data[off++] = (byte)(i_value >>> 16);
+           prim_field_data[off++] = (byte)(i_value >>> 8);
+           prim_field_data[off] = (byte)i_value;
+         }
+
+       public void put (String name, int value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           checkType (field, 'B');
+           int off = field.getOffset ();
+           prim_field_data[off++] = (byte)(value >>> 24);
+           prim_field_data[off++] = (byte)(value >>> 16);
+           prim_field_data[off++] = (byte)(value >>> 8);
+           prim_field_data[off] = (byte)value;
+         }
+
+       public void put (String name, long value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           checkType (field, 'B');
+           int off = field.getOffset ();
+           prim_field_data[off++] = (byte)(value >>> 52);
+           prim_field_data[off++] = (byte)(value >>> 48);
+           prim_field_data[off++] = (byte)(value >>> 40);
+           prim_field_data[off++] = (byte)(value >>> 32);
+           prim_field_data[off++] = (byte)(value >>> 24);
+           prim_field_data[off++] = (byte)(value >>> 16);
+           prim_field_data[off++] = (byte)(value >>> 8);
+           prim_field_data[off] = (byte)value;
+         }
+
+       public void put (String name, short value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           checkType (field, 'B');
+           int off = field.getOffset ();
+           prim_field_data[off++] = (byte)(value >>> 8);
+           prim_field_data[off] = (byte)value;
+         }
+
+       public void put (String name, Object value)
+         throws IOException, IllegalArgumentException
+         {
+           ObjectStreamField field
+             = currentObjectStreamClass.getField (name);
+           if (! field.getType ().isAssignableFrom (value.getClass ()))
+             throw new IllegalArgumentException ();
+           objs[field.getOffset ()] = value;
+         }
+
+       public void write (ObjectOutput out) throws IOException
+         {
+           out.write (prim_field_data);
+           for (int i = 0; i < objs.length; ++ i)
+             out.writeObject (objs[i]);
+         }
+
+       private void checkType (ObjectStreamField field, char type)
+         throws IllegalArgumentException
+         {
+           if (TypeSignature.getEncodingOfClass (field.getType ()).charAt (0) != type)
+             throw new IllegalArgumentException ();
+         }
+      };
+    // end PutFieldImpl
+
+    return currentPutField;
+  }
+
+
+  public void writeFields () throws IOException
+  {
+    if (currentPutField == null)
+      throw new NotActiveException ("writeFields can only be called after putFields has been called");
+
+    currentPutField.write (this);
+  }
+
+
+  // write out the block-data buffer, picking the correct header
+  // depending on the size of the buffer
+  private void writeBlockDataHeader (int size) throws IOException
+  {
+    if (size < 256)
+    {
+      realOutput.writeByte (TC_BLOCKDATA);
+      realOutput.write (size);
+    }
+    else
+    {
+      realOutput.writeByte (TC_BLOCKDATALONG);
+      realOutput.writeInt (size);
+    }
+  }
+
+
+  // lookup the handle for OBJ, return null if OBJ doesn't have a
+  // handle yet
+  private Integer findHandle (Object obj)
+  {
+    return (Integer)OIDLookupTable.get (new ObjectIdentityWrapper (obj));
+  }
+
+
+  // assigns the next availible handle to OBJ
+  private int assignNewHandle (Object obj)
+  {
+    OIDLookupTable.put (new ObjectIdentityWrapper (obj),
+                       new Integer (nextOID));
+    return nextOID++;
+  }
+
+
+  // resets mapping from objects to handles
+  private void clearHandles ()
+  {
+    nextOID = baseWireHandle;
+    OIDLookupTable.clear ();
+  }
+
+
+  // write out array size followed by each element of the array
+  private void writeArraySizeAndElements (Object array, Class clazz)
+    throws IOException
+  {
+    int length = Array.getLength (array);
+
+    if (clazz.isPrimitive ())
+    {
+      if (clazz == Boolean.TYPE)
+      {
+       boolean[] cast_array = (boolean[])array;
+       realOutput.writeInt (length);
+       for (int i=0; i < length; i++)
+         realOutput.writeBoolean (cast_array[i]);
+       return;
+      }
+      if (clazz == Byte.TYPE)
+      {
+       byte[] cast_array = (byte[])array;
+       realOutput.writeInt (length);
+       for (int i=0; i < length; i++)
+         realOutput.writeByte (cast_array[i]);
+       return;
+      }
+      if (clazz == Character.TYPE)
+      {
+       char[] cast_array = (char[])array;
+       realOutput.writeInt (length);
+       for (int i=0; i < length; i++)
+         realOutput.writeChar (cast_array[i]);
+       return;
+      }
+      if (clazz == Double.TYPE)
+      {
+       double[] cast_array = (double[])array;
+       realOutput.writeInt (length);
+       for (int i=0; i < length; i++)
+         realOutput.writeDouble (cast_array[i]);
+       return;
+      }
+      if (clazz == Float.TYPE)
+      {
+       float[] cast_array = (float[])array;
+       realOutput.writeInt (length);
+       for (int i=0; i < length; i++)
+         realOutput.writeFloat (cast_array[i]);
+       return;
+      }
+      if (clazz == Integer.TYPE)
+      {
+       int[] cast_array = (int[])array;
+       realOutput.writeInt (length);
+       for (int i=0; i < length; i++)
+         realOutput.writeInt (cast_array[i]);
+       return;
+      }
+      if (clazz == Long.TYPE)
+      {
+       long[] cast_array = (long[])array;
+       realOutput.writeInt (length);
+       for (int i=0; i < length; i++)
+         realOutput.writeLong (cast_array[i]);
+       return;
+      }
+      if (clazz == Short.TYPE)
+      {
+       short[] cast_array = (short[])array;
+       realOutput.writeInt (length);
+       for (int i=0; i < length; i++)
+         realOutput.writeShort (cast_array[i]);
+       return;
+      }
+    }
+    else
+    {
+      Object[] cast_array = (Object[])array;
+      realOutput.writeInt (length);
+      for (int i=0; i < length; i++)
+       writeObject (cast_array[i]);
+    }
+  }
+
+
+  // writes out FIELDS of OBJECT.  If CALL_WRITE_METHOD is true, use
+  // object's writeObject (ObjectOutputStream), otherwise use default
+  // serialization.  FIELDS are already in canonical order.
+  private void writeFields (Object obj,
+                           ObjectStreamField[] fields,
+                           boolean call_write_method) throws IOException
+  {
+    if (call_write_method)
+    {
+      setBlockDataMode (true);
+      callWriteMethod (obj);
+      setBlockDataMode (false);
+      return;
+    }
+
+    String field_name;
+    Class type;
+    for (int i=0; i < fields.length; i++)
+    {
+      field_name = fields[i].getName ();
+      type = fields[i].getType ();
+
+      if (type == Boolean.TYPE)
+       realOutput.writeBoolean (getBooleanField (obj, field_name));
+      else if (type == Byte.TYPE)
+       realOutput.writeByte (getByteField (obj, field_name));
+      else if (type == Character.TYPE)
+       realOutput.writeChar (getCharField (obj, field_name));
+      else if (type == Double.TYPE)
+       realOutput.writeDouble (getDoubleField (obj, field_name));
+      else if (type == Float.TYPE)
+       realOutput.writeFloat (getFloatField (obj, field_name));
+      else if (type == Integer.TYPE)
+       realOutput.writeInt (getIntField (obj, field_name));
+      else if (type == Long.TYPE)
+       realOutput.writeLong (getLongField (obj, field_name));
+      else if (type == Short.TYPE)
+       realOutput.writeShort (getShortField (obj, field_name));
+      else
+       writeObject (getObjectField (obj, field_name,
+                                    TypeSignature.getEncodingOfClass (type)));
+    }
+  }
+
+
+  // Toggles writing primitive data to block-data buffer.
+  private void setBlockDataMode (boolean on)
+  {
+    writeDataAsBlocks = on;
+
+    if (on)
+      dataOutput = blockDataOutput;
+    else
+      dataOutput = realOutput;
+  }
+
+
+  private void callWriteMethod (Object obj) throws IOException
+  {
+    try
+      {
+       Class classArgs[] = {Class.forName ("java.io.ObjectOutputStream")};
+       Class klass = obj.getClass ();
+       Method m = getMethod (klass, "writeObject", classArgs);
+       if (m == null)
+         return;
+       Object args[] = {this};
+       m.invoke (obj, args);   
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }
+  }
+    
+  private boolean getBooleanField (Object obj, String field_name) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       boolean b = f.getBoolean (obj);
+       return b;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private byte getByteField (Object obj, String field_name) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       byte b = f.getByte (obj);
+       return b;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private char getCharField (Object obj, String field_name) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       char b = f.getChar (obj);
+       return b;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private double getDoubleField (Object obj, String field_name) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       double b = f.getDouble (obj);
+       return b;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private float getFloatField (Object obj, String field_name) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       float b = f.getFloat (obj);
+       return b;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private int getIntField (Object obj, String field_name) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       int b = f.getInt (obj);
+       return b;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private long getLongField (Object obj, String field_name) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       long b = f.getLong (obj);
+       return b;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private short getShortField (Object obj, String field_name) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       short b = f.getShort (obj);
+       return b;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private Object getObjectField (Object obj, String field_name,
+                                String type_code) throws IOException
+  {
+    try
+      {
+       Class klass = obj.getClass ();
+       Field f = getField (klass, field_name);
+       Object o = f.get (obj);
+       // FIXME: We should check the type_code here
+       return o;
+      }
+    catch (Exception _)
+      {
+       throw new IOException ();
+      }    
+  }
+
+  private static native Field getField (Class klass, String name)
+    throws java.lang.NoSuchFieldException;
+
+  private static native Method getMethod (Class klass, String name, Class args[])
+    throws java.lang.NoSuchMethodException;
+
+  // this value comes from 1.2 spec, but is used in 1.1 as well
+  private final static int BUFFER_SIZE = 1024;
+
+  private static int defaultProtocolVersion = PROTOCOL_VERSION_1;
+
+  private DataOutputStream dataOutput;
+  private boolean writeDataAsBlocks;
+  private DataOutputStream realOutput;
+  private DataOutputStream blockDataOutput;
+  private byte[] blockData;
+  private int blockDataCount;
+  private Object currentObject;
+  private ObjectStreamClass currentObjectStreamClass;
+  private PutField currentPutField;
+  private boolean fieldsAlreadyWritten;
+  private boolean replacementEnabled;
+  private boolean isSerializing;
+  private int nextOID;
+  private Hashtable OIDLookupTable;
+  private int protocolVersion;
+  private boolean useSubclassMethod;
+}
diff --git a/libjava/java/io/ObjectStreamClass.java b/libjava/java/io/ObjectStreamClass.java
new file mode 100644 (file)
index 0000000..f799b4f
--- /dev/null
@@ -0,0 +1,666 @@
+/* ObjectStreamClass.java -- Class used to write class information
+   about serialized objects.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.DigestOutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Hashtable;
+import java.util.Vector;
+import gnu.java.io.NullOutputStream;
+import gnu.java.lang.reflect.TypeSignature;
+import gnu.gcj.io.SimpleSHSStream;
+
+
+public class ObjectStreamClass implements Serializable
+{
+  /**
+     Returns the <code>ObjectStreamClass</code> for <code>cl</code>.
+     If <code>cl</code> is null, or is not <code>Serializable</code>,
+     null is returned.  <code>ObjectStreamClass</code>'s are memoized;
+     later calls to this method with the same class will return the
+     same <code>ObjectStreamClass</code> object and no recalculation
+     will be done.
+
+     @see java.io.Serializable
+  */
+  public static ObjectStreamClass lookup (Class cl)
+  {
+    if (cl == null)
+      return null;
+
+    ObjectStreamClass osc = (ObjectStreamClass)classLookupTable.get (cl);
+
+    if (osc != null)
+      return osc;
+    else if (! (Serializable.class).isAssignableFrom (cl))
+      return null;
+    else
+    {
+      osc = new ObjectStreamClass (cl);
+      classLookupTable.put (cl, osc);
+      return osc;
+    }
+  }
+
+
+  /**
+     Returns the name of the class that this
+     <code>ObjectStreamClass</code> represents.
+  */
+  public String getName ()
+  {
+    return name;
+  }
+
+
+  /**
+     Returns the class that this <code>ObjectStreamClass</code>
+     represents.  Null could be returned if this
+     <code>ObjectStreamClass</code> was read from an
+     <code>ObjectInputStream</code> and the class it represents cannot
+     be found or loaded.
+
+     @see java.io.ObjectInputStream
+  */
+  public Class forClass ()
+  {
+    return clazz;
+  }
+
+
+  /**
+     Returns the serial version stream-unique identifier for the class
+     represented by this <code>ObjectStreamClass</code>.  This SUID is
+     either defined by the class as <code>static final long
+     serialVersionUID</code> or is calculated as specified in
+     Javasoft's "Object Serialization Specification" XXX: add reference
+  */
+  public long getSerialVersionUID ()
+  {
+    return uid;
+  }
+
+
+  // Returns the serializable (non-static and non-transient) Fields
+  // of the class represented by this ObjectStreamClass.  The Fields
+  // are sorted by name.
+  // XXX doc
+  public ObjectStreamField[] getFields ()
+  {
+    ObjectStreamField[] copy = new ObjectStreamField[ fields.length ];
+    System.arraycopy (fields, 0, copy, 0, fields.length);
+    return copy;
+  }
+
+
+  // XXX doc
+  // Can't do binary search since fields is sorted by name and
+  // primitiveness.
+  public ObjectStreamField getField (String name)
+  {
+    for (int i=0; i < fields.length; i++)
+      if (fields[i].getName ().equals (name))
+       return fields[i];
+    return null;
+  }
+
+
+  /**
+     Returns a textual representation of this
+     <code>ObjectStreamClass</code> object including the name of the
+     class it represents as well as that class's serial version
+     stream-unique identifier.
+
+     @see getSerialVersionUID ()
+     @see getName ()
+  */
+  public String toString ()
+  {
+    return "java.io.ObjectStreamClass< " + name + ", " + uid + " >";
+  }
+
+
+  // Returns true iff the class that this ObjectStreamClass represents
+  // has the following method:
+  //
+  // private void writeObject (ObjectOutputStream)
+  //
+  // This method is used by the class to override default
+  // serialization behaivior.
+  boolean hasWriteMethod ()
+  {
+    return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0;
+  }
+
+
+  // Returns true iff the class that this ObjectStreamClass represents
+  // implements Serializable but does *not* implement Externalizable.
+  boolean isSerializable ()
+  {
+    return (flags & ObjectStreamConstants.SC_SERIALIZABLE) != 0;
+  }
+
+
+  // Returns true iff the class that this ObjectStreamClass represents
+  // implements Externalizable.
+  boolean isExternalizable ()
+  {
+    return (flags & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0;
+  }
+
+
+  // Returns the <code>ObjectStreamClass</code> that represents the
+  // class that is the superclass of the class this
+  // <code>ObjectStreamClass</cdoe> represents.  If the superclass is
+  // not Serializable, null is returned.
+  ObjectStreamClass getSuper ()
+  {
+    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)
+  {
+    ObjectStreamClass osc = ObjectStreamClass.lookup (clazz);
+
+    ObjectStreamClass[] ret_val;
+
+    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;
+    }
+  }
+
+
+  // Returns an integer that consists of bit-flags that indicate
+  // properties of the class represented by this ObjectStreamClass.
+  // The bit-flags that could be present are those defined in
+  // ObjectStreamConstants that begin with `SC_'
+  int getFlags ()
+  {
+    return flags;
+  }
+
+
+  ObjectStreamClass (String name, long uid, byte flags,
+                    ObjectStreamField[] fields)
+  {
+    this.name = name;
+    this.uid = uid;
+    this.flags = flags;
+    this.fields = fields;
+  }
+
+
+  void setClass (Class clazz)
+  {
+    this.clazz = clazz;
+  }
+
+
+  void setSuperclass (ObjectStreamClass osc)
+  {
+    superClass = osc;
+  }
+
+
+  void calculateOffsets ()
+  {
+    int i;
+    ObjectStreamField field;
+    primFieldSize = 0;
+    int fcount = fields.length;
+    for (i = 0; i < fcount; ++ i)
+    {
+      field = fields[i];
+
+      if (! field.isPrimitive ())
+       break;
+
+      field.setOffset (primFieldSize);
+      switch (field.getTypeCode ())
+      {
+       case 'B':
+       case 'Z':
+         ++ primFieldSize;
+         break;
+       case 'C':
+       case 'S':
+         primFieldSize += 2;
+         break;
+       case 'I':
+       case 'F':
+         primFieldSize += 4;
+         break;
+       case 'D':
+       case 'J':
+         primFieldSize += 8;
+         break;
+      }
+    }
+
+    for (objectFieldCount = 0; i < fcount; ++ i)
+      fields[i].setOffset (objectFieldCount++);
+  }
+
+
+  private ObjectStreamClass (Class cl)
+  {
+    uid = 0;
+    flags = 0;
+
+    clazz = cl;
+    name = cl.getName ();
+    setFlags (cl);
+    setFields (cl);
+    setUID (cl);
+    superClass = lookup (cl.getSuperclass ());
+  }
+
+
+  // Sets bits in flags according to features of CL.
+  private void setFlags (Class cl)
+  {
+    if ((java.io.Externalizable.class).isAssignableFrom (cl))
+      flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
+    else if ((java.io.Serializable.class).isAssignableFrom (cl))
+      // only set this bit if CL is NOT Externalizable
+      flags |= ObjectStreamConstants.SC_SERIALIZABLE;
+
+    try
+    {
+      Method writeMethod = cl.getDeclaredMethod ("writeObject",
+                                                writeMethodArgTypes);
+      int modifiers = writeMethod.getModifiers ();
+
+      if (writeMethod.getReturnType () == Void.TYPE
+         && Modifier.isPrivate (modifiers)
+         && !Modifier.isStatic (modifiers))
+       flags |= ObjectStreamConstants.SC_WRITE_METHOD;
+    }
+    catch (NoSuchMethodException oh_well)
+    {}
+  }
+
+
+  // Sets fields to be a sorted array of the serializable fields of
+  // clazz.
+  private void setFields (Class cl)
+  {
+    if (! isSerializable () || isExternalizable ())
+    {
+      fields = NO_FIELDS;
+      return;
+    }
+
+    try
+    {
+      Field serialPersistantFields
+       = cl.getDeclaredField ("serialPersistantFields");
+      int modifiers = serialPersistantFields.getModifiers ();
+
+      if (Modifier.isStatic (modifiers)
+         && Modifier.isFinal (modifiers)
+         && Modifier.isPrivate (modifiers))
+      {
+       fields = getSerialPersistantFields (cl);
+       Arrays.sort (fields);
+       calculateOffsets ();
+       return;
+      }
+    }
+    catch (NoSuchFieldException ignore)
+    {}
+
+    int num_good_fields = 0;
+    Field[] all_fields = cl.getDeclaredFields ();
+
+    int modifiers;
+    // set non-serializable fields to null in all_fields
+    for (int i=0; i < all_fields.length; i++)
+    {
+      modifiers = all_fields[i].getModifiers ();
+      if (Modifier.isTransient (modifiers)
+         || Modifier.isStatic (modifiers))
+       all_fields[i] = null;
+      else
+       num_good_fields++;
+    }
+
+    // make a copy of serializable (non-null) fields
+    fields = new ObjectStreamField[ num_good_fields ];
+    for (int from=0, to=0; from < all_fields.length; from++)
+      if (all_fields[from] != null)
+      {
+       Field f = all_fields[from];
+       fields[to] = new ObjectStreamField (f.getName (), f.getType ());
+       to++;
+      }
+
+    Arrays.sort (fields);
+    calculateOffsets ();
+  }
+
+  // Sets uid be serial version UID defined by class, or if that
+  // isn't present, calculates value of serial version UID.
+  private void setUID (Class cl)
+  {
+    try
+    {
+      Field suid = cl.getDeclaredField ("serialVersionUID");
+      int modifiers = suid.getModifiers ();
+
+      if (Modifier.isStatic (modifiers)
+         && Modifier.isFinal (modifiers))
+      {
+       uid = getDefinedSUID (cl);
+       return;
+      }
+    }
+    catch (NoSuchFieldException ignore)
+    {}
+
+    // cl didn't define serialVersionUID, so we have to compute it
+    try
+    {
+      MessageDigest md = null;
+      DigestOutputStream digest_out = null;
+      DataOutputStream data_out = null;
+      SimpleSHSStream simple = null;
+
+      try 
+       {
+         md = MessageDigest.getInstance ("SHA");
+         digest_out = new DigestOutputStream (nullOutputStream, md);
+         data_out = new DataOutputStream (digest_out);   
+       }
+      catch (NoSuchAlgorithmException e)
+       {
+         simple = new SimpleSHSStream (nullOutputStream);
+         data_out = new DataOutputStream (simple);
+       }
+
+      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);
+
+      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
+      boolean has_init;
+      try
+      {
+       has_init = hasClassInitializer (cl);
+      }
+      catch (NoSuchMethodError e)
+      {
+       has_init = false;
+      }
+
+      if (has_init)
+      {
+       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 != null ? md.digest () : simple.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);
+
+      uid = result;
+    }
+    catch (NoSuchAlgorithmException e)
+    {
+      throw new RuntimeException ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
+                                 + cl.getName ());
+    }
+    catch (IOException ioe)
+    {
+      throw new RuntimeException (ioe.getMessage ());
+    }
+  }
+
+
+  // Returns the value of CLAZZ's final static long field named
+  // `serialVersionUID'.
+  private long getDefinedSUID (Class clazz)
+  {
+    long l = 0;
+    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.
+       Field f = clazz.getDeclaredField ("serialVersionUID");
+       l = f.getLong (null);
+      }
+    catch (java.lang.NoSuchFieldException e)
+      {
+      }
+
+    catch (java.lang.IllegalAccessException e)
+      {
+      }
+
+    return l;
+  }
+
+  // Returns the value of CLAZZ's private static final field named
+  // `serialPersistantFields'.
+  private ObjectStreamField[] getSerialPersistantFields (Class clazz)
+  {
+    ObjectStreamField[] o = null;
+    try
+      {
+       // Use getDeclaredField rather than getField for the same reason
+       // as above in getDefinedSUID.
+       Field f = clazz.getDeclaredField ("getSerialPersistantFields");
+       o = (ObjectStreamField[])f.get (null);
+      }
+    catch (java.lang.NoSuchFieldException e)
+      {
+      }
+    catch (java.lang.IllegalAccessException e)
+      {
+      }
+
+    return o;
+  }
+
+
+  // Returns true if CLAZZ has a static class initializer
+  // (a.k.a. <clinit>).
+  //
+  // A NoSuchMethodError is raised if CLAZZ has no such method.
+  private static boolean hasClassInitializer (Class clazz)
+    throws java.lang.NoSuchMethodError
+  {
+    Method m = null;
+
+    try
+      {
+       Class classArgs[] = {};
+       m = clazz.getMethod ("<clinit>", classArgs);
+      }
+    catch (java.lang.NoSuchMethodException e)
+      {
+       throw new java.lang.NoSuchMethodError ();
+      }
+
+    return m != null;
+  }
+
+  public static final ObjectStreamField[] NO_FIELDS = {};
+
+  private static Hashtable classLookupTable = new Hashtable ();
+  private static final NullOutputStream nullOutputStream = new NullOutputStream ();
+  private static final Comparator interfaceComparator = new InterfaceComparator ();
+  private static final Comparator memberComparator = new MemberComparator ();
+  private static final
+    Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };
+
+  private ObjectStreamClass superClass;
+  private Class clazz;
+  private String name;
+  private long uid;
+  private byte flags;
+
+  // this field is package protected so that ObjectInputStream and
+  // ObjectOutputStream can access it directly
+  ObjectStreamField[] fields;
+
+  // these are accessed by ObjectIn/OutputStream
+  int primFieldSize = -1;  // -1 if not yet calculated
+  int objectFieldCount;
+}
+
+
+// interfaces are compared only by name
+class InterfaceComparator implements Comparator
+{
+  public int compare (Object o1, Object o2)
+  {
+    return ((Class)o1).getName ().compareTo (((Class)o2).getName ());
+  }
+}
+
+
+// Members (Methods and Constructors) are compared first by name,
+// conflicts are resolved by comparing type signatures
+class MemberComparator implements Comparator
+{
+  public int compare (Object o1, Object o2)
+  {
+    Member m1 = (Member)o1;
+    Member m2 = (Member)o2;
+
+    int comp = m1.getName ().compareTo (m2.getName ());
+
+    if (comp == 0)
+      return TypeSignature.getEncodingOfMember (m1).
+       compareTo (TypeSignature.getEncodingOfMember (m2));
+    else
+      return comp;
+  }
+}
diff --git a/libjava/java/io/ObjectStreamConstants.java b/libjava/java/io/ObjectStreamConstants.java
new file mode 100644 (file)
index 0000000..c9a2aea
--- /dev/null
@@ -0,0 +1,74 @@
+/* ObjectStreamConstants.java -- Interface containing constant values
+   used in reading and writing serialized objects
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+   This interface contains constants that are used in object
+   serialization.  This interface is used by ObjectOutputStream,
+   ObjectInputStream, ObjectStreamClass, and possibly other classes.
+   The values for these constants are specified in Javasoft's "Object
+   Serialization Specification" TODO: add reference
+*/
+public interface ObjectStreamConstants
+{
+  public final static int PROTOCOL_VERSION_1 = 1;
+  public final static int PROTOCOL_VERSION_2 = 2;
+
+  final static short STREAM_MAGIC = (short)0xaced;
+  final static short STREAM_VERSION = 5;
+
+  final static byte TC_NULL = (byte)112;
+  final static byte TC_REFERENCE = (byte)113;
+  final static byte TC_CLASSDESC = (byte)114;
+  final static byte TC_OBJECT = (byte)115;
+  final static byte TC_STRING = (byte)116;
+  final static byte TC_ARRAY = (byte)117;
+  final static byte TC_CLASS = (byte)118;
+  final static byte TC_BLOCKDATA = (byte)119;
+  final static byte TC_ENDBLOCKDATA = (byte)120;
+  final static byte TC_RESET = (byte)121;
+  final static byte TC_BLOCKDATALONG = (byte)122;
+  final static byte TC_EXCEPTION = (byte)123;
+
+  final static byte TC_BASE = TC_NULL;
+  final static byte TC_MAX = TC_EXCEPTION;
+
+  final static int baseWireHandle = 0x7e0000;
+
+  final static byte SC_WRITE_METHOD = 0x01;
+  final static byte SC_SERIALIZABLE = 0x02;
+  final static byte SC_EXTERNALIZABLE = 0x04;
+  final static byte SC_BLOCK_DATA = 0x08;
+
+  final static SerializablePermission SUBSTITUTION_PERMISSION
+    = new SerializablePermission("enableSubstitution");
+
+  final static SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION
+    = new SerializablePermission("enableSubclassImplementation");
+}
diff --git a/libjava/java/io/ObjectStreamField.java b/libjava/java/io/ObjectStreamField.java
new file mode 100644 (file)
index 0000000..55181cc
--- /dev/null
@@ -0,0 +1,99 @@
+/* ObjectStreamField.java -- Class used to store name and class of fields
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+import gnu.java.lang.reflect.TypeSignature;
+
+// XXX doc
+public class ObjectStreamField implements java.lang.Comparable
+{
+  public ObjectStreamField (String name, Class type)
+  {
+    this.name = name;
+    this.type = type;
+  }
+
+  public String getName ()
+  {
+    return name;
+  }
+
+  public Class getType ()
+  {
+    return type;
+  }
+
+  public char getTypeCode ()
+  {
+    return TypeSignature.getEncodingOfClass (type).charAt (0);
+  }
+
+  public String getTypeString ()
+  {
+    return TypeSignature.getEncodingOfClass (type);
+  }
+
+  public int getOffset ()
+  {
+    return offset;
+  }
+
+  protected void setOffset (int off)
+  {
+    offset = off;
+  }
+
+  public boolean isPrimitive ()
+  {
+    return type.isPrimitive ();
+  }
+
+  public int compareTo (Object o)
+  {
+    ObjectStreamField f = (ObjectStreamField)o;
+    boolean this_is_primitive = isPrimitive ();
+    boolean f_is_primitive = f.isPrimitive ();
+
+    if (this_is_primitive && !f_is_primitive)
+      return -1;
+
+    if (!this_is_primitive && f_is_primitive)
+      return 1;
+
+    return getName ().compareTo (f.getName ());
+  }
+
+  public String toString ()
+  {
+    return "ObjectStreamField< " + type + " " + name + " >";
+  }
+
+  private String name;
+  private Class type;
+  private int offset = -1; // XXX make sure this is correct
+}
diff --git a/libjava/java/io/Replaceable.java b/libjava/java/io/Replaceable.java
new file mode 100644 (file)
index 0000000..1035ab5
--- /dev/null
@@ -0,0 +1,54 @@
+/* Replaceable.java -- Replace an object with another object
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This interface is used to indicate that an object may want to have
+  * another object serialized instead of itself.  It contains one method
+  * that is to be called when an object is to be serialized.  That method
+  * is reponsible for returning the real object that should be serialized
+  * instead of object being queried.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public interface Replaceable extends Serializable
+{
+
+/**
+  * This method returns the object that should be serialized instead of
+  * this object
+  *
+  * @return The real object that should be serialized
+  */
+public abstract Object
+writeReplace();
+
+} // interface Replaceable
+
diff --git a/libjava/java/io/Resolvable.java b/libjava/java/io/Resolvable.java
new file mode 100644 (file)
index 0000000..b7250de
--- /dev/null
@@ -0,0 +1,52 @@
+/* Resolvable.java -- Returns an object to replace the one being de-serialized
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This interface is implemented when an object wishes to return another
+  * object to replace it during de-serialization.  It has one method that
+  * returns the object that should be used to replace the original object.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public interface Resolvable extends Serializable
+{
+
+/**
+  * This method returns the object that should be used to replace the 
+  * original object during de-serialization.
+  *
+  * @return The replacement object
+  */
+public abstract Object
+readResolve();
+
+} // interface Resolvable
+
diff --git a/libjava/java/io/SerializablePermission.java b/libjava/java/io/SerializablePermission.java
new file mode 100644 (file)
index 0000000..78c7229
--- /dev/null
@@ -0,0 +1,106 @@
+/* SerializablePermission.java -- Basic permissions related to serialization.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+import java.security.BasicPermission;
+
+/**
+  * This class models permissions related to serialization.  As a subclass
+  * of <code>BasicPermission</code>, this class has permissions that have
+  * a name only.  There is no associated action list.
+  * <p>
+  * There are currently two allowable permission names for this class:
+  * <ul>
+  * <li><code>enableSubclassImplementation</code> - Allows a subclass to
+  * override the default serialization behavior of objects.
+  * <li><code>enableSubstitution</code> - Allows substitution of one object
+  * for another during serialization or deserialization.
+  * </ul>
+  *
+  * @see java.security.BasicPermission
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public final class SerializablePermission extends BasicPermission
+{
+
+/*
+ * Class Variables
+ */
+
+public static final String[] legal_names = { "enableSubclassImplementation",
+                                             "enableSubstitution" };
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+  * This method initializes a new instance of <code>SerializablePermission</code>
+  * that has the specified name.
+  *
+  * @param name The name of the permission.
+  *
+  * @exception IllegalArgumentException If the name is not valid for this class.
+  */
+public
+SerializablePermission(String name)
+{
+  this(name, null);
+}
+
+/*************************************************************************/
+
+/**
+  * This method initializes a new instance of <code>SerializablePermission</code>
+  * that has the specified name and action list.  Note that the action list
+  * is unused in this class.
+  *
+  * @param name The name of the permission.
+  * @param actions The action list (unused).
+  *
+  * @exception IllegalArgumentException If the name is not valid for this class.
+  */
+public
+SerializablePermission(String name, String actions)
+{
+  super(name, actions);
+
+  for (int i = 0; i < legal_names.length; i++)
+    if (legal_names[i].equals(name))
+      return;
+
+  throw new IllegalArgumentException("Bad permission name:  " + name);
+}
+
+
+} // class SerializablePermission
+
diff --git a/libjava/java/io/WriteAbortedException.java b/libjava/java/io/WriteAbortedException.java
new file mode 100644 (file)
index 0000000..1f22514
--- /dev/null
@@ -0,0 +1,89 @@
+/* WriteAbortedException.java -- An exception occured while writing a 
+   serialization stream
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.io;
+
+/**
+  * This exception is thrown when one of the other ObjectStreamException 
+  * subclasses was thrown during a serialization write.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public class WriteAbortedException extends ObjectStreamException
+{
+
+/*
+ * Instance Variables
+ */
+
+/**
+  * The detailed exception that caused this exception to be thrown
+  */
+public Exception detail;
+private String message;
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+  * Create a new WriteAbortedException with an eof parameter indicating
+  * the detailed Exception that caused this exception to be thrown.
+  *
+  * @param detail The exception that caused this exception to be thrown
+  */
+public
+WriteAbortedException(String msg, Exception detail)
+{
+  this.message = msg;
+  this.detail = detail;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+  * This method returns a message indicating what went wrong, including 
+  * the message text from the initial exception that caused this one to
+  * be thrown
+  */
+public String
+getMessage()
+{
+  return(message + ": " + detail.getMessage());
+}
+
+} // class WriteAbortedException
+
diff --git a/libjava/java/io/natObjectInputStream.cc b/libjava/java/io/natObjectInputStream.cc
new file mode 100644 (file)
index 0000000..b7a8dcb
--- /dev/null
@@ -0,0 +1,78 @@
+// natObjectInputStream.cc - Native part of ObjectInputStream class.
+
+/* Copyright (C) 1998, 1999  Free Software Foundation
+
+   This ObjectInputStream is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the ObjectInputStream "LIBGCJ_LICENSE" for
+details.  */
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/io/ObjectInputStream$GetField.h>
+#include <java/io/ObjectInputStream.h>
+#include <java/io/IOException.h>
+#include <java/lang/Class.h>
+#include <java/lang/reflect/Modifier.h>
+#include <java/lang/reflect/Method.h>
+
+jobject
+java::io::ObjectInputStream::allocateObject (jclass klass)
+{
+  jobject obj = NULL;
+  using namespace java::lang::reflect;
+
+  try
+    {
+      JvAssert (klass && ! klass->isArray ());
+      if (klass->isInterface() || Modifier::isAbstract(klass->getModifiers()))
+       obj = NULL;     
+      else
+       {
+         // FIXME: will this work for String?
+         obj = JvAllocObject (klass);
+       }
+    }
+  catch (jthrowable t)
+    {
+      return NULL;
+    }
+
+  return obj;
+}
+
+
+#define ObjectClass _CL_Q34java4lang6Object
+extern java::lang::Class ObjectClass;
+#define ClassClass _CL_Q34java4lang5Class
+extern java::lang::Class ClassClass;
+
+void 
+java::io::ObjectInputStream::callConstructor (jclass klass, jobject obj)
+{ 
+  jstring init_name = JvNewStringLatin1 ("<init>");
+  JArray<jclass> *arg_types
+    = (JArray<jclass> *) JvNewObjectArray (0, &ClassClass, NULL);
+  JArray<jobject> *args
+    = (JArray<jobject> *) JvNewObjectArray (0, &ObjectClass, NULL);
+  java::lang::reflect::Method *m = klass->getPrivateMethod (init_name, arg_types);
+  m->invoke (obj, args);
+}
+  
+java::lang::reflect::Field *
+java::io::ObjectInputStream::getField (jclass klass, jstring name)
+{
+  return klass->getPrivateField (name);
+}
+
+java::lang::reflect::Method *
+java::io::ObjectInputStream::getMethod (jclass klass, jstring name, 
+                                       JArray<jclass> *arg_types)
+{
+  return klass->getPrivateMethod (name, arg_types);
+}
+
diff --git a/libjava/java/io/natObjectOutputStream.cc b/libjava/java/io/natObjectOutputStream.cc
new file mode 100644 (file)
index 0000000..45ab753
--- /dev/null
@@ -0,0 +1,33 @@
+// natObjectOutputStream.cc - Native part of ObjectOutputStream class.
+
+/* Copyright (C) 1998, 1999  Free Software Foundation
+
+   This ObjectOutputStream is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the ObjectOutputStream "LIBGCJ_LICENSE" for
+details.  */
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+#include <java/io/ObjectOutputStream$PutField.h>
+#include <java/io/ObjectOutputStream.h>
+#include <java/io/IOException.h>
+#include <java/lang/Class.h>
+
+
+java::lang::reflect::Field *
+java::io::ObjectOutputStream::getField (jclass klass, jstring name)
+{
+  return klass->getPrivateField (name);
+}
+
+java::lang::reflect::Method *
+java::io::ObjectOutputStream::getMethod (jclass klass, jstring name, 
+                                        JArray<jclass> *arg_types)
+{
+  return klass->getPrivateMethod (name, arg_types);
+}
+
index d685a1b..03fa439 100644 (file)
@@ -130,6 +130,9 @@ private:
   java::lang::reflect::Field *getField (jstring, jint);
   jint _getMethods (JArray<java::lang::reflect::Method *> *result,
                    jint offset);
+  java::lang::reflect::Field *getPrivateField (jstring);
+  java::lang::reflect::Method *getPrivateMethod (jstring, JArray<jclass> *);
+
 public:
   JArray<java::lang::reflect::Field *> *getFields (void);
 
@@ -234,6 +237,10 @@ private:
   // Friends classes and functions to implement the ClassLoader
   friend class java::lang::ClassLoader;
 
+  friend class java::io::ObjectOutputStream;
+  friend class java::io::ObjectInputStream;
+  friend class java::io::ObjectStreamClass;
+
   friend void _Jv_WaitForState (jclass, int);
   friend void _Jv_RegisterClasses (jclass *classes);
   friend void _Jv_RegisterInitiatingLoader (jclass,java::lang::ClassLoader*);
index 4f1d152..9c14552 100644 (file)
@@ -110,6 +110,11 @@ public abstract class SecurityManager
       throw new SecurityException();
     }
 
+  public void checkPermission (java.security.Permission perm)
+    {
+      throw new SecurityException();
+    }
+
   public void checkPrintJobAccess ()
     {
       throw new SecurityException();
index 54be314..12f8789 100644 (file)
@@ -8,6 +8,8 @@ details.  */
 
 package java.lang;
 import java.io.UnsupportedEncodingException;
+import java.io.Serializable;
+import java.lang.Comparable;
 
 /**
  * @author Per Bothner <bothner@cygnus.com>
@@ -18,7 +20,7 @@ import java.io.UnsupportedEncodingException;
  * Status:  Complete to 1.1, but see FIXMEs. Also see testsuite results.
  */
 
-public final class String
+public final class String implements Serializable, Comparable
 {
   private Object data;
   private int boffset; // Note this is a byte offset - don't use in Java code!
@@ -172,6 +174,11 @@ public final class String
 
   public native int compareTo (String anotherString);
 
+  public int compareTo (Object obj)
+  {
+    return compareTo ((String)obj);
+  }
+
   public native boolean regionMatches (int toffset,
                                       String other, int ooffset, int len);
 
index cf82540..6e00fa7 100644 (file)
@@ -1,6 +1,6 @@
 // StringBuffer.java - Growable strings.
 
-/* Copyright (C) 1998, 1999, 2000  Red Hat
+/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
 
    This file is part of libgcj.
 
index 93e8210..dfc3840 100644 (file)
@@ -918,11 +918,27 @@ _Jv_IsAssignableFrom (jclass target, jclass source)
       return _Jv_IsAssignableFrom(target->getComponentType(), 
                                   source->getComponentType());
     }
-        
+
   if (target->isInterface())
     {
+      // Abstract classes have no IDTs, so compare superclasses instead.
+      if (java::lang::reflect::Modifier::isAbstract (source->accflags))
+       {
+         jclass super = source->getSuperclass();
+         return super ? _Jv_IsAssignableFrom (target, super) : false;
+       }
+
+      if (source->state != JV_STATE_DONE)
+       source->initializeClass ();
+      if (target->state != JV_STATE_DONE)
+       target->initializeClass ();
+
       _Jv_IDispatchTable *cl_idt = source->idt;
       _Jv_IDispatchTable *if_idt = target->idt;
+
+      if (if_idt == NULL) // The interface has no implementations
+       return false;
+
       if (__builtin_expect ((if_idt == NULL), false))
        return false; // No class implementing TARGET has been loaded.    
       jshort cl_iindex = cl_idt->cls.iindex;
@@ -1305,3 +1321,61 @@ _Jv_FindIIndex (jclass *ifaces, jshort *offsets, jshort num)
 
   return i;
 }
+
+// Only used by serialization
+java::lang::reflect::Field *
+java::lang::Class::getPrivateField (jstring name)
+{
+  int hash = name->hashCode ();
+
+  java::lang::reflect::Field* rfield;
+  for (int i = 0;  i < field_count;  i++)
+    {
+      _Jv_Field *field = &fields[i];
+      if (! _Jv_equal (field->name, name, hash))
+       continue;
+      rfield = new java::lang::reflect::Field ();
+      rfield->offset = (char*) field - (char*) fields;
+      rfield->declaringClass = this;
+      rfield->name = name;
+      return rfield;
+    }
+  jclass superclass = getSuperclass();
+  if (superclass == NULL)
+    return NULL;
+  rfield = superclass->getPrivateField(name);
+  for (int i = 0; i < interface_count && rfield == NULL; ++i)
+    rfield = interfaces[i]->getPrivateField (name);
+  return rfield;
+}
+
+// Only used by serialization
+java::lang::reflect::Method *
+java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
+{
+  jstring partial_sig = getSignature (param_types, false);
+  jint p_len = partial_sig->length();
+  _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
+  for (Class *klass = this; klass; klass = klass->getSuperclass())
+    {
+      int i = klass->isPrimitive () ? 0 : klass->method_count;
+      while (--i >= 0)
+       {
+         // FIXME: access checks.
+         if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
+             && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
+           {
+             // Found it.
+             using namespace java::lang::reflect;
+
+             Method *rmethod = new Method ();
+             rmethod->offset = ((char *) (&klass->methods[i])
+                                - (char *) klass->methods);
+             rmethod->declaringClass = klass;
+             return rmethod;
+           }
+       }
+    }
+  JvThrow (new java::lang::NoSuchMethodException);
+}
+
index 896873a..aa8782d 100644 (file)
@@ -46,7 +46,8 @@ extern java::lang::Class ClassClass;
 extern java::lang::Class VMClassLoader;
 #define ClassLoaderClass _CL_Q34java4lang11ClassLoader
 extern java::lang::Class ClassLoaderClass;
-
+#define SerializableClass _CL_Q34java2io12Serializable
+extern java::lang::Class SerializableClass;
 /////////// java.lang.ClassLoader native methods ////////////
 
 java::lang::ClassLoader *
@@ -579,10 +580,9 @@ _Jv_FindArrayClass (jclass element, java::lang::ClassLoader *loader)
       array_class->methods = (_Jv_Method *) element;
 
       // Register our interfaces.
-      // FIXME: for JDK 1.2 we need Serializable.
-      static jclass interfaces[] = { &CloneableClass };
+      static jclass interfaces[] = { &CloneableClass, &SerializableClass };
       array_class->interfaces = interfaces;
-      array_class->interface_count = 1;
+      array_class->interface_count = sizeof interfaces / sizeof interfaces[0];
 
       // Generate the interface dispatch table.
       _Jv_PrepareConstantTimeTables (array_class);
index 376a016..5a28c1e 100644 (file)
@@ -46,12 +46,12 @@ _Jv_StringFindSlot (jchar* data, jint len, jint hash)
   int start_index = hash & (strhash_size - 1);
   int deleted_index = -1;
 
-  register int index = start_index;
+  int index = start_index;
   /* step must be non-zero, and relatively prime with strhash_size. */
   int step = 8 * hash + 7;
   for (;;)
     {
-      register jstring* ptr = &strhash[index];
+      jstring* ptr = &strhash[index];
       if (*ptr == NULL)
        {
          if (deleted_index >= 0)
@@ -75,7 +75,7 @@ _Jv_StringFindSlot (jchar* data, jint len, jint hash)
 static jint
 hashChars (jchar* ptr, jint length)
 {
-  register jchar* limit = ptr + length;
+  jchar* limit = ptr + length;
   jint hash = 0;
   // Updated specification from
   // http://www.javasoft.com/docs/books/jls/clarify.html.
@@ -111,8 +111,8 @@ java::lang::String::rehash()
     }
   else
     {
-      register int i = strhash_size;
-      register jstring* ptr = strhash + i;
+      int i = strhash_size;
+      jstring* ptr = strhash + i;
       strhash_size *= 2;
       strhash = (jstring *) _Jv_AllocBytes (strhash_size * sizeof (jstring));
       memset (strhash, 0, strhash_size * sizeof (jstring));
@@ -198,8 +198,8 @@ _Jv_NewStringUtf8Const (Utf8Const* str)
   jchar *chrs;
   jchar buffer[100];
   jstring jstr;
-  register unsigned char* data = (unsigned char*) str->data;
-  register unsigned char* limit = data + str->length;
+  unsigned char* data = (unsigned char*) str->data;
+  unsigned char* limit = data + str->length;
   int length = _Jv_strLengthUtf8(str->data, str->length);
 
   if (length <= (int) (sizeof(buffer) / sizeof(jchar)))
@@ -239,12 +239,12 @@ _Jv_NewStringUtf8Const (Utf8Const* str)
 jsize
 _Jv_GetStringUTFLength (jstring string)
 {
-  register jsize len = 0;
-  register jchar *ptr = JvGetStringChars (string);
-  register jsize i = string->length();
+  jsize len = 0;
+  jchar *ptr = JvGetStringChars (string);
+  jsize i = string->length();
   while (--i >= 0)
     {
-      register jchar ch = *ptr++;
+      jchar ch = *ptr++;
       if (ch > 0 && ch <= 0x7F)
        len += 1;
       else if (ch <= 0x7FF)
@@ -260,9 +260,9 @@ _Jv_GetStringUTFLength (jstring string)
 jsize
 _Jv_GetStringUTFRegion (jstring str, jsize start, jsize len, char *buf)
 {
-  register jchar *sptr = JvGetStringChars (str) + start;
-  register jsize i = len;
-  register char *dptr = buf;
+  jchar *sptr = JvGetStringChars (str) + start;
+  jsize i = len;
+  char *dptr = buf;
   while (--i >= 0)
     {
       jchar ch = *sptr++;
@@ -429,9 +429,9 @@ java::lang::String::equals(jobject anObject)
   if (count != other->count)
     return false;
   /* if both are interned, return false. */
-  register jint i = count;
-  register jchar *xptr = JvGetStringChars (this);
-  register jchar *yptr = JvGetStringChars (other);
+  jint i = count;
+  jchar *xptr = JvGetStringChars (this);
+  jchar *yptr = JvGetStringChars (other);
   while (--i >= 0)
     {
       if (*xptr++ != *yptr++)
@@ -456,9 +456,9 @@ java::lang::String::getChars(jint srcBegin, jint srcEnd,
   if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count
       || dstBegin < 0 || dstBegin + (srcEnd-srcBegin) > dst_length)
     JvThrow (new java::lang::StringIndexOutOfBoundsException());
-  register jchar *dPtr = elements (dst) + dstBegin;
-  register jchar *sPtr = JvGetStringChars (this) + srcBegin;
-  register jint i = srcEnd-srcBegin;
+  jchar *dPtr = elements (dst) + dstBegin;
+  jchar *sPtr = JvGetStringChars (this) + srcBegin;
+  jint i = srcEnd-srcBegin;
   while (--i >= 0)
     *dPtr++ = *sPtr++;
 }
@@ -506,9 +506,9 @@ java::lang::String::getBytes(jint srcBegin, jint srcEnd,
   if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count
       || dstBegin < 0 || dstBegin + (srcEnd-srcBegin) > dst_length)
     JvThrow (new java::lang::StringIndexOutOfBoundsException());
-  register jbyte *dPtr = elements (dst) + dstBegin;
-  register jchar *sPtr = JvGetStringChars (this) + srcBegin;
-  register jint i = srcEnd-srcBegin;
+  jbyte *dPtr = elements (dst) + dstBegin;
+  jchar *sPtr = JvGetStringChars (this) + srcBegin;
+  jint i = srcEnd-srcBegin;
   while (--i >= 0)
     *dPtr++ = (jbyte) *sPtr++;
 }
@@ -517,9 +517,9 @@ jcharArray
 java::lang::String::toCharArray()
 {
   jcharArray array = JvNewCharArray(count);
-  register jchar *dPtr = elements (array);
-  register jchar *sPtr = JvGetStringChars (this);
-  register jint i = count;
+  jchar *dPtr = elements (array);
+  jchar *sPtr = JvGetStringChars (this);
+  jint i = count;
   while (--i >= 0)
     *dPtr++ = *sPtr++;
   return array;
@@ -530,9 +530,9 @@ java::lang::String::equalsIgnoreCase (jstring anotherString)
 {
   if (anotherString == NULL || count != anotherString->count)
     return false;
-  register jchar *tptr = JvGetStringChars (this);
-  register jchar *optr = JvGetStringChars (anotherString);
-  register jint i = count;
+  jchar *tptr = JvGetStringChars (this);
+  jchar *optr = JvGetStringChars (anotherString);
+  jint i = count;
   while (--i >= 0)
     {
       jchar tch = *tptr++;
@@ -555,9 +555,9 @@ java::lang::String::regionMatches (jint toffset,
       || toffset + len > count
       || ooffset + len > other->count)
     return false;
-  register jchar *tptr = JvGetStringChars (this) + toffset;
-  register jchar *optr = JvGetStringChars (other) + ooffset;
-  register jint i = len;
+  jchar *tptr = JvGetStringChars (this) + toffset;
+  jchar *optr = JvGetStringChars (other) + ooffset;
+  jint i = len;
   while (--i >= 0)
     {
       if (*tptr++ != *optr++)
@@ -569,11 +569,11 @@ java::lang::String::regionMatches (jint toffset,
 jint
 java::lang::String::compareTo (jstring anotherString)
 {
-  register jchar *tptr = JvGetStringChars (this);
-  register jchar *optr = JvGetStringChars (anotherString);
+  jchar *tptr = JvGetStringChars (this);
+  jchar *optr = JvGetStringChars (anotherString);
   jint tlen = this->count;
   jint olen = anotherString->count;
-  register jint i = tlen > olen ? olen : tlen;
+  jint i = tlen > olen ? olen : tlen;
   while (--i >= 0)
     {
       jchar tch = *tptr++;
@@ -592,9 +592,9 @@ java::lang::String::regionMatches (jboolean ignoreCase, jint toffset,
       || toffset + len > count
       || ooffset + len > other->count)
     return false;
-  register jchar *tptr = JvGetStringChars (this) + toffset;
-  register jchar *optr = JvGetStringChars (other) + ooffset;
-  register jint i = len;
+  jchar *tptr = JvGetStringChars (this) + toffset;
+  jchar *optr = JvGetStringChars (other) + ooffset;
+  jint i = len;
   if (ignoreCase)
     while (--i >= 0)
       {
@@ -620,11 +620,11 @@ java::lang::String::regionMatches (jboolean ignoreCase, jint toffset,
 jboolean
 java::lang::String::startsWith (jstring prefix, jint toffset)
 {
-  register jint i = prefix->count;
+  jint i = prefix->count;
   if (toffset < 0 || toffset + i > count)
     return false;
-  register jchar *xptr = JvGetStringChars (this) + toffset;
-  register jchar *yptr = JvGetStringChars (prefix);
+  jchar *xptr = JvGetStringChars (this) + toffset;
+  jchar *yptr = JvGetStringChars (prefix);
   while (--i >= 0)
     {
       if (*xptr++ != *yptr++)
@@ -638,7 +638,7 @@ java::lang::String::indexOf (jint ch, jint fromIndex)
 {
   if (fromIndex < 0)
     fromIndex = 0;
-  register jchar *ptr = JvGetStringChars(this);
+  jchar *ptr = JvGetStringChars(this);
   for (;; ++fromIndex)
     {
       if (fromIndex >= count)
@@ -682,7 +682,7 @@ java::lang::String::lastIndexOf (jint ch, jint fromIndex)
 {
   if (fromIndex >= count)
     fromIndex = count - 1;
-  register jchar *ptr = JvGetStringChars(this);
+  jchar *ptr = JvGetStringChars(this);
   for (;; --fromIndex)
     {
       if (fromIndex < 0)
@@ -716,9 +716,9 @@ java::lang::String::concat(jstring str)
   if (str_count == 0)
     return this;
   jstring result = JvAllocString(count + str_count);
-  register jchar *dstPtr = JvGetStringChars(result);
-  register jchar *srcPtr = JvGetStringChars(this);
-  register jint i = count;
+  jchar *dstPtr = JvGetStringChars(result);
+  jchar *srcPtr = JvGetStringChars(this);
+  jint i = count;
   while (--i >= 0)
     *dstPtr++ = *srcPtr++;
   srcPtr = JvGetStringChars(str);
@@ -834,9 +834,9 @@ java::lang::String::valueOf(jcharArray data, jint offset, jint count)
   jint data_length = JvGetArrayLength (data);
   if (offset < 0 || count < 0 || offset+count > data_length)
     JvThrow (new java::lang::IndexOutOfBoundsException());
-  register jstring result = JvAllocString(count);
-  register jchar *sPtr = elements (data) + offset;
-  register jchar *dPtr = JvGetStringChars(result);
+  jstring result = JvAllocString(count);
+  jchar *sPtr = elements (data) + offset;
+  jchar *dPtr = JvGetStringChars(result);
   while (--count >= 0)
     *dPtr++ = *sPtr++;
   return result;
@@ -845,7 +845,7 @@ java::lang::String::valueOf(jcharArray data, jint offset, jint count)
 jstring
 java::lang::String::valueOf(jchar c)
 {
-  register jstring result = JvAllocString(1);
+  jstring result = JvAllocString(1);
   JvGetStringChars (result)[0] = c;
   return result;
 }
index bbe18c2..eeb4e41 100644 (file)
@@ -39,6 +39,10 @@ details.  */
 
 #include <name-finder.h>
 
+#ifdef __ia64__
+extern "C" int _Jv_ia64_backtrace (void **array, int size);
+#endif
+
 /* FIXME: size of the stack trace is limited to 128 elements.  It's
    undoubtedly sensible to limit the stack trace, but 128 is rather
    arbitrary.  It may be better to configure this.  */
@@ -46,16 +50,21 @@ details.  */
 java::lang::Throwable *
 java::lang::Throwable::fillInStackTrace (void)
 {
-#ifdef HAVE_BACKTRACE
+#if defined (HAVE_BACKTRACE) || defined (__ia64__)
   void *p[128];
   
   // We subtract 1 from the number of elements because we don't want
   // to include the call to fillInStackTrace in the trace.
+#if defined (__ia64__)
+  int n = _Jv_ia64_backtrace (p, 128) - 1;  
+#else
   int n = backtrace (p, 128) - 1;  
+#endif
 
   // ???  Might this cause a problem if the byte array isn't aligned?
   stackTrace = JvNewByteArray (n * sizeof p[0]);
   memcpy (elements (stackTrace), p+1, (n * sizeof p[0]));
+
 #endif
 
   return this;
@@ -83,11 +92,15 @@ java::lang::Throwable::printRawStackTrace (java::io::PrintWriter *wr)
        {
          wr->print (JvNewStringLatin1 (": "));
          wr->print (JvNewStringLatin1 (finder.method_name));
-         wr->print (JvNewStringLatin1 (" ("));
-         wr->print (JvNewStringLatin1 (finder.file_name));
-         wr->print (JvNewStringLatin1 (")"));
+         if (finder.file_name[0])
+           {
+             wr->print (JvNewStringLatin1 (" ("));
+             wr->print (JvNewStringLatin1 (finder.file_name));
+             wr->print (JvNewStringLatin1 (")"));
+           }
        }
       wr->println ();
     }
 #endif /* HAVE_BACKTRACE */
+  wr->flush ();
 }
index f80a52f..5931eef 100644 (file)
@@ -329,6 +329,20 @@ public final class URL implements Serializable
     // If a non-default factory has been set, use it to find the protocol.
     if (factory != null)
       handler = factory.createURLStreamHandler(protocol);
+    else if (protocol.equals ("file"))
+      {
+       // This is an interesting case.  It's tempting to think that we
+       // could call Class.forName ("gnu.gcj.protocol.file.Handler") to
+       // get the appropriate class.  Unfortunately, if we do that the
+       // program will never terminate, because setURLStreamHandler is
+       // eventually called by Class.forName.
+       //
+       // Treating "file" as a special case is the minimum that will
+       // fix this problem.  If other protocols are required in a
+       // statically linked application they will need to be handled in
+       // the same way as "file".
+       handler = new gnu.gcj.protocol.file.Handler ();
+      }
 
     // Non-default factory may have returned null or a factory wasn't set.
     // Use the default search algorithm to find a handler for this protocol.
diff --git a/libjava/java/security/BasicPermission.java b/libjava/java/security/BasicPermission.java
new file mode 100644 (file)
index 0000000..f2e70ed
--- /dev/null
@@ -0,0 +1,271 @@
+/* BasicPermission.java -- Implements a simple named permission.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.security;
+
+import java.io.Serializable;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/**
+  * This class implements a simple model for named permissions without an
+  * associated action list.  That is, either the named permission is granted
+  * or it is not.  
+  * <p>
+  * It also supports trailing wildcards to allow the
+  * easy granting of permissions in a hierarchical fashion.  (For example,
+  * the name "org.gnu.*" might grant all permissions under the "org.gnu"
+  * permissions hierarchy).  The only valid wildcard character is a '*'
+  * which matches anything.  It must be the rightmost element in the
+  * permission name and must follow a '.' or else the Permission name must
+  * consist of only a '*'.  Any other occurrence of a '*' is not valid.
+  * <p>
+  * This class ignores the action list.  Subclasses can choose to implement
+  * actions on top of this class if desired.
+  *
+  * @version 0.1
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public abstract class BasicPermission extends Permission implements Serializable
+{
+
+  /*************************************************************************/
+
+  /*
+   * Constructors
+   */
+
+  /**
+   * This method initializes a new instance of <code>BasicPermission</code>
+   * with the specified name.  If the name contains an illegal wildcard
+   * character, an exception is thrown.
+   *
+   * @param name The name of this permission.
+   *
+   * @exception IllegalArgumentException If the name contains an invalid wildcard character
+   * @exception NullPointerException If the name is null
+   */
+  public 
+  BasicPermission(String name) throws IllegalArgumentException, NullPointerException
+  {
+    super(name);
+
+    if (name.indexOf("*") != -1)
+      {
+       if (!name.endsWith(".*") && !name.equals("*"))
+          throw new IllegalArgumentException("Bad wildcard: " + name);
+
+       if (name.indexOf("*") != name.lastIndexOf("*"))
+          throw new IllegalArgumentException("Bad wildcard: " + name);
+      }
+  }
+
+  /*************************************************************************/
+
+  /**
+   * This method initializes a new instance of <code>BasicPermission</code>
+   * with the specified name.  If the name contains an illegal wildcard
+   * character, an exception is thrown.  The action list passed to this
+   * form of the constructor is ignored.
+   *
+   * @param name The name of this permission.
+   * @param actions The list of actions for this permission - ignored in this class.
+   *
+   * @exception IllegalArgumentException If the name contains an invalid wildcard character
+   * @exception NullPointerException If the name is null
+   */
+  public
+  BasicPermission(String name, String actions) throws IllegalArgumentException, NullPointerException
+  {
+    // ignore actions
+    this(name);
+  }
+
+  /*************************************************************************/
+
+  /**
+   * This method tests to see if the specified permission is implied by 
+   * this permission.  This will be true if the following conditions are met:
+   * <p>
+   * <ul>
+   * <li>The specified object is an instance of <code>BasicPermission</code>, 
+   * or a subclass.
+   * <li>The name of the specified permission is identical to this permission's
+   * name or the name of the specified permission satisfies a wildcard match 
+   * on this permission.
+   * </ul>
+   *
+   * @param perm The <code>Permission</code> object to test against.
+   *
+   * @return <code>true</code> if the specified permission is implied by this one or <code>false</code> otherwise.
+   */
+  public boolean
+  implies(Permission perm)
+  {
+    if (!(perm instanceof BasicPermission))
+      return false;
+
+    String otherName = perm.getName();
+    String name = getName();
+
+    if (name.equals(otherName))
+      return true;
+
+    int last = name.length() - 1;
+    if (name.charAt(last) == '*'
+       && otherName.startsWith(name.substring(0, last)))
+      return true;
+
+    return false;
+  }
+
+  /*************************************************************************/
+
+  /**
+   * This method tests to see if this object is equal to the specified
+   * <code>Object</code>.  This will be true if and only if the specified
+   * object meets the following conditions:
+   * <p>
+   * <ul>
+   * <li>It is an instance of <code>BasicPermission</code>, or a subclass.
+   * <li>It has the same name as this permission.
+   * </ul>
+   *
+   * @param obj The <code>Object</code> to test for equality against this object
+   *
+   * @return <code>true</code> if the specified <code>Object</code> is equal to this object or <code>false</code> otherwise.
+   */
+  public boolean
+  equals(Object obj)
+  {
+    if (!(obj instanceof BasicPermission))
+      return(false);
+
+    if (!getName().equals(((BasicPermission)obj).getName()))
+      return(false);
+
+    return(true);
+  }
+
+  /*************************************************************************/
+
+  /**
+   * This method returns a hash code for this permission object.  The hash
+   * code returned is the value returned by calling the <code>hashCode</code>
+   * method on the <code>String</code> that is the name of this permission.
+   *
+   * @return A hash value for this object
+   */
+  public int
+  hashCode()
+  {
+    return(getName().hashCode());
+  }
+
+  /*************************************************************************/
+
+  /**
+   * This method returns a list of the actions associated with this 
+   * permission.  This method always returns the empty string ("") since
+   * this class ignores actions.
+   *
+   * @return The action list.
+   */
+  public String
+  getActions()
+  {
+    return("");
+  }
+
+  /*************************************************************************/
+
+  /**
+   * This method returns an instance of <code>PermissionCollection</code>
+   * suitable for storing <code>BasicPermission</code> objects.  This returns
+   * be a sub class of <code>PermissionCollection</code>
+   * that allows for an efficient and consistent implementation of
+   * the <code>implies</code> method.  The collection doesn't handle subclasses
+   * of BasicPermission correctly; they must override this method. 
+   *
+   * @return A new empty <code>PermissionCollection</code> object.
+   */
+  public PermissionCollection
+  newPermissionCollection()
+  {
+    return new PermissionCollection() 
+      {
+       Hashtable permissions = new Hashtable();
+       boolean allAllowed = false;
+      
+       public void add(Permission permission) 
+       {
+         if (isReadOnly())
+           throw new IllegalStateException("readonly");
+
+         BasicPermission bp = (BasicPermission) permission;
+         String name = bp.getName();
+         if (name.equals("*"))
+           allAllowed = true;
+         permissions.put(name, bp);
+       }
+      
+       public boolean implies(Permission permission)
+       {
+         if (!(permission instanceof BasicPermission))
+           return false;
+           
+         if (allAllowed)
+           return true;
+
+         BasicPermission toImply = (BasicPermission) permission;
+         String name = toImply.getName();
+         if (name.equals("*"))
+           return false;
+
+         int prefixLength = name.length();
+         if (name.endsWith("*"))
+           prefixLength -= 2;
+
+         while (true) {
+           if (permissions.get(name) != null)
+             return true;
+             
+           prefixLength = name.lastIndexOf('.', prefixLength);
+           if (prefixLength < 0)
+             return false;
+           name = name.substring(0, prefixLength + 1) + '*';
+         }
+       }
+      
+       public Enumeration elements()
+       {
+         return permissions.elements();
+       }
+      };
+  }
+} // class BasicPermission
diff --git a/libjava/java/security/DigestOutputStream.java b/libjava/java/security/DigestOutputStream.java
new file mode 100644 (file)
index 0000000..8d51278
--- /dev/null
@@ -0,0 +1,147 @@
+/* DigestOutputStream.java --- An output stream tied to a message digest
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.security;
+
+import java.io.OutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+
+/**
+   DigestOutputStream is a class that ties an OutputStream with a
+   MessageDigest. The Message Digest is used by the class to update it
+   self as bytes are written to the OutputStream.
+
+   The updating to the digest depends on the on flag which is set to
+   true by default that tells the class to update the data in the
+   message digest.
+
+   @version 0.0
+   @author Mark Benvenuto <ivymccough@worldnet.att.net>
+*/
+public class DigestOutputStream extends FilterOutputStream
+{
+  /**
+     The message digest for the DigestOutputStream
+  */
+  protected MessageDigest digest;
+
+  //Manages the on flag
+  private boolean state = true;
+
+  /**
+     Constructs a new DigestOutputStream.  It associates a
+     MessageDigest with the stream to compute the stream as data is
+     written.
+
+     @param stream An OutputStream to associate this stream with
+     @param digest A MessageDigest to hash the stream with
+  */
+  public DigestOutputStream (OutputStream stream, MessageDigest digest)
+  {
+    super (stream);
+    this.digest = digest;
+  }
+
+  /**
+     Returns the MessageDigest associated with this DigestOutputStream
+
+     @return The MessageDigest used to hash this stream
+  */
+  public MessageDigest getMessageDigest ()
+  {
+    return digest;
+  }
+  
+  /**
+     Sets the current MessageDigest to current parameter
+       
+     @param digest A MessageDigest to associate with this stream
+  */
+  public void setMessageDigest (MessageDigest digest)
+  {
+    this.digest = digest;
+  }
+
+
+  /**
+     Updates the hash if the on flag is true and then writes a byte to
+     the underlying output stream.
+
+     @param b A byte to write to the output stream
+     
+     @exception IOException if the underlying output stream 
+     cannot write the byte, this is thrown.
+  */
+  public void write (int b) throws IOException
+  {
+    if (state)
+      digest.update ((byte)b);
+    
+    super.write (b);
+  }
+
+  /**
+     Updates the hash if the on flag is true and then writes the bytes
+     to the underlying output stream.
+
+     @param b Bytes to write to the output stream
+     @param off Offset to start to start at in array
+     @param len Length of data to write
+
+     @exception IOException if the underlying output stream 
+     cannot write the bytes, this is thrown.
+  */
+  public void write (byte[] b, int off, int len) throws IOException
+  {
+    if (state)
+      digest.update (b, off, len);
+
+    super.write (b, off, len);
+  }
+
+  /**
+     Sets the flag specifying if this DigestOutputStream updates the
+     digest in the write() methods. The default is on;
+
+     @param on True means it digests stream, false means it does not
+  */
+  public void on (boolean on)
+  {
+    state = on;
+  }
+
+  /**
+     Converts the output stream and underlying message digest to a string.
+
+     @return A string representing the output stream and message digest.
+  */
+  public String toString()
+  {
+    return "[Digest Output Stream] " + digest.toString();
+  }
+}
diff --git a/libjava/java/security/Guard.java b/libjava/java/security/Guard.java
new file mode 100644 (file)
index 0000000..b397ddd
--- /dev/null
@@ -0,0 +1,54 @@
+/* Guard.java -- Check access to a guarded object
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.security;
+
+/**
+  * This interface specifies a mechanism for querying whether or not
+  * access is allowed to a guarded object.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public interface Guard
+{
+
+/**
+  * This method tests whether or not access is allowed to the specified
+  * guarded object.  Access is allowed if this method returns silently.  If
+  * access is denied, an exception is generated.
+  *
+  * @param obj The <code>Object</code> to test
+  *
+  * @exception SecurityException If access to the object is denied.
+  */
+public abstract void
+checkGuard(Object obj) throws SecurityException;
+
+} // interface Guard
+
diff --git a/libjava/java/security/Permission.java b/libjava/java/security/Permission.java
new file mode 100644 (file)
index 0000000..620d5b4
--- /dev/null
@@ -0,0 +1,191 @@
+/* Permission.java -- The superclass for all permission objects
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.security;
+
+import java.io.Serializable;
+
+/**
+  * This class is the abstract superclass of all classes that implement
+  * the concept of a permission.  A permission consists of a permission name 
+  * and optionally a list of actions that relate to the permission.  The
+  * actual meaning of the name of the permission is defined only in the
+  * context of a subclass.  It may name a resource to which access permissions
+  * are granted (for example, the name of a file) or it might represent
+  * something else entirely.  Similarly, the action list only has meaning
+  * within the context of a subclass.  Some permission names may have no
+  * actions associated with them.  That is, you either have the permission
+  * or you don't.
+  *
+  * The most important method in this class is <code>implies</code>.  This
+  * checks whether if one has this permission, then the specified
+  * permission is also implied.  As a conceptual example, consider the
+  * permissions "Read All Files" and "Read File foo".  The permission
+  * "Read All Files" implies that the caller has permission to read the
+  * file foo.
+  *
+  * <code>Permission</code>'s are not dynamic objects.  Once created, a 
+  * <code>Permission</code>'s name and action list cannot be changed.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public abstract class Permission implements Guard, Serializable
+{
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+  * This is the name assigned to this permission object.
+  */ 
+protected String name; // Taken from the serializable form information
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+  * This method initializes a new instance of <code>Permission</code> to
+  * have the specified name.
+  */
+public
+Permission(String name)
+{
+  this.name = name;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+  * This method returns the name of this <code>Permission</code>
+  *
+  * @return The name of this <code>Permission</code>
+  */
+public String
+getName()
+{
+  return(name);
+}
+
+/*************************************************************************/
+
+/**
+  * This method returns the list of actions for this <code>Permission</code>
+  * as a <code>String</code>.
+  *
+  * @return The action list for this <code>Permission</code>.
+  */
+public abstract String
+getActions();
+
+/*************************************************************************/
+
+/**
+  * This method implements the <code>Guard</code> interface for this class.
+  * It calls the <code>checkPermission</code> method in 
+  * <code>SecurityManager</code> with this <code>Permission</code> as its
+  * argument.  This method returns silently if the security check succeeds
+  * or throws an exception if it fails.
+  *
+  * @param obj The <code>Object</code> being guarded - ignored by this class
+  *
+  * @exception SecurityException If the security check fails
+  */
+public void
+checkGuard(Object obj) throws SecurityException
+{
+  SecurityManager sm = System.getSecurityManager();
+//  if (sm != null)
+//    sm.checkPermission(this);
+}
+  
+/*************************************************************************/
+
+/**
+  * This method tests whether this <code>Permission</code> implies that the
+  * specified <code>Permission</code> is also granted.
+  *
+  * @param perm The <code>Permission</code> to test against
+  *
+  * @return <code>true</code> if the specified <code>Permission</code> is implied by this one, <code>false</code> otherwise.
+  */
+public abstract boolean
+implies(Permission perm);
+
+/*************************************************************************/
+
+/**
+  * This method returns a hash code for this <code>Permission</code>.
+  *
+  * @return A hash value.
+  */
+public abstract int
+hashCode();
+
+/*************************************************************************/
+
+/**
+  * This method returns a <code>String</code> representation of this
+  * <code>Permission</code> object.
+  *
+  * @return This object as a <code>String</code>.
+  */
+public String
+toString()
+{
+  return("'\"" + getClass().getName() + "\" \"" + getName() + 
+         "\"" + " \"" + getActions() + "\")'");
+}
+
+/*************************************************************************/
+
+/**
+  * This method returns an empty <code>PermissionCollection</code> object
+  * that can store permissions of this type, or <code>null</code> if no
+  * such collection is defined.
+  *
+  * @return A new <code>PermissionCollection</code>
+  */
+public PermissionCollection
+newPermissionCollection()
+{
+  return(null);
+}
+
+} // class Permission
+
diff --git a/libjava/java/security/PermissionCollection.java b/libjava/java/security/PermissionCollection.java
new file mode 100644 (file)
index 0000000..08a9c49
--- /dev/null
@@ -0,0 +1,207 @@
+/* PermissionCollection.java -- A collection of permission objects
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.security;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+
+/**
+  * This class models a group of Java permissions.  It has convenient
+  * methods for determining whether or not a given permission is implied
+  * by any of the permissions in this collection.
+  * <p>
+  * Some care must be taken in storing permissions.  First, a collection of
+  * the appropriate type must be created.  This is done by calling the
+  * <code>newPermissionCollection</code> method on an object of the 
+  * permission class you wish to add to the collection.  If this method
+  * returns <code>null</code>, any type of <code>PermissionCollection</code>
+  * can be used to store permissions of that type.  However, if a
+  * <code>PermissionCollection</code> collection object is returned, that
+  * type must be used.  
+  * <p>
+  * The <code>PermissionCollection</code>'s returned
+  * by the <code>newPermissionCollection</code> instance in a subclass of
+  * <code>Permission</code> is a homogeneous collection.  It only will 
+  * hold permissions of one specified type - instances of the class that
+  * created it.  Not all <code>PermissionCollection</code> subclasses
+  * have to hold permissions of only one type however.  For example,
+  * the <code>Permissions</code> class holds permissions of many types.
+  * <p>
+  * Since the <code>newPermissionCollection</code> in <code>Permission</code>
+  * itself returns <code>null</code>, by default a permission can be stored
+  * in any type of collection unless it overrides that method to create its
+  * own collection type.
+  *
+  * @version 0.0
+  *
+  * @author Aaron M. Renn (arenn@urbanophile.com)
+  */
+public abstract class PermissionCollection extends Object implements Serializable
+{
+
+/*************************************************************************/
+
+/*
+ * Class Variables
+ */
+
+public static final String linesep = null;
+
+static
+{
+  String linesep = System.getProperty("line.separator");
+  if (linesep == null);
+    linesep = "\n";
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Variables
+ */
+
+/**
+  * Indicates whether or not this collection is read only.
+  */
+private boolean readOnly; 
+
+/*************************************************************************/
+
+/*
+ * Constructors
+ */
+
+/**
+  * This method initializes a new instance of <code>PermissionCollection</code>.
+  * This is provided only as a default constructor and does nothing in this
+  * class.
+  */
+public
+PermissionCollection()
+{
+  ;
+}
+
+/*************************************************************************/
+
+/*
+ * Instance Methods
+ */
+
+/**
+  * This method tests whether or not this <code>PermissionCollection</code>
+  * object is read only.
+  *
+  * @return <code>true</code> if this collection is read only, <code>false</code> otherwise
+  */
+public boolean
+isReadOnly()
+{
+  return(readOnly);
+}
+
+/*************************************************************************/
+
+/**
+  * This method sets this <code>PermissionCollection</code> object to be
+  * read only.  No further permissions can be added to it after calling this
+  * method.
+  */
+public void
+setReadOnly()
+{
+  readOnly = true;
+}
+
+/*************************************************************************/
+
+/**
+  * This method adds a new <code>Permission</code> object to the collection.
+  *
+  * @param perm The <code>Permission</code> to add.
+  *
+  * @exception SecurityException If the collection is marked read only.
+  * @exception IllegalArgumentException If a permission of the specified type cannot be added
+  */
+public abstract void
+add(Permission perm) throws SecurityException, IllegalArgumentException;
+
+/*************************************************************************/
+
+/**
+  * This method returns an <code>Enumeration</code> of all the objects in
+  * this collection.
+  *
+  * @return An <code>Enumeration</code> of this collection's objects.
+  */
+public abstract Enumeration
+elements();
+
+/*************************************************************************/
+
+/**
+  * This method tests whether the specified <code>Permission</code> object is
+  * implied by this collection of <code>Permission</code> objects.
+  *
+  * @param perm The <code>Permission</code> object to test.
+  *
+  * @return <code>true</code> if the specified <code>Permission</code> is implied by this collection, <code>false</code> otherwise.
+  */
+public abstract boolean
+implies(Permission perm);
+
+/*************************************************************************/
+
+/**
+  * This method returns a <code>String</code> representation of this
+  * collection.  It will print the class name and has code in the same
+  * manner as <code>Object.toString()</code> then print a listing of all
+  * the <code>Permission</code> objects contained.
+  *
+  * @return A <code>String</code> representing this object.
+  */
+public String
+toString()
+{
+  StringBuffer sb = new StringBuffer("");
+
+  sb.append(super.toString() + " (" + linesep);
+  Enumeration e = elements();
+  while (e.hasMoreElements())
+    {
+      Object obj = e.nextElement();
+      if (obj instanceof Permission)
+        sb.append(((Permission)obj).toString() + linesep);
+    }
+
+  sb.append(")" + linesep);
+  return(sb.toString());
+}
+
+} // class PermissionCollection
+
diff --git a/libjava/java/util/AbstractCollection.java b/libjava/java/util/AbstractCollection.java
new file mode 100644 (file)
index 0000000..8002044
--- /dev/null
@@ -0,0 +1,339 @@
+/* AbstractCollection.java -- Abstract implementation of most of Collection
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package java.util;
+
+import java.lang.reflect.Array;
+
+/**
+ * A basic implementation of most of the methods in the Collection interface to
+ * make it easier to create a collection. To create an unmodifiable Collection,
+ * just subclass AbstractCollection and provide implementations of the
+ * iterator() and size() methods. The Iterator returned by iterator() need only
+ * provide implementations of hasNext() and next() (that is, it may throw an
+ * UnsupportedOperationException if remove() is called). To create a modifiable
+ * Collection, you must in addition provide an implementation of the
+ * add(Object) method and the Iterator returned by iterator() must provide an
+ * implementation of remove(). Other methods should be overridden if the
+ * backing data structure allows for a more efficient implementation. The
+ * precise implementation used by AbstractCollection is documented, so that
+ * subclasses can tell which methods could be implemented more efficiently.
+ */
+public abstract class AbstractCollection implements Collection {
+
+  /**
+   * Return an Iterator over this collection. The iterator must provide the
+   * hasNext and next methods and should in addition provide remove if the
+   * collection is modifiable.
+   */
+  public abstract Iterator iterator();
+
+  /**
+   * Return the number of elements in this collection.
+   */
+  public abstract int size();
+
+  /**
+   * Add an object to the collection. This implementation always throws an
+   * UnsupportedOperationException - it should be overridden if the collection
+   * is to be modifiable.
+   *
+   * @param o the object to add
+   * @return true if the add operation caused the Collection to change
+   * @exception UnsupportedOperationException if the add operation is not
+   *   supported on this collection
+   */
+  public boolean add(Object o) {
+    throw new java.lang.UnsupportedOperationException();
+  }
+
+  /**
+   * Add all the elements of a given collection to this collection. This
+   * implementation obtains an Iterator over the given collection and iterates
+   * over it, adding each element with the add(Object) method (thus this method
+   * will fail with an UnsupportedOperationException if the add method does).
+   *
+   * @param c the collection to add the elements of to this collection
+   * @return true if the add operation caused the Collection to change
+   * @exception UnsupportedOperationException if the add operation is not
+   *   supported on this collection
+   */
+  public boolean addAll(Collection c) {
+    Iterator i = c.iterator();
+    boolean modified = false;
+    while (i.hasNext()) {
+      modified |= add(i.next());
+    }
+    return modified;
+  }
+
+  /**
+   * Remove all elements from the collection. This implementation obtains an
+   * iterator over the collection and calls next and remove on it repeatedly
+   * (thus this method will fail with an UnsupportedOperationException if the
+   * Iterator's remove method does) until there are no more elements to remove.
+   * Many implementations will have a faster way of doing this.
+   *
+   * @exception UnsupportedOperationException if the Iterator returned by
+   *   iterator does not provide an implementation of remove
+   */
+  public void clear() {
+    Iterator i = iterator();
+    while (i.hasNext()) {
+      i.next();
+      i.remove();
+    }
+  }
+
+  /**
+   * Test whether this collection contains a given object. That is, if the
+   * collection has an element e such that (o == null ? e == null :
+   * o.equals(e)). This implementation obtains an iterator over the collection
+   * and iterates over it, testing each element for equality with the given
+   * object. If it is equal, true is returned. Otherwise false is returned when
+   * the end of the collection is reached.
+   *
+   * @param o the object to remove from this collection
+   * @return true if this collection contains an object equal to o
+   */
+  public boolean contains(Object o) {
+    Iterator i = iterator();
+
+    // This looks crazily inefficient, but it takes the test o==null outside
+    // the loop, saving time, and also saves needing to store the result of
+    // i.next() each time.
+    if (o == null) {
+      while (i.hasNext()) {
+        if (i.next() == null) {
+          return true;
+        }
+      }
+    } else {
+      while (i.hasNext()) {
+        if (o.equals(i.next())) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Tests whether this collection contains all the elements in a given
+   * collection. This implementation iterates over the given collection,
+   * testing whether each element is contained in this collection. If any one
+   * is not, false is returned. Otherwise true is returned.
+   *
+   * @param c the collection to test against
+   * @return true if this collection contains all the elements in the given
+   *   collection
+   */
+  public boolean containsAll(Collection c) {
+    Iterator i = c.iterator();
+    while (i.hasNext()) {
+      if (!contains(i.next())) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Test whether this collection is empty. This implementation returns
+   * size() == 0.
+   *
+   * @return true if this collection is empty.
+   */
+  public boolean isEmpty() {
+    return size() == 0;
+  }
+
+  /**
+   * Remove a single instance of an object from this collection. That is,
+   * remove one element e such that (o == null ? e == null : o.equals(e)), if
+   * such an element exists. This implementation obtains an iterator over the
+   * collection and iterates over it, testing each element for equality with
+   * the given object. If it is equal, it is removed by the iterator's remove
+   * method (thus this method will fail with an UnsupportedOperationException
+   * if the Iterator's remove method does). After the first element has been
+   * removed, true is returned; if the end of the collection is reached, false
+   * is returned.
+   *
+   * @param o the object to remove from this collection
+   * @return true if the remove operation caused the Collection to change, or
+   *   equivalently if the collection did contain o.
+   * @exception UnsupportedOperationException if this collection's Iterator
+   *   does not support the remove method
+   */
+  public boolean remove(Object o) {
+    Iterator i = iterator();
+
+    // This looks crazily inefficient, but it takes the test o==null outside
+    // the loop, saving time, and also saves needing to store the result of
+    // i.next() each time.
+    if (o == null) {
+      while (i.hasNext()) {
+        if (i.next() == null) {
+          i.remove();
+         return true;
+        }
+      }
+    } else {
+      while (i.hasNext()) {
+        if (o.equals(i.next())) {
+          i.remove();
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Remove from this collection all its elements that are contained in a given
+   * collection. This implementation iterates over this collection, and for
+   * each element tests if it is contained in the given collection. If so, it
+   * is removed by the Iterator's remove method (thus this method will fail
+   * with an UnsupportedOperationException if the Iterator's remove method
+   * does).
+   *
+   * @param c the collection to remove the elements of
+   * @return true if the remove operation caused the Collection to change
+   * @exception UnsupportedOperationException if this collection's Iterator
+   *   does not support the remove method
+   */
+  public boolean removeAll(Collection c) {
+    Iterator i = iterator();
+    boolean changed = false;
+    while (i.hasNext()) {
+      if (c.contains(i.next())) {
+        i.remove();
+        changed = true;
+      }
+    }
+    return changed;
+  }
+
+  /**
+   * Remove from this collection all its elements that are not contained in a
+   * given collection. This implementation iterates over this collection, and
+   * for each element tests if it is contained in the given collection. If not,
+   * it is removed by the Iterator's remove method (thus this method will fail
+   * with an UnsupportedOperationException if the Iterator's remove method
+   * does).
+   *
+   * @param c the collection to retain the elements of
+   * @return true if the remove operation caused the Collection to change
+   * @exception UnsupportedOperationException if this collection's Iterator
+   *   does not support the remove method
+   */
+  public boolean retainAll(Collection c) {
+    Iterator i = iterator();
+    boolean changed = false;
+    while (i.hasNext()) {
+      if (!c.contains(i.next())) {
+        i.remove();
+        changed = true;
+      }
+    }
+    return changed;
+  }
+
+  /**
+   * Return an array containing the elements of this collection. This
+   * implementation creates an Object array of size size() and then iterates
+   * over the collection, setting each element of the array from the value
+   * returned by the iterator.
+   *
+   * @return an array containing the elements of this collection
+   */
+  public Object[] toArray() {
+    Object[] a = new Object[size()];
+    Iterator i = iterator();
+    for (int pos = 0; pos < a.length; pos++) {
+      a[pos] = i.next();
+    }
+    return a;
+  }
+
+  /**
+   * Copy the collection into a given array if it will fit, or into a
+   * dynamically created array of the same run-time type as the given array if
+   * not. If there is space remaining in the array, the first element after the
+   * end of the collection is set to null (this is only useful if the
+   * collection is known to contain no null elements, however). This
+   * implementation first tests whether the given array is large enough to hold
+   * all the elements of the collection. If not, the reflection API is used to
+   * allocate a new array of the same run-time type. Next an iterator is
+   * obtained over the collection and the elements are placed in the array as
+   * they are returned by the iterator. Finally the first spare element, if
+   * any, of the array is set to null, and the created array is returned.
+   *
+   * @param a the array to copy into, or of the correct run-time type
+   * @return the array that was produced
+   * @exception ClassCastException if the type of the array precludes holding
+   *   one of the elements of the Collection
+   */
+  public Object[] toArray(Object[] a) {
+    final int n = size();
+    if (a.length < n) {
+      a = (Object[])Array.newInstance(a.getClass().getComponentType(), n);
+    }
+    Iterator i = iterator();
+    for (int pos = 0; pos < n; pos++) {
+      a[pos] = i.next();
+    }
+    if (a.length > n) {
+      a[n] = null;
+    }
+    return a;
+  }
+
+  /**
+   * Creates a String representation of the Collection. The string returned is
+   * of the form "[a, b, ...]" where a and b etc are the results of calling
+   * toString on the elements of the collection. This implementation obtains an
+   * Iterator over the Collection and adds each element to a StringBuffer as it
+   * is returned by the iterator.
+   *
+   * @return a String representation of the Collection
+   */
+  public String toString() {
+    StringBuffer s = new StringBuffer();
+    s.append('[');
+    Iterator i = iterator();
+    boolean more = i.hasNext();
+    while(more) {
+      s.append(i.next());
+      if (more = i.hasNext()) {
+        s.append(", ");
+      }
+    }
+    s.append(']');
+    return s.toString();
+  }
+}
diff --git a/libjava/java/util/AbstractList.java b/libjava/java/util/AbstractList.java
new file mode 100644 (file)
index 0000000..da76a8b
--- /dev/null
@@ -0,0 +1,558 @@
+/* AbstractList.java -- Abstract implementation of most of List
+   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+// TO DO:
+// ~ Doc comments for almost everything.
+// ~ Better general commenting
+
+package java.util;
+
+/**
+ * A basic implementation of most of the methods in the List interface to make
+ * it easier to create a List based on a random-access data structure. To
+ * create an unmodifiable list, it is only necessary to override the size() and
+ * get(int) methods (this contrasts with all other abstract collection classes
+ * which require an iterator to be provided). To make the list modifiable, the
+ * set(int, Object)  method should also be overridden, and to make the list
+ * resizable, the add(int, Object) and remove(int) methods should be overridden
+ * too. Other methods should be overridden if the backing data structure allows
+ * for a more efficient implementation. The precise implementation used by
+ * AbstractList is documented, so that subclasses can tell which methods could
+ * be implemented more efficiently.
+ */
+public abstract class AbstractList extends AbstractCollection implements List {
+
+  /**
+   * A count of the number of structural modifications that have been made to
+   * the list (that is, insertions and removals).
+   */
+  protected transient int modCount = 0;
+
+  public abstract Object get(int index);
+
+  public void add(int index, Object o) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean add(Object o) {
+    add(size(), o);
+    return true;
+  }
+
+  public boolean addAll(int index, Collection c) {
+    Iterator i = c.iterator();
+    if (i.hasNext()) {
+      do {
+        add(index++, i.next());
+      } while (i.hasNext());
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  public void clear() {
+    removeRange(0, size());
+  }
+
+  public boolean equals(Object o) {
+    if (o == this) {
+      return true;
+    } else if (!(o instanceof List)) {
+      return false;
+    } else {
+      Iterator i1 = iterator();
+      Iterator i2 = ((List)o).iterator();
+      while (i1.hasNext()) {
+        if (!i2.hasNext()) {
+          return false;
+        } else {
+          Object e = i1.next();
+          if (e == null ? i2.next() != null : !e.equals(i2.next())) {
+            return false;
+          }
+        }
+      }
+      if (i2.hasNext()) {
+        return false;
+      } else {
+        return true;
+      }
+    }
+  }
+
+  public int hashCode() {
+    int hashCode = 1;
+    Iterator i = iterator();
+    while (i.hasNext()) {
+      Object obj = i.next();
+      hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
+    }
+    return hashCode;
+  }
+
+  public int indexOf(Object o) {
+    int index = 0;
+    ListIterator i = listIterator();
+    if (o == null) {
+      while (i.hasNext()) {
+        if (i.next() == null) {
+          return index;
+        }
+        index++;
+      }
+    } else {
+      while (i.hasNext()) {
+        if (o.equals(i.next())) {
+          return index;
+        }
+        index++;
+      }
+    }
+    return -1;
+  }
+
+  public Iterator iterator() {
+    return new Iterator() {
+      private int knownMod = modCount;
+      private int position = 0;
+      boolean removed = true;
+
+      private void checkMod() {
+        if (knownMod != modCount) {
+          throw new ConcurrentModificationException();
+        }
+      }
+
+      public boolean hasNext() {
+        checkMod();
+        return position < size();
+      }
+
+      public Object next() {
+        checkMod();
+        removed = false;
+        try {
+          return get(position++);
+        } catch (IndexOutOfBoundsException e) {
+          throw new NoSuchElementException();
+        }
+      }
+
+      public void remove() {
+        checkMod();
+        if (removed) {
+          throw new IllegalStateException();
+        }
+        AbstractList.this.remove(--position);
+        knownMod = modCount;
+        removed = true;
+      }
+    };
+  }
+
+  public int lastIndexOf(Object o) {
+    int index = size();
+    ListIterator i = listIterator(index);
+    if (o == null) {
+      while (i.hasPrevious()) {
+        index--;
+        if (i.previous() == null) {
+          return index;
+        }
+      }
+    } else {
+      while (i.hasPrevious()) {
+        index--;
+        if (o.equals(i.previous())) {
+          return index;
+        }
+      }
+    }
+    return -1;
+  }
+
+  public ListIterator listIterator() {
+    return listIterator(0);
+  }
+
+  public ListIterator listIterator(final int index) {
+
+    if (index < 0 || index > size()) {
+      throw new IndexOutOfBoundsException();
+    }
+
+    return new ListIterator() {
+      private int knownMod = modCount;
+      private int position = index;
+      private int lastReturned = -1;
+
+      private void checkMod() {
+        if (knownMod != modCount) {
+          throw new ConcurrentModificationException();
+        }
+      }
+
+      public boolean hasNext() {
+        checkMod();
+        return position < size();
+      }
+
+      public boolean hasPrevious() {
+        checkMod();
+        return position > 0;
+      }
+
+      public Object next() {
+        checkMod();
+        if (hasNext()) {
+          lastReturned = position++;
+          return get(lastReturned);
+        } else {
+          throw new NoSuchElementException();
+        }
+      }
+
+      public Object previous() {
+        checkMod();
+        if (hasPrevious()) {
+          lastReturned = --position;
+          return get(lastReturned);
+        } else {
+          throw new NoSuchElementException();
+        }
+      }
+
+      public int nextIndex() {
+        checkMod();
+        return position;
+      }
+
+      public int previousIndex() {
+        checkMod();
+        return position - 1;
+      }
+
+      public void remove() {
+        checkMod();
+        if (lastReturned < 0) {
+          throw new IllegalStateException();
+        }
+        AbstractList.this.remove(lastReturned);
+        knownMod = modCount;
+        position = lastReturned;
+        lastReturned = -1;
+      }
+
+      public void set(Object o) {
+        checkMod();
+        if (lastReturned < 0) {
+          throw new IllegalStateException();
+        }
+        AbstractList.this.set(lastReturned, o);
+      }
+
+      public void add(Object o) {
+        checkMod();
+        AbstractList.this.add(position++, o);
+        lastReturned = -1;
+        knownMod = modCount;
+      }
+    };
+  }
+
+  public Object remove(int index) {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Remove a subsection of the list. This is called by the clear and
+   * removeRange methods of the class which implements subList, which are
+   * difficult for subclasses to override directly. Therefore, this method
+   * should be overridden instead by the more efficient implementation, if one
+   * exists.
+   * <p>
+   * This implementation first checks for illegal or out of range arguments. It
+   * then obtains a ListIterator over the list using listIterator(fromIndex).
+   * It then calls next() and remove() on this iterator repeatedly, toIndex -
+   * fromIndex times.
+   *
+   * @param fromIndex the index, inclusive, to remove from.
+   * @param toIndex the index, exclusive, to remove to.
+   * @exception UnsupportedOperationException if this list does not support
+   *   the removeRange operation.
+   * @exception IndexOutOfBoundsException if fromIndex > toIndex || fromIndex <
+   *   0 || toIndex > size().
+   */
+  protected void removeRange(int fromIndex, int toIndex) {
+    if (fromIndex > toIndex) {
+      throw new IllegalArgumentException();
+    } else if (fromIndex < 0 || toIndex > size()) {
+      throw new IndexOutOfBoundsException();
+    } else {
+      ListIterator i = listIterator(fromIndex);
+      for (int index = fromIndex; index < toIndex; index++) {
+        i.next();
+        i.remove();
+      }
+    }
+  }
+
+  public Object set(int index, Object o) {
+    throw new UnsupportedOperationException();
+  }
+
+  public List subList(final int fromIndex, final int toIndex) {
+    if (fromIndex > toIndex)
+      throw new IllegalArgumentException();
+    if (fromIndex < 0 || toIndex > size())
+      throw new IndexOutOfBoundsException();
+    return new SubList(this, fromIndex, toIndex);
+  }
+
+  static class SubList extends AbstractList {
+
+    private AbstractList backingList;
+    private int offset;
+    private int size;
+
+    public SubList(AbstractList backing, int fromIndex, int toIndex) {
+      backingList = backing;
+      upMod();
+      offset = fromIndex;
+      size = toIndex - fromIndex;
+    }
+
+    // Note that within this class two fields called modCount are inherited -
+    // one from the superclass, and one from the outer class. 
+    // The code uses both these two fields and *no other* to provide fail-fast
+    // behaviour. For correct operation, the two fields should contain equal
+    // values. Therefore, if this.modCount != backingList.modCount, there
+    // has been a concurrent modification. This is all achieved purely by using
+    // the modCount field, precisely according to the docs of AbstractList.
+    // See the methods upMod and checkMod.
+
+    /**
+     * This method checks the two modCount fields to ensure that there has
+     * not been a concurrent modification. It throws an exception if there
+     * has been, and otherwise returns normally.
+     * Note that since this method is private, it will be inlined.
+     *
+     * @exception ConcurrentModificationException if there has been a
+     *   concurrent modification.
+     */
+    private void checkMod() {
+      if (this.modCount != backingList.modCount) {
+       throw new ConcurrentModificationException();
+      }
+    }
+    
+    /**
+     * This method is called after every method that causes a structural
+     * modification to the backing list. It updates the local modCount field
+     * to match that of the backing list.
+     * Note that since this method is private, it will be inlined.
+     */
+    private void upMod() {
+      this.modCount = backingList.modCount;
+    }
+    
+    /**
+     * This method checks that a value is between 0 and size (inclusive). If
+     * it is not, an exception is thrown.
+     * Note that since this method is private, it will be inlined.
+     *
+     * @exception IndexOutOfBoundsException if the value is out of range.
+     */
+    private void checkBoundsInclusive(int index) {
+      if (index < 0 || index > size) {
+       throw new IndexOutOfBoundsException();
+      }
+    }
+    
+    /**
+     * This method checks that a value is between 0 (inclusive) and size
+     * (exclusive). If it is not, an exception is thrown.
+     * Note that since this method is private, it will be inlined.
+     *
+     * @exception IndexOutOfBoundsException if the value is out of range.
+     */
+    private void checkBoundsExclusive(int index) {
+      if (index < 0 || index >= size) {
+       throw new IndexOutOfBoundsException();
+      }
+    }
+    
+    public int size() {
+      checkMod();
+      return size;
+    }
+    
+    public Iterator iterator() {
+      return listIterator();
+    }
+    
+    public ListIterator listIterator(final int index) {
+      
+      checkMod();
+      checkBoundsInclusive(index);
+      
+      return new ListIterator() {
+       ListIterator i = backingList.listIterator(index + offset);
+       int position = index;
+       
+       public boolean hasNext() {
+         checkMod();
+         return position < size;
+       }
+       
+       public boolean hasPrevious() {
+         checkMod();
+         return position > 0;
+       }
+       
+       public Object next() {
+         if (position < size) {
+           Object o = i.next();
+           position++;
+           return o;
+         } else {
+           throw new NoSuchElementException();
+         }
+       }
+       
+       public Object previous() {
+         if (position > 0) {
+           Object o = i.previous();
+           position--;
+           return o;
+         } else {
+           throw new NoSuchElementException();
+         }
+       }
+       
+       public int nextIndex() {
+         return offset + i.nextIndex();
+       }
+       
+       public int previousIndex() {
+         return offset + i.previousIndex();
+       }
+
+       public void remove() {
+         i.remove();
+         upMod();
+         size--;
+         position = nextIndex();
+       }
+       
+       public void set(Object o) {
+         i.set(o);
+       }
+       
+       public void add(Object o) {
+         i.add(o);
+         upMod();
+         size++;
+         position++;
+       }
+
+       // Here is the reason why the various modCount fields are mostly
+       // ignored in this wrapper listIterator.
+       // IF the backing listIterator is failfast, then the following holds:
+       //   Using any other method on this list will call a corresponding
+       //   method on the backing list *after* the backing listIterator
+       //   is created, which will in turn cause a ConcurrentModException
+       //   when this listIterator comes to use the backing one. So it is
+       //   implicitly failfast.
+       // If the backing listIterator is NOT failfast, then the whole of
+       //   this list isn't failfast, because the modCount field of the
+       //   backing list is not valid. It would still be *possible* to
+       //   make the iterator failfast wrt modifications of the sublist
+       //   only, but somewhat pointless when the list can be changed under
+       //   us.
+       // Either way, no explicit handling of modCount is needed.
+       // However upMod() must be called in add and remove, and size
+       // must also be updated in these two methods, since they do not go
+       // through the corresponding methods of the subList.
+
+      };
+    }
+
+    public Object set(int index, Object o) {
+      checkMod();
+      checkBoundsExclusive(index);
+      o = backingList.set(index + offset, o);
+      upMod();
+      return o;
+    }
+    
+    public Object get(int index) {
+      checkMod();
+      checkBoundsExclusive(index);
+      return backingList.get(index + offset);
+    }
+
+    public void add(int index, Object o) {
+      checkMod();
+      checkBoundsInclusive(index);
+      backingList.add(index + offset, o);
+      upMod();
+      size++;
+    }
+    
+    public Object remove(int index) {
+      checkMod();
+      checkBoundsExclusive(index);
+      Object o = backingList.remove(index + offset);
+      upMod();
+      size--;
+      return o;
+    }
+
+    public void removeRange(int fromIndex, int toIndex) {
+      checkMod();
+      checkBoundsExclusive(fromIndex);
+      checkBoundsInclusive(toIndex);
+      
+      // this call will catch the toIndex < fromIndex condition
+      backingList.removeRange(offset + fromIndex, offset + toIndex);
+      upMod();
+      size -= toIndex - fromIndex;
+    }
+    
+    public boolean addAll(int index, Collection c) {
+      checkMod();
+      checkBoundsInclusive(index);
+      int s = backingList.size();
+      boolean result = backingList.addAll(offset + index, c);
+      upMod();
+      size += backingList.size() - s;
+      return result;
+    }
+  }
+}
diff --git a/libjava/java/util/Arrays.java b/libjava/java/util/Arrays.java
new file mode 100644 (file)
index 0000000..fc51d38
--- /dev/null
@@ -0,0 +1,1757 @@
+/* Arrays.java -- Utility class with methods to operate on arrays
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+// TO DO:
+// ~ Fix the behaviour of sort and binarySearch as applied to float and double
+//   arrays containing NaN values. See the JDC, bug ID 4143272.
+
+package java.util;
+
+/**
+ * This class contains various static utility methods performing operations on
+ * arrays, and a method to provide a List "view" of an array to facilitate
+ * using arrays with Collection-based APIs.
+ */
+public class Arrays {
+
+  /**
+   * This class is non-instantiable.
+   */
+  private Arrays() {
+  }
+
+  private static Comparator defaultComparator = new Comparator() {
+    public int compare(Object o1, Object o2) {
+      return ((Comparable)o1).compareTo(o2);
+    }
+  };
+
+  /**
+   * Perform a binary search of a byte array for a key. The array must be
+   * sorted (as by the sort() method) - if it is not, the behaviour of this
+   * method is undefined, and may be an infinite loop. If the array contains
+   * the key more than once, any one of them may be found. Note: although the
+   * specification allows for an infinite loop if the array is unsorted, it
+   * will not happen in this implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   */
+  public static int binarySearch(byte[] a, byte key) {
+    int low = 0;
+    int hi = a.length - 1;
+    int mid = 0;
+    while (low <= hi) {
+      mid = (low + hi) >> 1;
+      final byte d = a[mid];
+      if (d == key) {
+        return mid;
+      } else if (d > key) {
+        hi = mid - 1;
+      } else {
+        low = ++mid; // This gets the insertion point right on the last loop
+      }
+    }
+    return -mid - 1;
+  }
+
+  /**
+   * Perform a binary search of a char array for a key. The array must be
+   * sorted (as by the sort() method) - if it is not, the behaviour of this
+   * method is undefined, and may be an infinite loop. If the array contains
+   * the key more than once, any one of them may be found. Note: although the
+   * specification allows for an infinite loop if the array is unsorted, it
+   * will not happen in this implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   */
+  public static int binarySearch(char[] a, char key) {
+    int low = 0;
+    int hi = a.length - 1;
+    int mid = 0;
+    while (low <= hi) {
+      mid = (low + hi) >> 1;
+      final char d = a[mid];
+      if (d == key) {
+        return mid;
+      } else if (d > key) {
+        hi = mid - 1;
+      } else {
+        low = ++mid; // This gets the insertion point right on the last loop
+      }
+    }
+    return -mid - 1;
+  }
+
+  /**
+   * Perform a binary search of a double array for a key. The array must be
+   * sorted (as by the sort() method) - if it is not, the behaviour of this
+   * method is undefined, and may be an infinite loop. If the array contains
+   * the key more than once, any one of them may be found. Note: although the
+   * specification allows for an infinite loop if the array is unsorted, it
+   * will not happen in this implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   */
+  public static int binarySearch(double[] a, double key) {
+    int low = 0;
+    int hi = a.length - 1;
+    int mid = 0;
+    while (low <= hi) {
+      mid = (low + hi) >> 1;
+      final double d = a[mid];
+      if (d == key) {
+        return mid;
+      } else if (d > key) {
+        hi = mid - 1;
+      } else {
+        low = ++mid; // This gets the insertion point right on the last loop
+      }
+    }
+    return -mid - 1;
+  }
+
+  /**
+   * Perform a binary search of a float array for a key. The array must be
+   * sorted (as by the sort() method) - if it is not, the behaviour of this
+   * method is undefined, and may be an infinite loop. If the array contains
+   * the key more than once, any one of them may be found. Note: although the
+   * specification allows for an infinite loop if the array is unsorted, it
+   * will not happen in this implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   */
+  public static int binarySearch(float[] a, float key) {
+    int low = 0;
+    int hi = a.length - 1;
+    int mid = 0;
+    while (low <= hi) {
+      mid = (low + hi) >> 1;
+      final float d = a[mid];
+      if (d == key) {
+        return mid;
+      } else if (d > key) {
+        hi = mid - 1;
+      } else {
+        low = ++mid; // This gets the insertion point right on the last loop
+      }
+    }
+    return -mid - 1;
+  }
+
+  /**
+   * Perform a binary search of an int array for a key. The array must be
+   * sorted (as by the sort() method) - if it is not, the behaviour of this
+   * method is undefined, and may be an infinite loop. If the array contains
+   * the key more than once, any one of them may be found. Note: although the
+   * specification allows for an infinite loop if the array is unsorted, it
+   * will not happen in this implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   */
+  public static int binarySearch(int[] a, int key) {
+    int low = 0;
+    int hi = a.length - 1;
+    int mid = 0;
+    while (low <= hi) {
+      mid = (low + hi) >> 1;
+      final int d = a[mid];
+      if (d == key) {
+        return mid;
+      } else if (d > key) {
+        hi = mid - 1;
+      } else {
+        low = ++mid; // This gets the insertion point right on the last loop
+      }
+    }
+    return -mid - 1;
+  }
+
+  /**
+   * Perform a binary search of a long array for a key. The array must be
+   * sorted (as by the sort() method) - if it is not, the behaviour of this
+   * method is undefined, and may be an infinite loop. If the array contains
+   * the key more than once, any one of them may be found. Note: although the
+   * specification allows for an infinite loop if the array is unsorted, it
+   * will not happen in this implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   */
+  public static int binarySearch(long[] a, long key) {
+    int low = 0;
+    int hi = a.length - 1;
+    int mid = 0;
+    while (low <= hi) {
+      mid = (low + hi) >> 1;
+      final long d = a[mid];
+      if (d == key) {
+        return mid;
+      } else if (d > key) {
+        hi = mid - 1;
+      } else {
+        low = ++mid; // This gets the insertion point right on the last loop
+      }
+    }
+    return -mid - 1;
+  }
+
+  /**
+   * Perform a binary search of a short array for a key. The array must be
+   * sorted (as by the sort() method) - if it is not, the behaviour of this
+   * method is undefined, and may be an infinite loop. If the array contains
+   * the key more than once, any one of them may be found. Note: although the
+   * specification allows for an infinite loop if the array is unsorted, it
+   * will not happen in this implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   */
+  public static int binarySearch(short[] a, short key) {
+    int low = 0;
+    int hi = a.length - 1;
+    int mid = 0;
+    while (low <= hi) {
+      mid = (low + hi) >> 1;
+      final short d = a[mid];
+      if (d == key) {
+        return mid;
+      } else if (d > key) {
+        hi = mid - 1;
+      } else {
+        low = ++mid; // This gets the insertion point right on the last loop
+      }
+    }
+    return -mid - 1;
+  }
+
+  /**
+   * This method does the work for the Object binary search methods. 
+   * @exception NullPointerException if the specified comparator is null.
+   * @exception ClassCastException if the objects are not comparable by c.
+   */
+  private static int objectSearch(Object[] a, Object key, final Comparator c) {
+    int low = 0;
+    int hi = a.length - 1;
+    int mid = 0;
+    while (low <= hi) {
+      mid = (low + hi) >> 1;
+      final int d = c.compare(key, a[mid]);
+      if (d == 0) {
+        return mid;
+      } else if (d < 0) {
+        hi = mid - 1;
+      } else {
+        low = ++mid; // This gets the insertion point right on the last loop
+      }
+    }
+    return -mid - 1;
+  }
+
+  /**
+   * Perform a binary search of an Object array for a key, using the natural
+   * ordering of the elements. The array must be sorted (as by the sort()
+   * method) - if it is not, the behaviour of this method is undefined, and may
+   * be an infinite loop. Further, the key must be comparable with every item
+   * in the array. If the array contains the key more than once, any one of
+   * them may be found. Note: although the specification allows for an infinite
+   * loop if the array is unsorted, it will not happen in this (JCL)
+   * implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   * @exception ClassCastException if key could not be compared with one of the
+   *   elements of a
+   * @exception NullPointerException if a null element has compareTo called
+   */
+  public static int binarySearch(Object[] a, Object key) {
+    return objectSearch(a, key, defaultComparator);
+  }
+
+  /**
+   * Perform a binary search of an Object array for a key, using a supplied
+   * Comparator. The array must be sorted (as by the sort() method with the
+   * same Comparator) - if it is not, the behaviour of this method is
+   * undefined, and may be an infinite loop. Further, the key must be
+   * comparable with every item in the array. If the array contains the key
+   * more than once, any one of them may be found. Note: although the
+   * specification allows for an infinite loop if the array is unsorted, it
+   * will not happen in this (JCL) implementation.
+   *
+   * @param a the array to search (must be sorted)
+   * @param key the value to search for
+   * @param c the comparator by which the array is sorted
+   * @returns the index at which the key was found, or -n-1 if it was not
+   *   found, where n is the index of the first value higher than key or
+   *   a.length if there is no such value.
+   * @exception ClassCastException if key could not be compared with one of the
+   *   elements of a
+   */
+  public static int binarySearch(Object[] a, Object key, Comparator c) {
+    return objectSearch(a, key, c);
+  }
+
+  /**
+   * Compare two byte arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+   */
+  public static boolean equals(byte[] a1, byte[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (a1[i] != a2[i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Compare two char arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+   */
+  public static boolean equals(char[] a1, char[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (a1[i] != a2[i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Compare two double arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+   */
+  public static boolean equals(double[] a1, double[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (a1[i] != a2[i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Compare two float arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+   */
+  public static boolean equals(float[] a1, float[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (a1[i] != a2[i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Compare two long arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+   */
+  public static boolean equals(long[] a1, long[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (a1[i] != a2[i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Compare two short arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+   */
+  public static boolean equals(short[] a1, short[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (a1[i] != a2[i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Compare two boolean arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+   */
+  public static boolean equals(boolean[] a1, boolean[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (a1[i] != a2[i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Compare two int arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a2 is of the same length
+   *   as a1, and for each 0 <= i < a1.length, a1[i] == a2[i]
+   */
+  public static boolean equals(int[] a1, int[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (a1[i] != a2[i]) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Compare two Object arrays for equality.
+   *
+   * @param a1 the first array to compare
+   * @param a2 the second array to compare
+   * @returns true if a1 and a2 are both null, or if a1 is of the same length
+   *   as a2, and for each 0 <= i < a.length, a1[i] == null ? a2[i] == null :
+   *   a1[i].equals(a2[i]).
+   */
+  public static boolean equals(Object[] a1, Object[] a2) {
+
+    // Quick test which saves comparing elements of the same array, and also
+    // catches the case that both are null.
+    if (a1 == a2) {
+      return true;
+    }
+    try {
+
+      // If they're the same length, test each element
+      if (a1.length == a2.length) {
+        for (int i = 0; i < a1.length; i++) {
+          if (!(a1[i] == null ? a2[i] == null : a1[i].equals(a2[i]))) {
+            return false;
+          }
+        }
+        return true;
+      }
+
+    // If a1 == null or a2 == null but not both then we will get a NullPointer
+    } catch (NullPointerException e) {
+    }
+
+    return false;
+  }
+
+  /**
+   * Fill an array with a boolean value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   */
+  public static void fill(boolean[] a, boolean val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with a boolean value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   */
+  public static void fill(boolean[] a, int fromIndex, int toIndex,
+                          boolean val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  /**
+   * Fill an array with a byte value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   */
+  public static void fill(byte[] a, byte val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with a byte value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   */
+  public static void fill(byte[] a, int fromIndex, int toIndex, byte val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  /**
+   * Fill an array with a char value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   */
+  public static void fill(char[] a, char val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with a char value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   */
+  public static void fill(char[] a, int fromIndex, int toIndex, char val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  /**
+   * Fill an array with a double value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   */
+  public static void fill(double[] a, double val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with a double value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   */
+  public static void fill(double[] a, int fromIndex, int toIndex, double val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  /**
+   * Fill an array with a float value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   */
+  public static void fill(float[] a, float val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with a float value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   */
+  public static void fill(float[] a, int fromIndex, int toIndex, float val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  /**
+   * Fill an array with an int value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   */
+  public static void fill(int[] a, int val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with an int value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   */
+  public static void fill(int[] a, int fromIndex, int toIndex, int val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  /**
+   * Fill an array with a long value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   */
+  public static void fill(long[] a, long val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with a long value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   */
+  public static void fill(long[] a, int fromIndex, int toIndex, long val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  /**
+   * Fill an array with a short value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   */
+  public static void fill(short[] a, short val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with a short value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   */
+  public static void fill(short[] a, int fromIndex, int toIndex, short val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  /**
+   * Fill an array with an Object value.
+   *
+   * @param a the array to fill
+   * @param val the value to fill it with
+   * @exception ClassCastException if val is not an instance of the element
+   *   type of a.
+   */
+  public static void fill(Object[] a, Object val) {
+    // This implementation is slightly inefficient timewise, but the extra
+    // effort over inlining it is O(1) and small, and I refuse to repeat code
+    // if it can be helped.
+    fill(a, 0, a.length, val);
+  }
+
+  /**
+   * Fill a range of an array with an Object value.
+   *
+   * @param a the array to fill
+   * @param fromIndex the index to fill from, inclusive
+   * @param toIndex the index to fill to, exclusive
+   * @param val the value to fill with
+   * @exception ClassCastException if val is not an instance of the element
+   *   type of a.
+   */
+  public static void fill(Object[] a, int fromIndex, int toIndex, Object val) {
+    for (int i = fromIndex; i < toIndex; i++) {
+      a[i] = val;
+    }
+  }
+
+  // Thanks to Paul Fisher <rao@gnu.org> for finding this quicksort algorithm
+  // as specified by Sun and porting it to Java.
+
+  /**
+   * Sort a byte array into ascending order. The sort algorithm is an optimised
+   * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
+   * "Engineering a Sort Function", Software-Practice and Experience, Vol.
+   * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
+   * performance on many arrays that would take quadratic time with a standard
+   * quicksort.
+   *
+   * @param a the array to sort
+   */
+  public static void sort(byte[] a) {
+    qsort(a, 0, a.length);
+  }
+
+  private static short cmp(byte i, byte j) {
+    return (short)(i-j);
+  }
+
+  private static int med3(int a, int b, int c, byte[] d) {
+    return cmp(d[a], d[b]) < 0 ? 
+      (cmp(d[b], d[c]) < 0 ? b : cmp(d[a], d[c]) < 0 ? c : a)
+    : (cmp(d[b], d[c]) > 0 ? b : cmp(d[a], d[c]) > 0 ? c : a);
+  }
+  
+  private static void swap(int i, int j, byte[] a) {
+    byte c = a[i];
+    a[i] = a[j];
+    a[j] = c;
+  }
+
+  private static void qsort(byte[] a, int start, int n) {
+    // use an insertion sort on small arrays
+    if (n < 7) {
+      for (int i = start + 1; i < start + n; i++)
+        for (int j = i; j > 0 && cmp(a[j-1], a[j]) > 0; j--)
+          swap(j, j-1, a);
+      return;
+    }
+
+    int pm = n/2;       // small arrays, middle element
+    if (n > 7) {
+      int pl = start;
+      int pn = start + n-1;
+
+      if (n > 40) {     // big arrays, pseudomedian of 9
+        int s = n/8;
+        pl = med3(pl, pl+s, pl+2*s, a);
+        pm = med3(pm-s, pm, pm+s, a);
+        pn = med3(pn-2*s, pn-s, pn, a);
+      }
+      pm = med3(pl, pm, pn, a); // mid-size, med of 3
+    }
+
+    int pa, pb, pc, pd, pv;
+    short r;
+
+    pv = start; swap(pv, pm, a);
+    pa = pb = start;
+    pc = pd = start + n-1;
+    
+    for (;;) {
+      while (pb <= pc && (r = cmp(a[pb], a[pv])) <= 0) {
+        if (r == 0) { swap(pa, pb, a); pa++; }
+        pb++;
+      }
+      while (pc >= pb && (r = cmp(a[pc], a[pv])) >= 0) {
+        if (r == 0) { swap(pc, pd, a); pd--; }
+        pc--;
+      }
+      if (pb > pc) break;
+      swap(pb, pc, a);
+      pb++;
+      pc--;
+    }
+    int pn = start + n;
+    int s;
+    s = Math.min(pa-start, pb-pa); vecswap(start, pb-s, s, a);
+    s = Math.min(pd-pc, pn-pd-1); vecswap(pb, pn-s, s, a);
+    if ((s = pb-pa) > 1) qsort(a, start, s);
+    if ((s = pd-pc) > 1) qsort(a, pn-s, s);
+  }
+
+  private static void vecswap(int i, int j, int n, byte[] a) {
+    for (; n > 0; i++, j++, n--)
+      swap(i, j, a);
+  }
+
+  /**
+   * Sort a char array into ascending order. The sort algorithm is an optimised
+   * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
+   * "Engineering a Sort Function", Software-Practice and Experience, Vol.
+   * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
+   * performance on many arrays that would take quadratic time with a standard
+   * quicksort.
+   *
+   * @param a the array to sort
+   */
+  public static void sort(char[] a) {
+    qsort(a, 0, a.length);
+  }
+
+  private static int cmp(char i, char j) {
+    return i-j;
+  }
+
+  private static int med3(int a, int b, int c, char[] d) {
+    return cmp(d[a], d[b]) < 0 ? 
+      (cmp(d[b], d[c]) < 0 ? b : cmp(d[a], d[c]) < 0 ? c : a)
+    : (cmp(d[b], d[c]) > 0 ? b : cmp(d[a], d[c]) > 0 ? c : a);
+  }
+  
+  private static void swap(int i, int j, char[] a) {
+    char c = a[i];
+    a[i] = a[j];
+    a[j] = c;
+  }
+
+  private static void qsort(char[] a, int start, int n) {
+    // use an insertion sort on small arrays
+    if (n < 7) {
+      for (int i = start + 1; i < start + n; i++)
+        for (int j = i; j > 0 && cmp(a[j-1], a[j]) > 0; j--)
+          swap(j, j-1, a);
+      return;
+    }
+
+    int pm = n/2;       // small arrays, middle element
+    if (n > 7) {
+      int pl = start;
+      int pn = start + n-1;
+
+      if (n > 40) {     // big arrays, pseudomedian of 9
+        int s = n/8;
+        pl = med3(pl, pl+s, pl+2*s, a);
+        pm = med3(pm-s, pm, pm+s, a);
+        pn = med3(pn-2*s, pn-s, pn, a);
+      }
+      pm = med3(pl, pm, pn, a); // mid-size, med of 3
+    }
+
+    int pa, pb, pc, pd, pv;
+    int r;
+
+    pv = start; swap(pv, pm, a);
+    pa = pb = start;
+    pc = pd = start + n-1;
+    
+    for (;;) {
+      while (pb <= pc && (r = cmp(a[pb], a[pv])) <= 0) {
+        if (r == 0) { swap(pa, pb, a); pa++; }
+        pb++;
+      }
+      while (pc >= pb && (r = cmp(a[pc], a[pv])) >= 0) {
+        if (r == 0) { swap(pc, pd, a); pd--; }
+        pc--;
+      }
+      if (pb > pc) break;
+      swap(pb, pc, a);
+      pb++;
+      pc--;
+    }
+    int pn = start + n;
+    int s;
+    s = Math.min(pa-start, pb-pa); vecswap(start, pb-s, s, a);
+    s = Math.min(pd-pc, pn-pd-1); vecswap(pb, pn-s, s, a);
+    if ((s = pb-pa) > 1) qsort(a, start, s);
+    if ((s = pd-pc) > 1) qsort(a, pn-s, s);
+  }
+
+  private static void vecswap(int i, int j, int n, char[] a) {
+    for (; n > 0; i++, j++, n--)
+      swap(i, j, a);
+  }
+
+  /**
+   * Sort a double array into ascending order. The sort algorithm is an
+   * optimised quicksort, as described in Jon L. Bentley and M. Douglas
+   * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,
+   * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
+   * performance on many arrays that would take quadratic time with a standard
+   * quicksort. Note that this implementation, like Sun's, has undefined
+   * behaviour if the array contains any NaN values.
+   *
+   * @param a the array to sort
+   */
+  public static void sort(double[] a) {
+    qsort(a, 0, a.length);
+  }
+
+  private static double cmp(double i, double j) {
+    return i-j;
+  }
+
+  private static int med3(int a, int b, int c, double[] d) {
+    return cmp(d[a], d[b]) < 0 ? 
+      (cmp(d[b], d[c]) < 0 ? b : cmp(d[a], d[c]) < 0 ? c : a)
+    : (cmp(d[b], d[c]) > 0 ? b : cmp(d[a], d[c]) > 0 ? c : a);
+  }
+  
+  private static void swap(int i, int j, double[] a) {
+    double c = a[i];
+    a[i] = a[j];
+    a[j] = c;
+  }
+
+  private static void qsort(double[] a, int start, int n) {
+    // use an insertion sort on small arrays
+    if (n < 7) {
+      for (int i = start + 1; i < start + n; i++)
+        for (int j = i; j > 0 && cmp(a[j-1], a[j]) > 0; j--)
+          swap(j, j-1, a);
+      return;
+    }
+
+    int pm = n/2;       // small arrays, middle element
+    if (n > 7) {
+      int pl = start;
+      int pn = start + n-1;
+
+      if (n > 40) {     // big arrays, pseudomedian of 9
+        int s = n/8;
+        pl = med3(pl, pl+s, pl+2*s, a);
+        pm = med3(pm-s, pm, pm+s, a);
+        pn = med3(pn-2*s, pn-s, pn, a);
+      }
+      pm = med3(pl, pm, pn, a); // mid-size, med of 3
+    }
+
+    int pa, pb, pc, pd, pv;
+    double r;
+
+    pv = start; swap(pv, pm, a);
+    pa = pb = start;
+    pc = pd = start + n-1;
+    
+    for (;;) {
+      while (pb <= pc && (r = cmp(a[pb], a[pv])) <= 0) {
+        if (r == 0) { swap(pa, pb, a); pa++; }
+        pb++;
+      }
+      while (pc >= pb && (r = cmp(a[pc], a[pv])) >= 0) {
+        if (r == 0) { swap(pc, pd, a); pd--; }
+        pc--;
+      }
+      if (pb > pc) break;
+      swap(pb, pc, a);
+      pb++;
+      pc--;
+    }
+    int pn = start + n;
+    int s;
+    s = Math.min(pa-start, pb-pa); vecswap(start, pb-s, s, a);
+    s = Math.min(pd-pc, pn-pd-1); vecswap(pb, pn-s, s, a);
+    if ((s = pb-pa) > 1) qsort(a, start, s);
+    if ((s = pd-pc) > 1) qsort(a, pn-s, s);
+  }
+
+  private static void vecswap(int i, int j, int n, double[] a) {
+    for (; n > 0; i++, j++, n--)
+      swap(i, j, a);
+  }
+
+  /**
+   * Sort a float array into ascending order. The sort algorithm is an
+   * optimised quicksort, as described in Jon L. Bentley and M. Douglas
+   * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,
+   * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
+   * performance on many arrays that would take quadratic time with a standard
+   * quicksort. Note that this implementation, like Sun's, has undefined
+   * behaviour if the array contains any NaN values.
+   *
+   * @param a the array to sort
+   */
+  public static void sort(float[] a) {
+    qsort(a, 0, a.length);
+  }
+
+  private static float cmp(float i, float j) {
+    return i-j;
+  }
+
+  private static int med3(int a, int b, int c, float[] d) {
+    return cmp(d[a], d[b]) < 0 ? 
+      (cmp(d[b], d[c]) < 0 ? b : cmp(d[a], d[c]) < 0 ? c : a)
+    : (cmp(d[b], d[c]) > 0 ? b : cmp(d[a], d[c]) > 0 ? c : a);
+  }
+
+  private static void swap(int i, int j, float[] a) {
+    float c = a[i];
+    a[i] = a[j];
+    a[j] = c;
+  }
+
+  private static void qsort(float[] a, int start, int n) {
+    // use an insertion sort on small arrays
+    if (n < 7) {
+      for (int i = start + 1; i < start + n; i++)
+        for (int j = i; j > 0 && cmp(a[j-1], a[j]) > 0; j--)
+          swap(j, j-1, a);
+      return;
+    }
+
+    int pm = n/2;       // small arrays, middle element
+    if (n > 7) {
+      int pl = start;
+      int pn = start + n-1;
+
+      if (n > 40) {     // big arrays, pseudomedian of 9
+        int s = n/8;
+        pl = med3(pl, pl+s, pl+2*s, a);
+        pm = med3(pm-s, pm, pm+s, a);
+        pn = med3(pn-2*s, pn-s, pn, a);
+      }
+      pm = med3(pl, pm, pn, a); // mid-size, med of 3
+    }
+
+    int pa, pb, pc, pd, pv;
+    float r;
+
+    pv = start; swap(pv, pm, a);
+    pa = pb = start;
+    pc = pd = start + n-1;
+    
+    for (;;) {
+      while (pb <= pc && (r = cmp(a[pb], a[pv])) <= 0) {
+        if (r == 0) { swap(pa, pb, a); pa++; }
+        pb++;
+      }
+      while (pc >= pb && (r = cmp(a[pc], a[pv])) >= 0) {
+        if (r == 0) { swap(pc, pd, a); pd--; }
+        pc--;
+      }
+      if (pb > pc) break;
+      swap(pb, pc, a);
+      pb++;
+      pc--;
+    }
+    int pn = start + n;
+    int s;
+    s = Math.min(pa-start, pb-pa); vecswap(start, pb-s, s, a);
+    s = Math.min(pd-pc, pn-pd-1); vecswap(pb, pn-s, s, a);
+    if ((s = pb-pa) > 1) qsort(a, start, s);
+    if ((s = pd-pc) > 1) qsort(a, pn-s, s);
+  }
+
+  private static void vecswap(int i, int j, int n, float[] a) {
+    for (; n > 0; i++, j++, n--)
+      swap(i, j, a);
+  }
+
+  /**
+   * Sort an int array into ascending order. The sort algorithm is an optimised
+   * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
+   * "Engineering a Sort Function", Software-Practice and Experience, Vol.
+   * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
+   * performance on many arrays that would take quadratic time with a standard
+   * quicksort.
+   *
+   * @param a the array to sort
+   */
+  public static void sort(int[] a) {
+    qsort(a, 0, a.length);
+  }
+
+  private static long cmp(int i, int j) {
+    return (long)i-(long)j;
+  }
+
+  private static int med3(int a, int b, int c, int[] d) {
+    return cmp(d[a], d[b]) < 0 ? 
+      (cmp(d[b], d[c]) < 0 ? b : cmp(d[a], d[c]) < 0 ? c : a)
+    : (cmp(d[b], d[c]) > 0 ? b : cmp(d[a], d[c]) > 0 ? c : a);
+  }
+  
+  private static void swap(int i, int j, int[] a) {
+    int c = a[i];
+    a[i] = a[j];
+    a[j] = c;
+  }
+
+  private static void qsort(int[] a, int start, int n) {
+    // use an insertion sort on small arrays
+    if (n < 7) {
+      for (int i = start + 1; i < start + n; i++)
+        for (int j = i; j > 0 && cmp(a[j-1], a[j]) > 0; j--)
+          swap(j, j-1, a);
+      return;
+    }
+
+    int pm = n/2;       // small arrays, middle element
+    if (n > 7) {
+      int pl = start;
+      int pn = start + n-1;
+
+      if (n > 40) {     // big arrays, pseudomedian of 9
+        int s = n/8;
+        pl = med3(pl, pl+s, pl+2*s, a);
+        pm = med3(pm-s, pm, pm+s, a);
+        pn = med3(pn-2*s, pn-s, pn, a);
+      }
+      pm = med3(pl, pm, pn, a); // mid-size, med of 3
+    }
+
+    int pa, pb, pc, pd, pv;
+    long r;
+
+    pv = start; swap(pv, pm, a);
+    pa = pb = start;
+    pc = pd = start + n-1;
+    
+    for (;;) {
+      while (pb <= pc && (r = cmp(a[pb], a[pv])) <= 0) {
+        if (r == 0) { swap(pa, pb, a); pa++; }
+        pb++;
+      }
+      while (pc >= pb && (r = cmp(a[pc], a[pv])) >= 0) {
+        if (r == 0) { swap(pc, pd, a); pd--; }
+        pc--;
+      }
+      if (pb > pc) break;
+      swap(pb, pc, a);
+      pb++;
+      pc--;
+    }
+    int pn = start + n;
+    int s;
+    s = Math.min(pa-start, pb-pa); vecswap(start, pb-s, s, a);
+    s = Math.min(pd-pc, pn-pd-1); vecswap(pb, pn-s, s, a);
+    if ((s = pb-pa) > 1) qsort(a, start, s);
+    if ((s = pd-pc) > 1) qsort(a, pn-s, s);
+  }
+
+  private static void vecswap(int i, int j, int n, int[] a) {
+    for (; n > 0; i++, j++, n--)
+      swap(i, j, a);
+  }
+
+  /**
+   * Sort a long array into ascending order. The sort algorithm is an optimised
+   * quicksort, as described in Jon L. Bentley and M. Douglas McIlroy's
+   * "Engineering a Sort Function", Software-Practice and Experience, Vol.
+   * 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
+   * performance on many arrays that would take quadratic time with a standard
+   * quicksort.
+   *
+   * @param a the array to sort
+   */
+  public static void sort(long[] a) {
+    qsort(a, 0, a.length);
+  }
+
+  // The "cmp" method has been removed from here and replaced with direct
+  // compares in situ, to avoid problems with overflow if the difference
+  // between two numbers is bigger than a long will hold.
+  // One particular change as a result is the use of r1 and r2 in qsort
+
+  private static int med3(int a, int b, int c, long[] d) {
+    return d[a] < d[b] ? 
+      (d[b] < d[c] ? b : d[a] < d[c] ? c : a)
+    : (d[b] > d[c] ? b : d[a] > d[c] ? c : a);
+  }
+  
+  private static void swap(int i, int j, long[] a) {
+    long c = a[i];
+    a[i] = a[j];
+    a[j] = c;
+  }
+
+  private static void qsort(long[] a, int start, int n) {
+    // use an insertion sort on small arrays
+    if (n < 7) {
+      for (int i = start + 1; i < start + n; i++)
+        for (int j = i; j > 0 && a[j-1] > a[j]; j--)
+          swap(j, j-1, a);
+      return;
+    }
+
+    int pm = n/2;       // small arrays, middle element
+    if (n > 7) {
+      int pl = start;
+      int pn = start + n-1;
+
+      if (n > 40) {     // big arrays, pseudomedian of 9
+        int s = n/8;
+        pl = med3(pl, pl+s, pl+2*s, a);
+        pm = med3(pm-s, pm, pm+s, a);
+        pn = med3(pn-2*s, pn-s, pn, a);
+      }
+      pm = med3(pl, pm, pn, a); // mid-size, med of 3
+    }
+
+    int pa, pb, pc, pd, pv;
+    long r1, r2;
+
+    pv = start; swap(pv, pm, a);
+    pa = pb = start;
+    pc = pd = start + n-1;
+    
+    for (;;) {
+      while (pb <= pc && (r1 = a[pb]) <= (r2 = a[pv])) {
+        if (r1 == r2) { swap(pa, pb, a); pa++; }
+        pb++;
+      }
+      while (pc >= pb && (r1 = a[pc]) >= (r2 = a[pv])) {
+        if (r1 == r2) { swap(pc, pd, a); pd--; }
+        pc--;
+      }
+      if (pb > pc) break;
+      swap(pb, pc, a);
+      pb++;
+      pc--;
+    }
+    int pn = start + n;
+    int s;
+    s = Math.min(pa-start, pb-pa); vecswap(start, pb-s, s, a);
+    s = Math.min(pd-pc, pn-pd-1); vecswap(pb, pn-s, s, a);
+    if ((s = pb-pa) > 1) qsort(a, start, s);
+    if ((s = pd-pc) > 1) qsort(a, pn-s, s);
+  }
+
+  private static void vecswap(int i, int j, int n, long[] a) {
+    for (; n > 0; i++, j++, n--)
+      swap(i, j, a);
+  }
+
+  /**
+   * Sort a short array into ascending order. The sort algorithm is an
+   * optimised quicksort, as described in Jon L. Bentley and M. Douglas
+   * McIlroy's "Engineering a Sort Function", Software-Practice and Experience,
+   * Vol. 23(11) P. 1249-1265 (November 1993). This algorithm gives nlog(n)
+   * performance on many arrays that would take quadratic time with a standard
+   * quicksort.
+   *
+   * @param a the array to sort
+   */
+  public static void sort(short[] a) {
+    qsort(a, 0, a.length);
+  }
+
+  private static int cmp(short i, short j) {
+    return i-j;
+  }
+
+  private static int med3(int a, int b, int c, short[] d) {
+    return cmp(d[a], d[b]) < 0 ? 
+      (cmp(d[b], d[c]) < 0 ? b : cmp(d[a], d[c]) < 0 ? c : a)
+    : (cmp(d[b], d[c]) > 0 ? b : cmp(d[a], d[c]) > 0 ? c : a);
+  }
+  
+  private static void swap(int i, int j, short[] a) {
+    short c = a[i];
+    a[i] = a[j];
+    a[j] = c;
+  }
+
+  private static void qsort(short[] a, int start, int n) {
+    // use an insertion sort on small arrays
+    if (n < 7) {
+      for (int i = start + 1; i < start + n; i++)
+        for (int j = i; j > 0 && cmp(a[j-1], a[j]) > 0; j--)
+          swap(j, j-1, a);
+      return;
+    }
+
+    int pm = n/2;       // small arrays, middle element
+    if (n > 7) {
+      int pl = start;
+      int pn = start + n-1;
+
+      if (n > 40) {     // big arrays, pseudomedian of 9
+        int s = n/8;
+        pl = med3(pl, pl+s, pl+2*s, a);
+        pm = med3(pm-s, pm, pm+s, a);
+        pn = med3(pn-2*s, pn-s, pn, a);
+      }
+      pm = med3(pl, pm, pn, a); // mid-size, med of 3
+    }
+
+    int pa, pb, pc, pd, pv;
+    int r;
+
+    pv = start; swap(pv, pm, a);
+    pa = pb = start;
+    pc = pd = start + n-1;
+    
+    for (;;) {
+      while (pb <= pc && (r = cmp(a[pb], a[pv])) <= 0) {
+        if (r == 0) { swap(pa, pb, a); pa++; }
+        pb++;
+      }
+      while (pc >= pb && (r = cmp(a[pc], a[pv])) >= 0) {
+        if (r == 0) { swap(pc, pd, a); pd--; }
+        pc--;
+      }
+      if (pb > pc) break;
+      swap(pb, pc, a);
+      pb++;
+      pc--;
+    }
+    int pn = start + n;
+    int s;
+    s = Math.min(pa-start, pb-pa); vecswap(start, pb-s, s, a);
+    s = Math.min(pd-pc, pn-pd-1); vecswap(pb, pn-s, s, a);
+    if ((s = pb-pa) > 1) qsort(a, start, s);
+    if ((s = pd-pc) > 1) qsort(a, pn-s, s);
+  }
+
+  private static void vecswap(int i, int j, int n, short[] a) {
+    for (; n > 0; i++, j++, n--)
+      swap(i, j, a);
+  }
+
+  /**
+   * The bulk of the work for the object sort routines.  In general,
+   * the code attempts to be simple rather than fast, the idea being
+   * that a good optimising JIT will be able to optimise it better
+   * than I can, and if I try it will make it more confusing for the
+   * JIT.  
+   */
+  private static void mergeSort(Object[] a, int from, int to, Comparator c)
+  {
+    // First presort the array in chunks of length 6 with insertion sort. 
+    // mergesort would give too much overhead for this length.
+    for (int chunk = from; chunk < to; chunk += 6)
+      {
+       int end = Math.min(chunk+6, to);
+       for (int i = chunk + 1; i < end; i++)
+         {
+           if (c.compare(a[i-1], a[i]) > 0)
+             {
+               // not already sorted
+               int j=i;
+               Object elem = a[j];
+               do 
+                 {
+                   a[j] = a[j-1];
+                   j--;
+                 } 
+               while (j>chunk && c.compare(a[j-1], elem) > 0);
+               a[j] = elem;
+             }
+         }
+      }
+    
+    int len = to - from;
+    // If length is smaller or equal 6 we are done.
+    if (len <= 6)
+      return;
+
+    Object[] src = a;
+    Object[] dest = new Object[len];
+    Object[] t = null; // t is used for swapping src and dest
+
+    // The difference of the fromIndex of the src and dest array.
+    int srcDestDiff = -from;
+
+    // The merges are done in this loop
+    for (int size = 6; size < len; size <<= 1) 
+      {
+       for (int start = from; start < to; start += size << 1)
+         {
+           // mid ist the start of the second sublist;
+           // end the start of the next sublist (or end of array).
+           int mid = start + size;
+           int end = Math.min(to, mid + size);
+           
+           // The second list is empty or the elements are already in
+           // order - no need to merge
+           if (mid >= end || c.compare(src[mid - 1], src[mid]) <= 0) {
+             System.arraycopy(src, start, 
+                              dest, start + srcDestDiff, end - start);
+             
+             // The two halves just need swapping - no need to merge
+           } else if (c.compare(src[start], src[end - 1]) > 0) {
+             System.arraycopy(src, start, 
+                              dest, end - size + srcDestDiff, size);
+             System.arraycopy(src, mid, 
+                              dest, start + srcDestDiff, end - mid);
+             
+           } else {
+             // Declare a lot of variables to save repeating
+             // calculations.  Hopefully a decent JIT will put these
+             // in registers and make this fast
+             int p1 = start;
+             int p2 = mid;
+             int i = start + srcDestDiff;
+             
+             // The main merge loop; terminates as soon as either
+             // half is ended
+             while (p1 < mid && p2 < end)
+               {
+                 dest[i++] = 
+                   src[c.compare(src[p1], src[p2]) <= 0 ? p1++ : p2++];
+               }
+             
+             // Finish up by copying the remainder of whichever half
+             // wasn't finished.
+             if (p1 < mid)
+               System.arraycopy(src, p1, dest, i, mid - p1);
+             else
+               System.arraycopy(src, p2, dest, i, end - p2);
+           } 
+         }
+       // swap src and dest ready for the next merge
+       t = src; src = dest; dest = t; 
+       from += srcDestDiff;
+       to   += srcDestDiff;
+       srcDestDiff = -srcDestDiff;
+      }
+
+    // make sure the result ends up back in the right place.  Note
+    // that src and dest may have been swapped above, so src 
+    // contains the sorted array.
+    if (src != a)
+      {
+       // Note that from == 0.
+       System.arraycopy(src, 0, a, srcDestDiff, to);
+      }
+  }
+
+  /**
+   * Sort an array of Objects according to their natural ordering. The sort is
+   * guaranteed to be stable, that is, equal elements will not be reordered.
+   * The sort algorithm is a mergesort with the merge omitted if the last
+   * element of one half comes before the first element of the other half. This
+   * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a
+   * copy of the array.
+   *
+   * @param a the array to be sorted
+   * @exception ClassCastException if any two elements are not mutually
+   *   comparable
+   * @exception NullPointerException if an element is null (since
+   *   null.compareTo cannot work)
+   */
+  public static void sort(Object[] a) {
+    mergeSort(a, 0, a.length, defaultComparator);
+  }
+
+  /**
+   * Sort an array of Objects according to a Comparator. The sort is
+   * guaranteed to be stable, that is, equal elements will not be reordered.
+   * The sort algorithm is a mergesort with the merge omitted if the last
+   * element of one half comes before the first element of the other half. This
+   * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a
+   * copy of the array.
+   *
+   * @param a the array to be sorted
+   * @param c a Comparator to use in sorting the array
+   * @exception ClassCastException if any two elements are not mutually
+   *   comparable by the Comparator provided
+   */
+  public static void sort(Object[] a, Comparator c) {
+    mergeSort(a, 0, a.length, c);
+  }
+
+  /**
+   * Sort an array of Objects according to their natural ordering. The sort is
+   * guaranteed to be stable, that is, equal elements will not be reordered.
+   * The sort algorithm is a mergesort with the merge omitted if the last
+   * element of one half comes before the first element of the other half. This
+   * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a
+   * copy of the array.
+   *
+   * @param a the array to be sorted
+   * @param fromIndex the index of the first element to be sorted.
+   * @param toIndex the index of the last element to be sorted plus one.
+   * @exception ClassCastException if any two elements are not mutually
+   *   comparable by the Comparator provided
+   * @exception ArrayIndexOutOfBoundsException, if fromIndex and toIndex
+   *   are not in range.
+   * @exception IllegalArgumentException if fromIndex > toIndex
+   */
+  public static void sort(Object[] a, int fromIndex, 
+                         int toIndex) {
+    if (fromIndex > toIndex)
+      throw new IllegalArgumentException("fromIndex "+fromIndex
+                                        +" > toIndex "+toIndex);
+    mergeSort(a, fromIndex, toIndex, defaultComparator);
+  }
+
+  /**
+   * Sort an array of Objects according to a Comparator. The sort is
+   * guaranteed to be stable, that is, equal elements will not be reordered.
+   * The sort algorithm is a mergesort with the merge omitted if the last
+   * element of one half comes before the first element of the other half. This
+   * algorithm gives guaranteed O(nlog(n)) time, at the expense of making a
+   * copy of the array.
+   *
+   * @param a the array to be sorted
+   * @param fromIndex the index of the first element to be sorted.
+   * @param toIndex the index of the last element to be sorted plus one.
+   * @param c a Comparator to use in sorting the array
+   * @exception ClassCastException if any two elements are not mutually
+   *   comparable by the Comparator provided
+   * @exception ArrayIndexOutOfBoundsException, if fromIndex and toIndex
+   *   are not in range.
+   * @exception IllegalArgumentException if fromIndex > toIndex
+   */
+  public static void sort(Object[] a, int fromIndex, 
+                         int toIndex, Comparator c) {
+    if (fromIndex > toIndex)
+      throw new IllegalArgumentException("fromIndex "+fromIndex
+                                        +" > toIndex "+toIndex);
+    mergeSort(a, fromIndex, toIndex, c);
+  }
+
+  /**
+   * Returns a list "view" of the specified array. This method is intended to
+   * make it easy to use the Collections API with existing array-based APIs and
+   * programs.
+   *
+   * @param a the array to return a view of
+   * @returns a fixed-size list, changes to which "write through" to the array
+   */
+  public static List asList(final Object[] a) {
+
+    if (a == null) {
+      throw new NullPointerException();
+    }
+
+    return new ListImpl( a );
+  }
+
+
+  /**
+   * Inner class used by asList(Object[]) to provide a list interface
+   * to an array. The methods are all simple enough to be self documenting.
+   * Note: When Sun fully specify serialized forms, this class will have to
+   * be renamed.
+   */
+  private static class ListImpl extends AbstractList {
+
+    ListImpl(Object[] a) {
+      this.a = a;
+    }
+
+    public Object get(int index) {
+      return a[index];
+    }
+
+    public int size() {
+      return a.length;
+    }
+
+    public Object set(int index, Object element) {
+      Object old = a[index];
+      a[index] = element;
+      return old;
+    }
+
+    private Object[] a;
+  }
+    
+}
index e9c2548..8a1aa87 100644 (file)
@@ -4,7 +4,7 @@
 # to link with libgcj.
 #
 %rename lib liborig
-*lib: -lgcj -lm @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(liborig)
+*lib: -lgcjawt -lgcj -lm @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(liborig)
 
 *jc1:  @DIVIDESPEC@ @EXCEPTIONSPEC@ -fasynchronous-exceptions
 
index b64463e..d4de792 100644 (file)
@@ -74,19 +74,15 @@ PACKAGE = @PACKAGE@
 RANLIB = @RANLIB@
 VERSION = @VERSION@
 
-AUTOMAKE_OPTIONS = no-dependencies foreign
+AUTOMAKE_OPTIONS = no-dependencies foreign no-installinfo
 
 INCLUDES = $(GCINCS)
 
-@INSTALL_LTDL_TRUE@include_HEADERS = \
-@INSTALL_LTDL_TRUE@ltdl.h
-@INSTALL_LTDL_TRUE@lib_LTLIBRARIES = \
-@INSTALL_LTDL_TRUE@libltdl.la
-@INSTALL_LTDL_FALSE@noinst_HEADERS = \
-@INSTALL_LTDL_FALSE@ltdl.h
+@INSTALL_LTDL_TRUE@include_HEADERS = @INSTALL_LTDL_TRUE@ltdl.h
+@INSTALL_LTDL_TRUE@lib_LTLIBRARIES = @INSTALL_LTDL_TRUE@libltdl.la
+@INSTALL_LTDL_FALSE@noinst_HEADERS = @INSTALL_LTDL_FALSE@ltdl.h
 
-@CONVENIENCE_LTDL_TRUE@noinst_LTLIBRARIES = \
-@CONVENIENCE_LTDL_TRUE@libltdlc.la
+@CONVENIENCE_LTDL_TRUE@noinst_LTLIBRARIES = @CONVENIENCE_LTDL_TRUE@libltdlc.la
 
 libltdl_la_SOURCES = ltdl.c
 libltdl_la_LDFLAGS = -version-info 1:2:1
@@ -124,7 +120,7 @@ configure.in
 
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
-TAR = tar
+TAR = gtar
 GZIP_ENV = --best
 SOURCES = $(libltdl_la_SOURCES) $(libltdlc_la_SOURCES)
 OBJECTS = $(libltdl_la_OBJECTS) $(libltdlc_la_OBJECTS)
@@ -338,7 +334,7 @@ distdir: $(DISTFILES)
        @for file in $(DISTFILES); do \
          d=$(srcdir); \
          if test -d $$d/$$file; then \
-           cp -pr $$/$$file $(distdir)/$$file; \
+           cp -pr $$d/$$file $(distdir)/$$file; \
          else \
            test -f $(distdir)/$$file \
            || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@@ -353,6 +349,8 @@ check-am: all-am
 check: check-am
 installcheck-am:
 installcheck: installcheck-am
+install-info-am: 
+install-info: install-info-am
 all-recursive-am: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-recursive
 
@@ -429,11 +427,12 @@ maintainer-clean-compile mostlyclean-libtool distclean-libtool \
 clean-libtool maintainer-clean-libtool uninstall-includeHEADERS \
 install-includeHEADERS tags mostlyclean-tags distclean-tags clean-tags \
 maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \
-installcheck-am installcheck all-recursive-am install-exec-am \
-install-exec install-data-am install-data install-am install \
-uninstall-am uninstall all-redirect all-am all installdirs \
-mostlyclean-generic distclean-generic clean-generic \
-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+installcheck-am installcheck install-info-am install-info \
+all-recursive-am install-exec-am install-exec install-data-am \
+install-data install-am install uninstall-am uninstall all-redirect \
+all-am all installdirs mostlyclean-generic distclean-generic \
+clean-generic maintainer-clean-generic clean mostlyclean distclean \
+maintainer-clean
 
 
 ltdl.lo: ltdl.h config.h
index 28905d1..1a4e48b 100644 (file)
@@ -4,13 +4,13 @@ JDK1.1
 !java.applet
 !java.awt
 !java.beans
-# We don't support object serialization yet.
-!java.io.ObjectStreamClass
-!java.io.ObjectInputOutput
 java.lang.Character.classify12
 java.lang.String.hash
-# We support 1.2 for this test.
+# We support 1.2 for these 3 tests.
 java.lang.reflect.Modifier.toString12
+!java.io.ObjectInputOutput.InputTest
+!java.io.ObjectInputOutput.OutputTest
+!java.io.ObjectStreamClass.Test
 java.math
 !java.rmi
 java.security
index 8f0cdf4..ab028af 100644 (file)
@@ -64,10 +64,14 @@ _Jv_name_finder::_Jv_name_finder (char *executable)
   char *argv[6];
   {
     int arg = 0;
+#ifdef __ia64__
+    argv[arg++] = "addr2name.awk";
+#else
     argv[arg++] = "addr2line";
     argv[arg++] = "-C";
     argv[arg++] = "-f";
     argv[arg++] = "-e";
+#endif
     argv[arg++] = executable;
     argv[arg] = NULL;
   }
index c9cb92e..4279b09 100644 (file)
@@ -95,13 +95,26 @@ void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event);
 #endif
 \f
 
+extern "C" void _Jv_ThrowSignal (void *) __attribute ((noreturn));
+
+// Just like _Jv_Throw, but fill in the stack trace first.  Although
+// this is declared extern in order that its name not be mangled, it
+// is not intended to be used outside this file.
+void 
+_Jv_ThrowSignal (void *e)
+{
+  java::lang::Throwable *throwable = (java::lang::Throwable *)e;
+  throwable->fillInStackTrace ();
+  _Jv_Throw (throwable);
+}
 #ifdef HANDLE_SEGV
 static java::lang::NullPointerException *nullp;
+
 SIGNAL_HANDLER (catch_segv)
 {
-  MAKE_THROW_FRAME;
-  nullp->fillInStackTrace ();
-  _Jv_Throw (nullp);
+  MAKE_THROW_FRAME (nullp);
+  _Jv_ThrowSignal (nullp);
 }
 #endif
 
@@ -113,10 +126,9 @@ SIGNAL_HANDLER (catch_fpe)
 #ifdef HANDLE_DIVIDE_OVERFLOW
   HANDLE_DIVIDE_OVERFLOW;
 #else
-  MAKE_THROW_FRAME;
+  MAKE_THROW_FRAME (arithexception);
 #endif
-  arithexception->fillInStackTrace ();
-  _Jv_Throw (arithexception);
+  _Jv_ThrowSignal (arithexception);
 }
 #endif
 
@@ -125,8 +137,8 @@ SIGNAL_HANDLER (catch_fpe)
 jboolean
 _Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b)
 {
-  register int len;
-  register _Jv_ushort *aptr, *bptr;
+  int len;
+  _Jv_ushort *aptr, *bptr;
   if (a == b)
     return true;
   if (a->hash != b->hash)
@@ -155,8 +167,8 @@ _Jv_equal (Utf8Const* a, jstring str, jint hash)
   jint len = str->length();
   jint i = 0;
   jchar *sptr = _Jv_GetStringChars (str);
-  register unsigned char* ptr = (unsigned char*) a->data;
-  register unsigned char* limit = ptr + a->length;
+  unsigned char* ptr = (unsigned char*) a->data;
+  unsigned char* limit = ptr + a->length;
   for (;; i++, sptr++)
     {
       int ch = UTF8_GET (ptr, limit);
@@ -175,8 +187,8 @@ _Jv_equaln (Utf8Const *a, jstring str, jint n)
   jint len = str->length();
   jint i = 0;
   jchar *sptr = _Jv_GetStringChars (str);
-  register unsigned char* ptr = (unsigned char*) a->data;
-  register unsigned char* limit = ptr + a->length;
+  unsigned char* ptr = (unsigned char*) a->data;
+  unsigned char* limit = ptr + a->length;
   for (; n-- > 0; i++, sptr++)
     {
       int ch = UTF8_GET (ptr, limit);
@@ -192,8 +204,8 @@ _Jv_equaln (Utf8Const *a, jstring str, jint n)
 int
 _Jv_strLengthUtf8(char* str, int len)
 {
-  register unsigned char* ptr;
-  register unsigned char* limit;
+  unsigned char* ptr;
+  unsigned char* limit;
   int str_length;
 
   ptr = (unsigned char*) str;
@@ -213,8 +225,8 @@ _Jv_strLengthUtf8(char* str, int len)
 static jint
 hashUtf8String (char* str, int len)
 {
-  register unsigned char* ptr = (unsigned char*) str;
-  register unsigned char* limit = ptr + len;
+  unsigned char* ptr = (unsigned char*) str;
+  unsigned char* limit = ptr + len;
   jint hash = 0;
 
   for (; ptr < limit;)
@@ -976,7 +988,7 @@ jint
 _Jv_divI (jint dividend, jint divisor)
 {
   if (__builtin_expect (divisor == 0, false))
-    _Jv_Throw (arithexception);
+    _Jv_ThrowSignal (arithexception);
   
   if (dividend == (jint) 0x80000000L && divisor == -1)
     return dividend;
@@ -988,7 +1000,7 @@ jint
 _Jv_remI (jint dividend, jint divisor)
 {
   if (__builtin_expect (divisor == 0, false))
-    _Jv_Throw (arithexception);
+    _Jv_ThrowSignal (arithexception);
   
   if (dividend == (jint) 0x80000000L && divisor == -1)
     return 0;
@@ -1000,7 +1012,7 @@ jlong
 _Jv_divJ (jlong dividend, jlong divisor)
 {
   if (__builtin_expect (divisor == 0, false))
-    _Jv_Throw (arithexception);
+    _Jv_ThrowSignal (arithexception);
   
   if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
     return dividend;
@@ -1012,7 +1024,7 @@ jlong
 _Jv_remJ (jlong dividend, jlong divisor)
 {
   if (__builtin_expect (divisor == 0, false))
-    _Jv_Throw (arithexception);
+    _Jv_ThrowSignal (arithexception);
   
   if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
     return 0;
index 05f9133..e9f17c7 100644 (file)
@@ -10,7 +10,7 @@
 # details.
 
 # Usage: cd <top-srcdir> ; perl classes.pl.
-# Can also be run from the `gcj' directory; this lets us
+# Can also be run from the `include' directory; this lets us
 # more easily insert the output into javaprims.h (which is where it goes).
 
 use DirHandle;
@@ -100,5 +100,5 @@ sub scan
        &scan ("$dir/$_", $indent + 2);
     }
 
-    print $spaces, "}\n";
+    print $spaces, "};\n";
 }
diff --git a/libjava/sysdep/ia64-frame.h b/libjava/sysdep/ia64-frame.h
new file mode 100644 (file)
index 0000000..7f07988
--- /dev/null
@@ -0,0 +1,282 @@
+/* Header file for unwinding stack frames for exception handling.  */
+/* Compile this one with gcc.  */
+/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+   Contributed by Jason Merrill <jason@cygnus.com>.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+/* Number of hardware registers known to the compiler.  
+   We have 128 general registers, 128 floating point registers, 64 predicate
+   registers, 8 branch registers, and one frame pointer register.  */
+
+/* ??? Should add ar.lc, ar.ec and probably also ar.pfs.  */
+
+#define FIRST_PSEUDO_REGISTER 330
+
+#ifndef DWARF_FRAME_REGISTERS
+#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
+#endif
+
+typedef struct frame_state
+{
+  void *cfa;
+  void *eh_ptr;
+  long cfa_offset;
+  long args_size;
+  long reg_or_offset[DWARF_FRAME_REGISTERS+1];
+  unsigned short cfa_reg;
+  unsigned short retaddr_column;
+  char saved[DWARF_FRAME_REGISTERS+1];
+} frame_state;
+
+/* Values for 'saved' above.  */
+#define REG_UNSAVED 0
+#define REG_SAVED_OFFSET 1
+#define REG_SAVED_REG 2
+
+/* The representation for an "object" to be searched for frame unwind info.
+   For targets with named sections, one object is an executable or shared
+   library; for other targets, one object is one translation unit.
+
+   A copy of this structure declaration is printed by collect2.c;
+   keep the copies synchronized!  */
+
+struct object {
+#ifdef IA64_UNWIND_INFO
+  void *pc_base;        /* This field will be set by __do_frame_setup. */
+#endif
+  void *pc_begin;
+  void *pc_end;
+  struct dwarf_fde *fde_begin;
+  struct dwarf_fde **fde_array;
+  size_t count;
+  struct object *next;
+};
+
+/* Called from __throw to find the registers to restore for a given
+   PC_TARGET.  The caller should allocate a local variable of `struct
+   frame_state' (declared in frame.h) and pass its address to STATE_IN.
+   Returns NULL on failure, otherwise returns STATE_IN.  */
+
+extern struct frame_state *__frame_state_for (void *, struct frame_state *);
+
+#ifdef IA64_UNWIND_INFO
+
+/* This is the information required for unwind records in an ia64
+   object file. This is required by GAS and the compiler runtime. */
+
+/* These are the starting point masks for the various types of
+   unwind records. To create a record of type R3 for instance, one
+   starts by using the value UNW_R3 and or-ing in any other required values. 
+   These values are also unique (in context), so they can be used to identify 
+   the various record types as well. UNW_Bx and some UNW_Px do have the
+   same value, but Px can only occur in a prologue context, and Bx in
+   a body context.  */
+
+#define UNW_R1 0x00
+#define UNW_R2 0x40
+#define UNW_R3 0x60
+#define UNW_P1 0x80
+#define UNW_P2 0xA0
+#define UNW_P3 0xB0
+#define UNW_P4 0xB8
+#define UNW_P5 0xB9
+#define UNW_P6 0xC0
+#define UNW_P7 0xE0
+#define UNW_P8 0xF0
+#define UNW_P9 0xF1
+#define UNW_P10        0xFF
+#define UNW_X1 0xF9
+#define UNW_X2 0xFA
+#define UNW_X3 0xFB
+#define UNW_X4 0xFC
+#define UNW_B1 0x80
+#define UNW_B2 0xC0
+#define UNW_B3 0xE0
+#define UNW_B4 0xF0
+
+/* These are all the various types of unwind records.  */
+
+typedef enum
+{
+  prologue, prologue_gr, body, mem_stack_f, mem_stack_v, psp_gr, psp_sprel,
+  rp_when, rp_gr, rp_br, rp_psprel, rp_sprel, pfs_when, pfs_gr, pfs_psprel,
+  pfs_sprel, preds_when, preds_gr, preds_psprel, preds_sprel,
+  fr_mem, frgr_mem, gr_gr, gr_mem, br_mem, br_gr, spill_base, spill_mask,
+  unat_when, unat_gr, unat_psprel, unat_sprel, lc_when, lc_gr, lc_psprel,
+  lc_sprel, fpsr_when, fpsr_gr, fpsr_psprel, fpsr_sprel, 
+  priunat_when_gr, priunat_when_mem, priunat_gr, priunat_psprel, 
+  priunat_sprel, bsp_when, bsp_gr, bsp_psprel, bsp_sprel, bspstore_when,
+  bspstore_gr, bspstore_psprel, bspstore_sprel, rnat_when, rnat_gr,
+  rnat_psprel, rnat_sprel, epilogue, label_state, copy_state,
+  spill_psprel, spill_sprel, spill_reg, spill_psprel_p, spill_sprel_p,
+  spill_reg_p
+} unw_record_type;
+
+
+/* These structures declare the fields that can be used in each of the 
+   4 record formats, R, P, B and X.  */
+
+typedef struct unw_r_record
+{
+  unsigned long rlen;
+  unsigned short mask;
+  unsigned short grsave;
+} unw_r_record;
+
+typedef struct unw_p_record
+{
+  void *imask;
+  unsigned long t;
+  unsigned long size;
+  unsigned long spoff;
+  unsigned long br;
+  unsigned long pspoff;
+  unsigned short gr;
+  unsigned short rmask;
+  unsigned short grmask;
+  unsigned long frmask;
+  unsigned short brmask;
+} unw_p_record;
+
+typedef struct unw_b_record
+{
+  unsigned long t;
+  unsigned long label;
+  unsigned short ecount;
+} unw_b_record;
+
+typedef struct unw_x_record
+{
+  unsigned long t;
+  unsigned long spoff;
+  unsigned long pspoff;
+  unsigned short reg;
+  unsigned short treg;
+  unsigned short qp;
+  unsigned short xy;   /* Value of the XY field..  */
+} unw_x_record;
+
+/* This structure is used to determine the specific record type and 
+   its fields.  */
+typedef struct unwind_record
+{
+  unw_record_type type;
+  union {
+    unw_r_record r;
+    unw_p_record p;
+    unw_b_record b;
+    unw_x_record x;
+  } record;
+} unwind_record;
+
+/* This structure represents the start of an unwind information pointer.  
+   'unwind_descriptors' is the beginninng of the unwind descriptors, which
+   use up 'length' bytes of storage.  */
+
+typedef struct unwind_info_ptr 
+{
+  unsigned short version;
+  unsigned short flags;
+  unsigned int length;
+  unsigned char unwind_descriptors[1];
+} unwind_info_ptr;
+
+
+#define IA64_UNW_LOC_TYPE_NONE         0
+#define IA64_UNW_LOC_TYPE_MEM          1
+#define IA64_UNW_LOC_TYPE_GR           2
+#define IA64_UNW_LOC_TYPE_FR           3
+#define IA64_UNW_LOC_TYPE_BR           4
+#define IA64_UNW_LOC_TYPE_SPOFF                5
+#define IA64_UNW_LOC_TYPE_PSPOFF       6
+#define IA64_UNW_LOC_TYPE_OFFSET       7
+#define IA64_UNW_LOC_TYPE_SPILLBASE    8
+
+typedef struct ia64_reg_loc 
+{
+  long when;           /* PC relative offset from start of function. */
+  union {              /* In memory or another register?  */
+    void *mem;
+    int regno;
+    int offset;
+  } l;
+  short loc_type;      /* Where to find value.  */
+  short reg_size;
+} ia64_reg_loc;
+
+/* Frame information record.  */
+
+typedef struct ia64_frame_state
+{
+  ia64_reg_loc gr[4];  /* gr4 to  gr7.  */
+  ia64_reg_loc fr[20]; /* fr2 to fr5, fr16 to fr31.  */
+  ia64_reg_loc br[5];  /* br1 to  br5.  */
+  ia64_reg_loc rp;
+  ia64_reg_loc fpsr;
+  ia64_reg_loc bsp;
+  ia64_reg_loc bspstore;
+  ia64_reg_loc rnat;
+  ia64_reg_loc pfs;
+  ia64_reg_loc unat;
+  ia64_reg_loc lc;
+  ia64_reg_loc pr;
+  ia64_reg_loc priunat;
+  ia64_reg_loc sp;
+  ia64_reg_loc psp;
+  ia64_reg_loc spill_base;
+  void *my_sp;
+  void *my_bsp;
+} ia64_frame_state;
+
+
+extern unwind_info_ptr *build_ia64_frame_state (unsigned char *, ia64_frame_state *, 
+                                               void *, void *);
+extern void *get_real_reg_value (ia64_reg_loc *);
+extern void *get_personality (unwind_info_ptr *);
+extern void *get_except_table (unwind_info_ptr *);
+extern void set_real_reg_value (ia64_reg_loc *, void *);
+void *calc_caller_bsp (long, unsigned char *);
+
+#endif   /* IA64_UNWIND_INFO  */
+
+/* Note the following routines are exported interfaces from libgcc; do not
+   change these interfaces.  Instead create new interfaces.  Also note
+   references to these functions may be made weak in files where they
+   are referenced.  */
+
+extern void __register_frame (void * );
+extern void __register_frame_table (void *);
+extern void __deregister_frame (void *);
+
+/* Called either from crtbegin.o or a static constructor to register the
+   unwind info for an object or translation unit, respectively.  */
+
+extern void __register_frame_info (void *, struct object *);
+
+/* Similar, but BEGIN is actually a pointer to a table of unwind entries
+   for different translation units.  Called from the file generated by
+   collect2.  */
+extern void __register_frame_info_table (void *, struct object *);
+
+/* Called from crtend.o to deregister the unwind info for an object.  */
+
+extern void *__deregister_frame_info (void *);
+
+
diff --git a/libjava/sysdep/ia64.c b/libjava/sysdep/ia64.c
new file mode 100644 (file)
index 0000000..f3c4761
--- /dev/null
@@ -0,0 +1,81 @@
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#include <stddef.h>
+#include <memory.h>
+
+#define IA64_UNWIND_INFO
+#include "ia64-frame.h"
+
+static int 
+ia64_backtrace_helper (void **array, void *throw_pc, 
+                      ia64_frame_state *throw_frame,
+                      ia64_frame_state *frame, void *bsp, int size)
+{
+  void *pc = NULL;
+  int frame_count = 0;
+  unwind_info_ptr *info;
+
+  asm volatile ("flushrs");  /*  Make the local register stacks available.  */
+    
+  /* Start at our stack frame, get our state.  */
+  info = build_ia64_frame_state (throw_pc, throw_frame, bsp, NULL);
+
+  memcpy (frame, throw_frame, sizeof (*frame));
+
+  while (info && frame_count < size)
+    {
+      pc = array[frame_count++] = get_real_reg_value (&frame->rp);
+      --pc;
+      bsp = calc_caller_bsp 
+       ((long)get_real_reg_value (&frame->pfs), frame->my_bsp);
+      info = build_ia64_frame_state (pc, frame, bsp, NULL);
+      if (frame->rp.loc_type == IA64_UNW_LOC_TYPE_NONE) /* We've finished. */
+       break;
+    }
+
+  return frame_count;
+}
+  
+int
+_Jv_ia64_backtrace (void **array, int size)
+{
+  ia64_frame_state my_frame;
+  ia64_frame_state originator; /* For the context handler is in.  */
+  void *bsp;
+  /* Do any necessary initialization to access arbitrary stack frames.
+     This forces gcc to save memory in our stack frame for saved
+     registers. */
+  __builtin_unwind_init ();
+
+label_ia64:
+  bsp = __builtin_ia64_bsp ();
+  
+  return ia64_backtrace_helper (array, &&label_ia64, &my_frame, 
+                               &originator, bsp, size);
+}
index ed58a1f..180ce65 100644 (file)
@@ -99,6 +99,7 @@ OBJDUMP = @OBJDUMP@
 PACKAGE = @PACKAGE@
 PERL = @PERL@
 RANLIB = @RANLIB@
+SYSDEP_SOURCES = @SYSDEP_SOURCES@
 SYSTEMSPEC = @SYSTEMSPEC@
 THREADDEPS = @THREADDEPS@
 THREADINCS = @THREADINCS@