diff options
125 files changed, 18458 insertions, 560 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 87c7b28..669ef7b 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -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. diff --git a/libjava/Makefile.am b/libjava/Makefile.am index d7b98c2..97d5047 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -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 = - - diff --git a/libjava/Makefile.in b/libjava/Makefile.in index 7038e2e..881731b 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -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 index 0000000..f31befd --- /dev/null +++ b/libjava/addr2name.awk @@ -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(); +} + + diff --git a/libjava/configure b/libjava/configure index f28388d..a108f72 100755 --- a/libjava/configure +++ b/libjava/configure @@ -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 diff --git a/libjava/configure.host b/libjava/configure.host index 38d927d..39a41bb 100644 --- a/libjava/configure.host +++ b/libjava/configure.host @@ -66,6 +66,11 @@ case "${host}" in ;; sparc-*) ;; + ia64-*) + libgcj_flags="${libgcj_flags} -funwind-tables" + libgcj_sjlj=yes + libgcj_interpreter=yes + ;; *) libgcj_sjlj=yes ;; diff --git a/libjava/configure.in b/libjava/configure.in index 8c4be25..5fefe1f 100644 --- a/libjava/configure.in +++ b/libjava/configure.in @@ -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 diff --git a/libjava/gcj/Makefile.in b/libjava/gcj/Makefile.in index 830733c..26fec33 100644 --- a/libjava/gcj/Makefile.in +++ b/libjava/gcj/Makefile.in @@ -99,6 +99,7 @@ OBJDUMP = @OBJDUMP@ PACKAGE = @PACKAGE@ PERL = @PERL@ RANLIB = @RANLIB@ +SYSDEP_SOURCES = @SYSDEP_SOURCES@ SYSTEMSPEC = @SYSTEMSPEC@ THREADDEPS = @THREADDEPS@ THREADINCS = @THREADINCS@ diff --git a/libjava/gcj/javaprims.h b/libjava/gcj/javaprims.h index 3e7d2e2..9ef52dc 100644 --- a/libjava/gcj/javaprims.h +++ b/libjava/gcj/javaprims.h @@ -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 index 0000000..bcf8ea5 --- /dev/null +++ b/libjava/gnu/gcj/io/SimpleSHSStream.java @@ -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 index 0000000..2cd213b --- /dev/null +++ b/libjava/gnu/gcj/io/natSimpleSHSStream.cc @@ -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 index 0000000..96b4f56 --- /dev/null +++ b/libjava/gnu/gcj/io/shs.cc @@ -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 index 0000000..8c91ff3 --- /dev/null +++ b/libjava/gnu/gcj/io/shs.h @@ -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 index 0000000..85aafa1 --- /dev/null +++ b/libjava/gnu/java/beans/BeanInfoEmbryo.java @@ -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 index 0000000..ad7d91d --- /dev/null +++ b/libjava/gnu/java/beans/EmptyBeanInfo.java @@ -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 index 0000000..8cab94b --- /dev/null +++ b/libjava/gnu/java/beans/ExplicitBeanInfo.java @@ -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 index 0000000..e3f4807 --- /dev/null +++ b/libjava/gnu/java/beans/IntrospectionIncubator.java @@ -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 index 0000000..1c002d6 --- /dev/null +++ b/libjava/gnu/java/beans/editors/ColorEditor.java @@ -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 index 0000000..3b0145a --- /dev/null +++ b/libjava/gnu/java/beans/editors/FontEditor.java @@ -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 index 0000000..0af58a5 --- /dev/null +++ b/libjava/gnu/java/beans/editors/NativeBooleanEditor.java @@ -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 index 0000000..513f4a6 --- /dev/null +++ b/libjava/gnu/java/beans/editors/NativeByteEditor.java @@ -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 index 0000000..45eb095 --- /dev/null +++ b/libjava/gnu/java/beans/editors/NativeDoubleEditor.java @@ -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 index 0000000..d0ec98d --- /dev/null +++ b/libjava/gnu/java/beans/editors/NativeFloatEditor.java @@ -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 index 0000000..16b7c6e --- /dev/null +++ b/libjava/gnu/java/beans/editors/NativeIntEditor.java @@ -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 index 0000000..e9a3345 --- /dev/null +++ b/libjava/gnu/java/beans/editors/NativeLongEditor.java @@ -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 index 0000000..b32bb6a --- /dev/null +++ b/libjava/gnu/java/beans/editors/NativeShortEditor.java @@ -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 index 0000000..bb3988c --- /dev/null +++ b/libjava/gnu/java/beans/editors/StringEditor.java @@ -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 index 0000000..4cf45fa --- /dev/null +++ b/libjava/gnu/java/beans/info/ComponentBeanInfo.java @@ -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 index 0000000..76e1f05 --- /dev/null +++ b/libjava/gnu/java/io/ClassLoaderObjectInputStream.java @@ -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 index 0000000..caf8ade --- /dev/null +++ b/libjava/gnu/java/io/NullOutputStream.java @@ -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 index 0000000..f06e205 --- /dev/null +++ b/libjava/gnu/java/io/ObjectIdentityWrapper.java @@ -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 index 0000000..a04551e --- /dev/null +++ b/libjava/gnu/java/lang/ArrayHelper.java @@ -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 index 0000000..a4f32dc --- /dev/null +++ b/libjava/gnu/java/lang/ClassHelper.java @@ -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 index 0000000..5a11e8c --- /dev/null +++ b/libjava/gnu/java/lang/reflect/TypeSignature.java @@ -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() ); + } +} diff --git a/libjava/include/Makefile.in b/libjava/include/Makefile.in index d348658..34d6c7b 100644 --- a/libjava/include/Makefile.in +++ b/libjava/include/Makefile.in @@ -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 \ diff --git a/libjava/include/config.h.in b/libjava/include/config.h.in index 10b74af..7667245 100644 --- a/libjava/include/config.h.in +++ b/libjava/include/config.h.in @@ -344,8 +344,14 @@ /* 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 diff --git a/libjava/include/default-signal.h b/libjava/include/default-signal.h index 0fb3d7d..492f0ca 100644 --- a/libjava/include/default-signal.h +++ b/libjava/include/default-signal.h @@ -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 */ diff --git a/libjava/include/i386-signal.h b/libjava/include/i386-signal.h index 491a809..599edc9 100644 --- a/libjava/include/i386-signal.h +++ b/libjava/include/i386-signal.h @@ -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; \ diff --git a/libjava/interpret.cc b/libjava/interpret.cc index d6d2958..6fd1fa6 100644 --- a/libjava/interpret.cc +++ b/libjava/interpret.cc @@ -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 index 0000000..b96a94f --- /dev/null +++ b/libjava/java/beans/BeanDescriptor.java @@ -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 index 0000000..3fcc527 --- /dev/null +++ b/libjava/java/beans/BeanInfo.java @@ -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><Bean Class Name>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 index 0000000..08e5623 --- /dev/null +++ b/libjava/java/beans/Beans.java @@ -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 index 0000000..1fecd4f --- /dev/null +++ b/libjava/java/beans/Customizer.java @@ -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 index 0000000..b7782f9 --- /dev/null +++ b/libjava/java/beans/DesignMode.java @@ -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 index 0000000..c0840fe --- /dev/null +++ b/libjava/java/beans/EventSetDescriptor.java @@ -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 <listenerMethodName>(<eventSetName>Event)</CODE> + ** (where <CODE><eventSetName></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<eventSetName>Listener(<listenerType>)</CODE> and + ** <CODE>void remove<eventSetName>Listener(<listenerType>)</CODE> in + ** in class <CODE>eventSourceClass</CODE>, where + ** <CODE><eventSetName></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 index 0000000..102a3a3 --- /dev/null +++ b/libjava/java/beans/FeatureDescriptor.java @@ -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 index 0000000..daf8441 --- /dev/null +++ b/libjava/java/beans/IndexedPropertyDescriptor.java @@ -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><propertyType>[] <getMethodName>()</CODE></LI> + ** <LI>A set array method must have signature + ** <CODE>void <setMethodName>(<propertyType>[])</CODE></LI> + ** <LI>A get index method must have signature + ** <CODE><propertyType> <getMethodName>(int)</CODE></LI> + ** <LI>A set index method must have signature + ** <CODE>void <setMethodName>(int,<propertyType>)</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<name>()</CODE> + ** and setter methods named + ** <CODE>set<name>()</CODE> in class + ** <CODE><beanClass></CODE>, where <name> 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 index 0000000..0bbd579 --- /dev/null +++ b/libjava/java/beans/IntrospectionException.java @@ -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 index 0000000..a191971 --- /dev/null +++ b/libjava/java/beans/Introspector.java @@ -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 <type> getXXX(int)</CODE> + ** method, then XXX is a read-only indexed property of + ** type <type>. If there is a + ** <CODE>public void setXXX(int,<type>)</CODE> + ** method, then it is a read-write indexed property of + ** type <type>. There may also be a + ** <CODE>public <type>[] getXXX()</CODE> and a + ** <CODE>public void setXXX(<type>)</CODE> + ** method as well.</CODE></LI> + ** <LI>If there is a + ** <CODE>public void setXXX(int,<type>)</CODE> + ** method, then it is a write-only indexed property of + ** type <type>. There may also be a + ** <CODE>public <type>[] getXXX()</CODE> and a + ** <CODE>public void setXXX(<type>)</CODE> + ** method as well.</CODE></LI> + ** <LI>If there is a + ** <CODE>public <type> getXXX()</CODE> method, + ** then XXX is a read-only property of type + ** <type>. If there is a + ** <CODE>public void setXXX(<type>)</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(<type>)</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 <type>.</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(<type>)</CODE> and + ** <CODE>public void removeXXX(<type>)</CODE>, where + ** <type> 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 <type>.<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 index 0000000..bb052f7 --- /dev/null +++ b/libjava/java/beans/MethodDescriptor.java @@ -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 index 0000000..664d5ca --- /dev/null +++ b/libjava/java/beans/ParameterDescriptor.java @@ -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 index 0000000..f07577c --- /dev/null +++ b/libjava/java/beans/PropertyChangeEvent.java @@ -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 index 0000000..7f1df72 --- /dev/null +++ b/libjava/java/beans/PropertyChangeListener.java @@ -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 index 0000000..512c8ed --- /dev/null +++ b/libjava/java/beans/PropertyChangeSupport.java @@ -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 index 0000000..ec14312 --- /dev/null +++ b/libjava/java/beans/PropertyDescriptor.java @@ -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><propertyType> <getMethodName>()</CODE></LI> + ** <LI>A set method must have signature + ** <CODE>void <setMethodName>(<propertyType>)</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<name>()</CODE> + ** (or, optionally, if the property is boolean, + ** <CODE>is<name>()</CODE>) and + ** <CODE>set<name>()</CODE> in class + ** <CODE><beanClass></CODE>, where <name> 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 index 0000000..b861b52 --- /dev/null +++ b/libjava/java/beans/PropertyEditor.java @@ -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 index 0000000..b64b2a8 --- /dev/null +++ b/libjava/java/beans/PropertyEditorManager.java @@ -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 index 0000000..6fadacc --- /dev/null +++ b/libjava/java/beans/PropertyEditorSupport.java @@ -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 index 0000000..51a5642 --- /dev/null +++ b/libjava/java/beans/PropertyVetoException.java @@ -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 index 0000000..e8b6777 --- /dev/null +++ b/libjava/java/beans/SimpleBeanInfo.java @@ -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 index 0000000..253d712 --- /dev/null +++ b/libjava/java/beans/VetoableChangeListener.java @@ -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 index 0000000..6d0ff0c --- /dev/null +++ b/libjava/java/beans/VetoableChangeSupport.java @@ -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 index 0000000..ca8c404 --- /dev/null +++ b/libjava/java/beans/Visibility.java @@ -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 index 0000000..d5274d8 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContext.java @@ -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 index 0000000..d8bcb5e --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextChild.java @@ -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 index 0000000..f8ef7ca --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextChildComponentProxy.java @@ -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 index 0000000..08d2a71 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextChildSupport.java @@ -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 index 0000000..28d967b0 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextContainerProxy.java @@ -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 index 0000000..0e4f20a --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextEvent.java @@ -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 index 0000000..d808735 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextMembershipEvent.java @@ -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 index 0000000..fc0b5b6 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextMembershipListener.java @@ -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 index 0000000..129e4f8 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextProxy.java @@ -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 index 0000000..933ef3d --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceAvailableEvent.java @@ -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 index 0000000..c7a570e --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceProvider.java @@ -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 index 0000000..d751f70 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java @@ -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 index 0000000..32520bc --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceRevokedEvent.java @@ -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 index 0000000..8caf357 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceRevokedListener.java @@ -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 index 0000000..e67687b --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServices.java @@ -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 index 0000000..bb55f8d --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServicesListener.java @@ -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 index 0000000..ef70f54 --- /dev/null +++ b/libjava/java/io/BlockDataException.java @@ -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 index 0000000..045df86 --- /dev/null +++ b/libjava/java/io/Externalizable.java @@ -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 index 0000000..fd03154 --- /dev/null +++ b/libjava/java/io/InvalidClassException.java @@ -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 index 0000000..705082a --- /dev/null +++ b/libjava/java/io/InvalidObjectException.java @@ -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 index 0000000..f628a3b --- /dev/null +++ b/libjava/java/io/NotActiveException.java @@ -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 index 0000000..d1e0bd2 --- /dev/null +++ b/libjava/java/io/NotSerializableException.java @@ -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 index 0000000..ef23fa9 --- /dev/null +++ b/libjava/java/io/ObjectInput.java @@ -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 index 0000000..7855480 --- /dev/null +++ b/libjava/java/io/ObjectInputStream.java @@ -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 index 0000000..cf3508e --- /dev/null +++ b/libjava/java/io/ObjectInputValidation.java @@ -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 index 0000000..56b3390 --- /dev/null +++ b/libjava/java/io/ObjectOutput.java @@ -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 index 0000000..a98b55ba --- /dev/null +++ b/libjava/java/io/ObjectOutputStream.java @@ -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<type></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 index 0000000..f799b4f --- /dev/null +++ b/libjava/java/io/ObjectStreamClass.java @@ -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 index 0000000..c9a2aea --- /dev/null +++ b/libjava/java/io/ObjectStreamConstants.java @@ -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 index 0000000..55181cc --- /dev/null +++ b/libjava/java/io/ObjectStreamField.java @@ -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 index 0000000..1035ab5 --- /dev/null +++ b/libjava/java/io/Replaceable.java @@ -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 index 0000000..b7250de6 --- /dev/null +++ b/libjava/java/io/Resolvable.java @@ -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 index 0000000..78c7229 --- /dev/null +++ b/libjava/java/io/SerializablePermission.java @@ -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 index 0000000..1f22514 --- /dev/null +++ b/libjava/java/io/WriteAbortedException.java @@ -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 index 0000000..b7a8dcb --- /dev/null +++ b/libjava/java/io/natObjectInputStream.cc @@ -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 index 0000000..45ab753 --- /dev/null +++ b/libjava/java/io/natObjectOutputStream.cc @@ -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); +} + diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h index d685a1b..03fa439 100644 --- a/libjava/java/lang/Class.h +++ b/libjava/java/lang/Class.h @@ -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*); diff --git a/libjava/java/lang/SecurityManager.java b/libjava/java/lang/SecurityManager.java index 4f1d152..9c14552 100644 --- a/libjava/java/lang/SecurityManager.java +++ b/libjava/java/lang/SecurityManager.java @@ -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(); diff --git a/libjava/java/lang/String.java b/libjava/java/lang/String.java index 54be314..12f8789 100644 --- a/libjava/java/lang/String.java +++ b/libjava/java/lang/String.java @@ -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); diff --git a/libjava/java/lang/StringBuffer.java b/libjava/java/lang/StringBuffer.java index cf82540..6e00fa7 100644 --- a/libjava/java/lang/StringBuffer.java +++ b/libjava/java/lang/StringBuffer.java @@ -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. diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index 93e8210..dfc3840 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -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); +} + diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc index 896873a..aa8782d 100644 --- a/libjava/java/lang/natClassLoader.cc +++ b/libjava/java/lang/natClassLoader.cc @@ -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); diff --git a/libjava/java/lang/natString.cc b/libjava/java/lang/natString.cc index 376a016..5a28c1e 100644 --- a/libjava/java/lang/natString.cc +++ b/libjava/java/lang/natString.cc @@ -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; } diff --git a/libjava/java/lang/natThrowable.cc b/libjava/java/lang/natThrowable.cc index bbe18c2..eeb4e41e 100644 --- a/libjava/java/lang/natThrowable.cc +++ b/libjava/java/lang/natThrowable.cc @@ -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 (); } diff --git a/libjava/java/net/URL.java b/libjava/java/net/URL.java index f80a52f..5931eef 100644 --- a/libjava/java/net/URL.java +++ b/libjava/java/net/URL.java @@ -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 index 0000000..f2e70ed --- /dev/null +++ b/libjava/java/security/BasicPermission.java @@ -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 index 0000000..8d51278 --- /dev/null +++ b/libjava/java/security/DigestOutputStream.java @@ -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 index 0000000..b397ddd --- /dev/null +++ b/libjava/java/security/Guard.java @@ -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 index 0000000..620d5b4 --- /dev/null +++ b/libjava/java/security/Permission.java @@ -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 index 0000000..08a9c49 --- /dev/null +++ b/libjava/java/security/PermissionCollection.java @@ -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 index 0000000..8002044 --- /dev/null +++ b/libjava/java/util/AbstractCollection.java @@ -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 index 0000000..da76a8b --- /dev/null +++ b/libjava/java/util/AbstractList.java @@ -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 index 0000000..fc51d38 --- /dev/null +++ b/libjava/java/util/Arrays.java @@ -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; + } + +} diff --git a/libjava/libgcj.spec.in b/libjava/libgcj.spec.in index e9c2548..8a1aa87 100644 --- a/libjava/libgcj.spec.in +++ b/libjava/libgcj.spec.in @@ -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 diff --git a/libjava/libltdl/Makefile.in b/libjava/libltdl/Makefile.in index b64463e..d4de792 100644 --- a/libjava/libltdl/Makefile.in +++ b/libjava/libltdl/Makefile.in @@ -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 diff --git a/libjava/mauve-libgcj b/libjava/mauve-libgcj index 28905d1..1a4e48b 100644 --- a/libjava/mauve-libgcj +++ b/libjava/mauve-libgcj @@ -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 diff --git a/libjava/name-finder.cc b/libjava/name-finder.cc index 8f0cdf4..ab028af 100644 --- a/libjava/name-finder.cc +++ b/libjava/name-finder.cc @@ -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; } diff --git a/libjava/prims.cc b/libjava/prims.cc index c9cb92e..4279b09 100644 --- a/libjava/prims.cc +++ b/libjava/prims.cc @@ -95,13 +95,26 @@ void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event); #endif +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; diff --git a/libjava/scripts/classes.pl b/libjava/scripts/classes.pl index 05f9133..e9f17c7 100644 --- a/libjava/scripts/classes.pl +++ b/libjava/scripts/classes.pl @@ -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 index 0000000..7f07988 --- /dev/null +++ b/libjava/sysdep/ia64-frame.h @@ -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 index 0000000..f3c4761 --- /dev/null +++ b/libjava/sysdep/ia64.c @@ -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); +} diff --git a/libjava/testsuite/Makefile.in b/libjava/testsuite/Makefile.in index ed58a1f..180ce65 100644 --- a/libjava/testsuite/Makefile.in +++ b/libjava/testsuite/Makefile.in @@ -99,6 +99,7 @@ OBJDUMP = @OBJDUMP@ PACKAGE = @PACKAGE@ PERL = @PERL@ RANLIB = @RANLIB@ +SYSDEP_SOURCES = @SYSDEP_SOURCES@ SYSTEMSPEC = @SYSTEMSPEC@ THREADDEPS = @THREADDEPS@ THREADINCS = @THREADINCS@ |