aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/beans
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/beans')
-rw-r--r--libjava/java/beans/BeanDescriptor.java72
-rw-r--r--libjava/java/beans/BeanInfo.java170
-rw-r--r--libjava/java/beans/Beans.java199
-rw-r--r--libjava/java/beans/Customizer.java75
-rw-r--r--libjava/java/beans/DesignMode.java82
-rw-r--r--libjava/java/beans/EventSetDescriptor.java429
-rw-r--r--libjava/java/beans/FeatureDescriptor.java155
-rw-r--r--libjava/java/beans/IndexedPropertyDescriptor.java296
-rw-r--r--libjava/java/beans/IntrospectionException.java46
-rw-r--r--libjava/java/beans/Introspector.java427
-rw-r--r--libjava/java/beans/MethodDescriptor.java77
-rw-r--r--libjava/java/beans/ParameterDescriptor.java41
-rw-r--r--libjava/java/beans/PropertyChangeEvent.java111
-rw-r--r--libjava/java/beans/PropertyChangeListener.java48
-rw-r--r--libjava/java/beans/PropertyChangeSupport.java203
-rw-r--r--libjava/java/beans/PropertyDescriptor.java333
-rw-r--r--libjava/java/beans/PropertyEditor.java198
-rw-r--r--libjava/java/beans/PropertyEditorManager.java150
-rw-r--r--libjava/java/beans/PropertyEditorSupport.java195
-rw-r--r--libjava/java/beans/PropertyVetoException.java55
-rw-r--r--libjava/java/beans/SimpleBeanInfo.java127
-rw-r--r--libjava/java/beans/VetoableChangeListener.java62
-rw-r--r--libjava/java/beans/VetoableChangeSupport.java245
-rw-r--r--libjava/java/beans/Visibility.java74
-rw-r--r--libjava/java/beans/beancontext/BeanContext.java261
-rw-r--r--libjava/java/beans/beancontext/BeanContextChild.java162
-rw-r--r--libjava/java/beans/beancontext/BeanContextChildComponentProxy.java49
-rw-r--r--libjava/java/beans/beancontext/BeanContextChildSupport.java356
-rw-r--r--libjava/java/beans/beancontext/BeanContextContainerProxy.java52
-rw-r--r--libjava/java/beans/beancontext/BeanContextEvent.java91
-rw-r--r--libjava/java/beans/beancontext/BeanContextMembershipEvent.java102
-rw-r--r--libjava/java/beans/beancontext/BeanContextMembershipListener.java59
-rw-r--r--libjava/java/beans/beancontext/BeanContextProxy.java54
-rw-r--r--libjava/java/beans/beancontext/BeanContextServiceAvailableEvent.java84
-rw-r--r--libjava/java/beans/beancontext/BeanContextServiceProvider.java129
-rw-r--r--libjava/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java49
-rw-r--r--libjava/java/beans/beancontext/BeanContextServiceRevokedEvent.java99
-rw-r--r--libjava/java/beans/beancontext/BeanContextServiceRevokedListener.java51
-rw-r--r--libjava/java/beans/beancontext/BeanContextServices.java195
-rw-r--r--libjava/java/beans/beancontext/BeanContextServicesListener.java45
40 files changed, 5708 insertions, 0 deletions
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>&lt;Bean Class Name&gt;BeanInfo</CODE> and place it in
+ ** the same package as the Bean, or in the bean info search path
+ ** (see Introspector for information on search paths).<P>
+ **
+ ** A simple note about the way the Introspector interacts with
+ ** BeanInfo. Introspectors look at a Bean class and determine
+ ** if there is a BeanInfo class with it. If there is not a
+ ** BeanInfo class, it will behave as if the BeanInfo class
+ ** provided was a SimpleBeanInfo class (i.e. it will determine
+ ** all information automatically).<P>If there is a BeanInfo
+ ** class, then any methods that do *not* return null are
+ ** regarded as providing definitive information about the class
+ ** and all of its superclasses for those information types.
+ ** Even if a parent BeanInfo class explicitly returns that
+ ** information, it will not be used.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 28 Jul 1998
+ **/
+
+public interface BeanInfo {
+ /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+ public static int ICON_COLOR_16x16 = 1;
+ /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+ public static int ICON_COLOR_32x32 = 2;
+ /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+ public static int ICON_MONO_16x16 = 3;
+ /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
+ public static int ICON_MONO_32x32 = 4;
+
+ /** Get the general description of this Bean type.
+ ** @return the BeanDescriptor for the Bean, or null if
+ ** the BeanDescriptor should be obtained by
+ ** Introspection.
+ **/
+ public abstract BeanDescriptor getBeanDescriptor();
+
+ /** Get the events this Bean type fires.
+ ** @return the EventDescriptors representing events this
+ ** Bean fires. Returns <CODE>null</CODE> if the
+ ** events are to be acquired by Introspection.
+ **/
+ public abstract EventSetDescriptor[] getEventSetDescriptors();
+
+ /** Get the "default" event, basically the one a RAD tool
+ ** user is most likely to select.
+ ** @return the index into the getEventSetDescriptors()
+ ** that the user is most likely to use. Returns
+ ** <CODE>-1</CODE> if there is no default event.
+ **/
+ public abstract int getDefaultEventIndex();
+
+ /** Get the properties (get/set method pairs) this Bean
+ ** type supports.
+ ** @return the PropertyDescriptors representing the
+ ** properties this Bean type supports.
+ ** Returns <CODE>null</CODE> if the properties
+ ** are to be obtained by Introspection.
+ **/
+ public abstract PropertyDescriptor[] getPropertyDescriptors();
+
+ /** Get the "default" property, basically the one a RAD
+ ** tool user is most likely to select.
+ ** @return the index into the getPropertyDescriptors()
+ ** that the user is most likely to use. Returns
+ ** <CODE>-1</CODE> if there is no default event.
+ **/
+ public abstract int getDefaultPropertyIndex();
+
+ /** Get the methods this Bean type supports.
+ ** @return the MethodDescriptors representing the
+ ** methods this Bean type supports. Returns
+ ** <CODE>null</CODE> if the methods are to be
+ ** obtained by Introspection.
+ **/
+ public abstract MethodDescriptor[] getMethodDescriptors();
+
+ /** Get additional BeanInfos representing this Bean.
+ ** In this version of JavaBeans, this method is used so
+ ** that space and time can be saved by reading a BeanInfo
+ ** for each class in the hierarchy (super, super(super),
+ ** and so on).<P>
+ **
+ ** The order of precedence when two pieces of BeanInfo
+ ** conflict (such as two PropertyDescriptors that have
+ ** the same name), in order from highest precedence to
+ ** lowest, is:
+ ** <OL>
+ ** <LI>This BeanInfo object.</LI>
+ ** <LI><CODE>getAdditionalBeanInfo()[getAdditionalBeanInfo().length]</CODE></LI>
+ ** <LI> ... </LI>
+ ** <LI><CODE>getAdditionalBeanInfo()[1]</CODE></LI>
+ ** <LI><CODE>getAdditionalBeanInfo()[0]</CODE></LI>
+ ** </OL><P>
+ **
+ ** <STRONG>Spec Note:</STRONG> It is possible that
+ ** returning <CODE>null</CODE> from this method could
+ ** stop Introspection in its tracks, but it is unclear
+ ** from the spec whether this is the case.
+ **
+ ** @return additional BeanInfos representing this Bean.
+ ** <CODE>null</CODE> may be returned (see Spec
+ ** Note, above).
+ **/
+ public abstract BeanInfo[] getAdditionalBeanInfo();
+
+ /** Get a visual icon for this Bean.
+ ** A Bean does not have to support icons, and if it does
+ ** support icons, it does not have to support every single
+ ** type. Sun recommends that if you only support one
+ ** type, you support 16x16 color. Sun also notes that you
+ ** should try to use a type (like GIF) that allows for
+ ** transparent pixels, so that the background of the RAD
+ ** tool can show through.<P>
+ **
+ ** <STRONG>Spec Note:</STRONG> If you do not support the
+ ** type of icon that is being asked for, but you do
+ ** support another type, it is unclear whether you should
+ ** return the other type or not. I would presume not.
+ **
+ ** @param iconType the type of icon to get (see the
+ ** ICON_* constants in this class).
+ ** @return the icon, or null if that type of icon is
+ ** unsupported by this Bean.
+ **/
+ public abstract java.awt.Image getIcon(int iconType);
+}
diff --git a/libjava/java/beans/Beans.java b/libjava/java/beans/Beans.java
new file mode 100644
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 &lt;listenerMethodName&gt;(&lt;eventSetName&gt;Event)</CODE>
+ ** (where <CODE>&lt;eventSetName&gt;</CODE> has its first character capitalized
+ ** by the constructor and the Event is a descendant of
+ ** <CODE>java.util.EventObject</CODE>) in class <CODE>listenerType</CODE>
+ ** (any exceptions may be thrown).
+ ** <B>Implementation note:</B> Note that there could conceivably be multiple
+ ** methods with this type of signature (example: java.util.MouseEvent vs.
+ ** my.very.own.MouseEvent). In this implementation, all methods fitting the
+ ** description will be put into the <CODE>EventSetDescriptor</CODE>, even
+ ** though the spec says only one should be chosen (they probably weren't thinking as
+ ** pathologically as I was). I don't like arbitrarily choosing things.
+ ** If your class has only one such signature, as most do, you'll have no problems.</LI>
+ ** <LI>The add and remove methods must be public and named
+ ** <CODE>void add&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> and
+ ** <CODE>void remove&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> in
+ ** in class <CODE>eventSourceClass</CODE>, where
+ ** <CODE>&lt;eventSetName&gt;</CODE> will have its first letter capitalized.
+ ** Standard exception rules (see class description) apply.</LI>
+ ** </OL>
+ ** @param eventSourceClass the class containing the add/remove listener methods.
+ ** @param eventSetName the programmatic name of the event set, generally starting
+ ** with a lowercase letter (i.e. fooManChu instead of FooManChu). This will be used
+ ** to generate the name of the event object as well as the names of the add and
+ ** remove methods.
+ ** @param listenerType the class containing the event firing method.
+ ** @param listenerMethodName the name of the event firing method.
+ ** @exception IntrospectionException if listenerType is not an EventListener,
+ ** or if methods are not found or are invalid.
+ **/
+ public EventSetDescriptor(Class eventSourceClass,
+ String eventSetName,
+ Class listenerType,
+ String listenerMethodName) throws IntrospectionException {
+ setName(eventSetName);
+ if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Listener type is not an EventListener.");
+ }
+
+ String[] names = new String[1];
+ names[0] = listenerMethodName;
+
+ try {
+ eventSetName = Character.toUpperCase(eventSetName.charAt(0)) + eventSetName.substring(1);
+ } catch(StringIndexOutOfBoundsException e) {
+ eventSetName = "";
+ }
+
+ findMethods(eventSourceClass,listenerType,names,"add"+eventSetName+"Listener","remove"+eventSetName+"Listener",eventSetName+"Event");
+ this.listenerType = listenerType;
+ checkAddListenerUnicast();
+ if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+ throw new IntrospectionException("Listener remove method throws exceptions.");
+ }
+ }
+
+ /** Create a new EventSetDescriptor.
+ ** This form of the constructor allows you to specify the names of the methods and adds
+ ** no new constraints on top of the rules already described at the top of the class.<P>
+ **
+ ** @param eventSourceClass the class containing the add and remove listener methods.
+ ** @param eventSetName the programmatic name of the event set, generally starting
+ ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+ ** @param listenerType the class containing the event firing methods.
+ ** @param listenerMethodNames the names of the even firing methods.
+ ** @param addListenerMethodName the name of the add listener method.
+ ** @param removeListenerMethodName the name of the remove listener method.
+ ** @exception IntrospectionException if listenerType is not an EventListener
+ ** or if methods are not found or are invalid.
+ **/
+ public EventSetDescriptor(Class eventSourceClass,
+ String eventSetName,
+ Class listenerType,
+ String[] listenerMethodNames,
+ String addListenerMethodName,
+ String removeListenerMethodName) throws IntrospectionException {
+ setName(eventSetName);
+ if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Listener type is not an EventListener.");
+ }
+
+ findMethods(eventSourceClass,listenerType,listenerMethodNames,addListenerMethodName,removeListenerMethodName,null);
+ this.listenerType = listenerType;
+ checkAddListenerUnicast();
+ if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+ throw new IntrospectionException("Listener remove method throws exceptions.");
+ }
+ }
+
+ /** Create a new EventSetDescriptor.
+ ** This form of constructor allows you to explicitly say which methods do what, and
+ ** no reflection is done by the EventSetDescriptor. The methods are, however,
+ ** checked to ensure that they follow the rules set forth at the top of the class.
+ ** @param eventSetName the programmatic name of the event set, generally starting
+ ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+ ** @param listenerType the class containing the listenerMethods.
+ ** @param listenerMethods the event firing methods.
+ ** @param addListenerMethod the add listener method.
+ ** @param removeListenerMethod the remove listener method.
+ ** @exception IntrospectionException if the listenerType is not an EventListener,
+ ** or any of the methods are invalid.
+ **/
+ public EventSetDescriptor(String eventSetName,
+ Class listenerType,
+ Method[] listenerMethods,
+ Method addListenerMethod,
+ Method removeListenerMethod) throws IntrospectionException {
+ setName(eventSetName);
+ if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Listener type is not an EventListener.");
+ }
+
+ this.listenerMethods = listenerMethods;
+ this.addListenerMethod = addListenerMethod;
+ this.removeListenerMethod = removeListenerMethod;
+ this.listenerType = listenerType;
+ checkMethods();
+ checkAddListenerUnicast();
+ if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+ throw new IntrospectionException("Listener remove method throws exceptions.");
+ }
+ }
+
+ /** Create a new EventSetDescriptor.
+ ** This form of constructor allows you to explicitly say which methods do what, and
+ ** no reflection is done by the EventSetDescriptor. The methods are, however,
+ ** checked to ensure that they follow the rules set forth at the top of the class.
+ ** @param eventSetName the programmatic name of the event set, generally starting
+ ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
+ ** @param listenerType the class containing the listenerMethods.
+ ** @param listenerMethodDescriptors the event firing methods.
+ ** @param addListenerMethod the add listener method.
+ ** @param removeListenerMethod the remove listener method.
+ ** @exception IntrospectionException if the listenerType is not an EventListener,
+ ** or any of the methods are invalid.
+ **/
+ public EventSetDescriptor(String eventSetName,
+ Class listenerType,
+ MethodDescriptor[] listenerMethodDescriptors,
+ Method addListenerMethod,
+ Method removeListenerMethod) throws IntrospectionException {
+ setName(eventSetName);
+ if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Listener type is not an EventListener.");
+ }
+
+ this.listenerMethodDescriptors = listenerMethodDescriptors;
+ this.listenerMethods = new Method[listenerMethodDescriptors.length];
+ for(int i=0;i<this.listenerMethodDescriptors.length;i++) {
+ this.listenerMethods[i] = this.listenerMethodDescriptors[i].getMethod();
+ }
+
+ this.addListenerMethod = addListenerMethod;
+ this.removeListenerMethod = removeListenerMethod;
+ this.listenerType = listenerType;
+ checkMethods();
+ checkAddListenerUnicast();
+ if(this.removeListenerMethod.getExceptionTypes().length > 0) {
+ throw new IntrospectionException("Listener remove method throws exceptions.");
+ }
+ }
+
+ /** Get the class that contains the event firing methods. **/
+ public Class getListenerType() {
+ return listenerType;
+ }
+
+ /** Get the event firing methods. **/
+ public Method[] getListenerMethods() {
+ return listenerMethods;
+ }
+
+ /** Get the event firing methods as MethodDescriptors. **/
+ public MethodDescriptor[] getListenerMethodDescriptors() {
+ if(listenerMethodDescriptors == null) {
+ listenerMethodDescriptors = new MethodDescriptor[listenerMethods.length];
+ for(int i=0;i<listenerMethods.length;i++) {
+ listenerMethodDescriptors[i] = new MethodDescriptor(listenerMethods[i]);
+ }
+ }
+ return listenerMethodDescriptors;
+ }
+
+ /** Get the add listener method. **/
+ public Method getAddListenerMethod() {
+ return addListenerMethod;
+ }
+
+ /** Get the remove listener method. **/
+ public Method getRemoveListenerMethod() {
+ return removeListenerMethod;
+ }
+
+ /** Set whether or not multiple listeners may be added.
+ ** @param unicast whether or not multiple listeners may be added.
+ **/
+ public void setUnicast(boolean unicast) {
+ this.unicast = unicast;
+ }
+
+ /** Get whether or not multiple listeners may be added. (Defaults to false.) **/
+ public boolean isUnicast() {
+ return unicast;
+ }
+
+ /** Set whether or not this is in the default event set.
+ ** @param inDefaultEventSet whether this is in the default event set.
+ **/
+ public void setInDefaultEventSet(boolean inDefaultEventSet) {
+ this.inDefaultEventSet = inDefaultEventSet;
+ }
+
+ /** Get whether or not this is in the default event set. (Defaults to true.)**/
+ public boolean isInDefaultEventSet() {
+ return inDefaultEventSet;
+ }
+
+ private void checkAddListenerUnicast() throws IntrospectionException {
+ Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
+ if(addListenerExceptions.length > 1) {
+ throw new IntrospectionException("Listener add method throws too many exceptions.");
+ } else if(addListenerExceptions.length == 1
+ && !java.util.TooManyListenersException.class.isAssignableFrom(addListenerExceptions[0])) {
+ throw new IntrospectionException("Listener add method throws too many exceptions.");
+ }
+ }
+
+ private void checkMethods() throws IntrospectionException {
+ if(!addListenerMethod.getDeclaringClass().isAssignableFrom(removeListenerMethod.getDeclaringClass())
+ && !removeListenerMethod.getDeclaringClass().isAssignableFrom(addListenerMethod.getDeclaringClass())) {
+ throw new IntrospectionException("add and remove listener methods do not come from the same class. This is bad.");
+ }
+ if(!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
+ || addListenerMethod.getParameterTypes().length != 1
+ || !listenerType.equals(addListenerMethod.getParameterTypes()[0])
+ || !Modifier.isPublic(addListenerMethod.getModifiers())) {
+ throw new IntrospectionException("Add Listener Method invalid.");
+ }
+ if(!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
+ || removeListenerMethod.getParameterTypes().length != 1
+ || !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
+ || removeListenerMethod.getExceptionTypes().length > 0
+ || !Modifier.isPublic(removeListenerMethod.getModifiers())) {
+ throw new IntrospectionException("Remove Listener Method invalid.");
+ }
+
+ for(int i=0;i<listenerMethods.length;i++) {
+ if(!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
+ || Modifier.isPrivate(listenerMethods[i].getModifiers())) {
+ throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " non-void or private.");
+ }
+ if(!listenerMethods[i].getDeclaringClass().isAssignableFrom(listenerType)) {
+ throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " not from class " + listenerType.getName());
+ }
+ }
+ }
+
+ private void findMethods(Class eventSourceClass,
+ Class listenerType,
+ String listenerMethodNames[],
+ String addListenerMethodName,
+ String removeListenerMethodName,
+ String absurdEventClassCheckName) throws IntrospectionException {
+
+ /* Find add listener method and remove listener method. */
+ Class[] listenerArgList = new Class[1];
+ listenerArgList[0] = listenerType;
+ try {
+ this.addListenerMethod = eventSourceClass.getMethod(addListenerMethodName,listenerArgList);
+ } catch(SecurityException E) {
+ throw new IntrospectionException("SecurityException trying to access method " + addListenerMethodName + ".");
+ } catch(NoSuchMethodException E) {
+ throw new IntrospectionException("Could not find method " + addListenerMethodName + ".");
+ }
+
+ if(this.addListenerMethod == null || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+ throw new IntrospectionException("Add listener method does not exist, is not public, or is not void.");
+ }
+
+ try {
+ this.removeListenerMethod = eventSourceClass.getMethod(removeListenerMethodName,listenerArgList);
+ } catch(SecurityException E) {
+ throw new IntrospectionException("SecurityException trying to access method " + removeListenerMethodName + ".");
+ } catch(NoSuchMethodException E) {
+ throw new IntrospectionException("Could not find method " + removeListenerMethodName + ".");
+ }
+ if(this.removeListenerMethod == null || !this.removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+ throw new IntrospectionException("Remove listener method does not exist, is not public, or is not void.");
+ }
+
+ /* Find the listener methods. */
+ Method[] methods;
+ try {
+ methods = ClassHelper.getAllMethods(listenerType);
+ } catch(SecurityException E) {
+ throw new IntrospectionException("Security: You cannot access fields in this class.");
+ }
+
+ Vector chosenMethods = new Vector();
+ boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
+ for(int i=0;i<methods.length;i++) {
+ if(Modifier.isPrivate(methods[i].getModifiers())) {
+ continue;
+ }
+ Method currentMethod = methods[i];
+ Class retval = currentMethod.getReturnType();
+ if(retval.equals(java.lang.Void.TYPE)) {
+ for(int j=0;j<listenerMethodNames.length;j++) {
+ if(currentMethod.getName().equals(listenerMethodNames[j])
+ && (absurdEventClassCheckName == null
+ || (currentMethod.getParameterTypes().length == 1
+ && ((currentMethod.getParameterTypes()[0]).getName().equals(absurdEventClassCheckName)
+ || (currentMethod.getParameterTypes()[0]).getName().endsWith("."+absurdEventClassCheckName)
+ )
+ )
+ )
+ ) {
+ chosenMethods.addElement(currentMethod);
+ listenerMethodFound[j] = true;
+ }
+ }
+ }
+ }
+
+ /* Make sure we found all the methods we were looking for. */
+ for(int i=0;i<listenerMethodFound.length;i++) {
+ if(!listenerMethodFound[i]) {
+ throw new IntrospectionException("Could not find event method " + listenerMethodNames[i]);
+ }
+ }
+
+ /* Now that we've chosen the listener methods we want, store them. */
+ this.listenerMethods = new Method[chosenMethods.size()];
+ for(int i=0;i<chosenMethods.size();i++) {
+ this.listenerMethods[i] = (Method)chosenMethods.elementAt(i);
+ }
+ }
+}
diff --git a/libjava/java/beans/FeatureDescriptor.java b/libjava/java/beans/FeatureDescriptor.java
new file mode 100644
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>&lt;propertyType&gt;[] &lt;getMethodName&gt;()</CODE></LI>
+ ** <LI>A set array method must have signature
+ ** <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;[])</CODE></LI>
+ ** <LI>A get index method must have signature
+ ** <CODE>&lt;propertyType&gt; &lt;getMethodName&gt;(int)</CODE></LI>
+ ** <LI>A set index method must have signature
+ ** <CODE>void &lt;setMethodName&gt;(int,&lt;propertyType&gt;)</CODE></LI>
+ ** <LI>All these methods may throw any exception.</LI>
+ ** <LI>All these methods must be public.</LI>
+ ** </OL>
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+
+public class IndexedPropertyDescriptor extends PropertyDescriptor {
+ private Class indexedPropertyType;
+ private Method setIndex;
+ private Method getIndex;
+
+ /** Create a new IndexedPropertyDescriptor by introspection.
+ ** This form of constructor creates the PropertyDescriptor by
+ ** looking for getter methods named <CODE>get&lt;name&gt;()</CODE>
+ ** and setter methods named
+ ** <CODE>set&lt;name&gt;()</CODE> in class
+ ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
+ ** first letter capitalized by the constructor.<P>
+ **
+ ** <B>Implementation note:</B> If there is a get(int) method,
+ ** then the return type of that method is used to find the
+ ** remaining methods. If there is no get method, then the
+ ** set(int) method is searched for exhaustively and that type
+ ** is used to find the others.<P>
+ **
+ ** <B>Spec note:</B>
+ ** If there is no get(int) method and multiple set(int) methods with
+ ** the same name and the correct parameters (different type of course),
+ ** then an IntrospectionException is thrown. While Sun's spec
+ ** does not state this, it can make Bean behavior different on
+ ** different systems (since method order is not guaranteed) and as
+ ** such, can be treated as a bug in the spec. I am not aware of
+ ** whether Sun's implementation catches this.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param beanClass the class the get and set methods live in.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public IndexedPropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
+ super(name);
+ String capitalized;
+ try {
+ capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ } catch(StringIndexOutOfBoundsException e) {
+ capitalized = "";
+ }
+ findMethods(beanClass, "get" + capitalized, "set" + capitalized, "get" + capitalized, "set" + capitalized);
+ }
+
+ /** Create a new IndexedPropertyDescriptor by introspection.
+ ** This form of constructor allows you to specify the
+ ** names of the get and set methods to search for.<P>
+ **
+ ** <B>Implementation note:</B> If there is a get(int) method,
+ ** then the return type of that method is used to find the
+ ** remaining methods. If there is no get method, then the
+ ** set(int) method is searched for exhaustively and that type
+ ** is used to find the others.<P>
+ **
+ ** <B>Spec note:</B>
+ ** If there is no get(int) method and multiple set(int) methods with
+ ** the same name and the correct parameters (different type of course),
+ ** then an IntrospectionException is thrown. While Sun's spec
+ ** does not state this, it can make Bean behavior different on
+ ** different systems (since method order is not guaranteed) and as
+ ** such, can be treated as a bug in the spec. I am not aware of
+ ** whether Sun's implementation catches this.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param beanClass the class the get and set methods live in.
+ ** @param getMethodName the name of the get array method.
+ ** @param setMethodName the name of the set array method.
+ ** @param getIndexName the name of the get index method.
+ ** @param setIndexName the name of the set index method.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public IndexedPropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
+ super(name);
+ findMethods(beanClass, getMethodName, setMethodName, getIndexName, setIndexName);
+ }
+
+ /** Create a new PropertyDescriptor using explicit Methods.
+ ** Note that the methods will be checked for conformance to standard
+ ** Property method rules, as described above at the top of this class.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param getMethod the get array method.
+ ** @param setMethod the set array method.
+ ** @param getIndex the get index method.
+ ** @param setIndex the set index method.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public IndexedPropertyDescriptor(String name, Method getMethod, Method setMethod, Method getIndex, Method setIndex) throws IntrospectionException {
+ super(name);
+ if(getMethod != null && getMethod.getParameterTypes().length > 0) {
+ throw new IntrospectionException("get method has parameters");
+ }
+ if(getMethod != null && setMethod.getParameterTypes().length != 1) {
+ throw new IntrospectionException("set method does not have exactly one parameter");
+ }
+ if(getMethod != null && setMethod != null) {
+ if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
+ throw new IntrospectionException("set and get methods do not share the same type");
+ }
+ if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
+ && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
+ throw new IntrospectionException("set and get methods are not in the same class.");
+ }
+ }
+
+ if(getIndex != null && (getIndex.getParameterTypes().length != 1
+ || !(getIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
+ throw new IntrospectionException("get index method has wrong parameters");
+ }
+ if(setIndex != null && (setIndex.getParameterTypes().length != 2
+ || !(setIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
+ throw new IntrospectionException("set index method has wrong parameters");
+ }
+ if(getIndex != null && setIndex != null) {
+ if(!getIndex.getReturnType().equals(setIndex.getParameterTypes()[1])) {
+ throw new IntrospectionException("set index methods do not share the same type");
+ }
+ if(!getIndex.getDeclaringClass().isAssignableFrom(setIndex.getDeclaringClass())
+ && !setIndex.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
+ throw new IntrospectionException("get and set index methods are not in the same class.");
+ }
+ }
+
+ if(getIndex != null && getMethod != null && !getIndex.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())
+ && !getMethod.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
+ throw new IntrospectionException("methods are not in the same class.");
+ }
+
+ if(getIndex != null && getMethod != null && !Array.newInstance(getIndex.getReturnType(),0).getClass().equals(getMethod.getReturnType())) {
+ throw new IntrospectionException("array methods do not match index methods.");
+ }
+
+ this.getMethod = getMethod;
+ this.setMethod = setMethod;
+ this.getIndex = getIndex;
+ this.setIndex = getIndex;
+ this.indexedPropertyType = getIndex != null ? getIndex.getReturnType() : setIndex.getParameterTypes()[1];
+ this.propertyType = getMethod != null ? getMethod.getReturnType() : (setMethod != null ? setMethod.getParameterTypes()[0] : Array.newInstance(this.indexedPropertyType,0).getClass());
+ }
+
+ public Class getIndexedPropertyType() {
+ return indexedPropertyType;
+ }
+
+ public Method getIndexedReadMethod() {
+ return getIndex;
+ }
+
+ public Method getIndexedWriteMethod() {
+ return setIndex;
+ }
+
+ private void findMethods(Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
+ try {
+ if(getIndexName != null) {
+ try {
+ Class[] getArgs = new Class[1];
+ getArgs[0] = java.lang.Integer.TYPE;
+ getIndex = beanClass.getMethod(getIndexName,getArgs);
+ indexedPropertyType = getIndex.getReturnType();
+ } catch(NoSuchMethodException E) {
+ }
+ }
+ if(getIndex != null) {
+ if(setIndexName != null) {
+ try {
+ Class[] setArgs = new Class[2];
+ setArgs[0] = java.lang.Integer.TYPE;
+ setArgs[1] = indexedPropertyType;
+ setIndex = beanClass.getMethod(setIndexName,setArgs);
+ if(!setIndex.getReturnType().equals(java.lang.Void.TYPE)) {
+ throw new IntrospectionException(setIndexName + " has non-void return type");
+ }
+ } catch(NoSuchMethodException E) {
+ }
+ }
+ } else if(setIndexName != null) {
+ Method[] m = beanClass.getMethods();
+ for(int i=0;i<m.length;i++) {
+ Method current = m[i];
+ if(current.getName().equals(setIndexName)
+ && current.getParameterTypes().length == 2
+ && (current.getParameterTypes()[0]).equals(java.lang.Integer.TYPE)
+ && current.getReturnType().equals(java.lang.Void.TYPE)) {
+ if(setIndex != null) {
+ throw new IntrospectionException("Multiple, different set methods found that fit the bill!");
+ } else {
+ setIndex = current;
+ indexedPropertyType = current.getParameterTypes()[1];
+ }
+ }
+ }
+ if(setIndex == null) {
+ throw new IntrospectionException("Cannot find get or set methods.");
+ }
+ } else {
+ throw new IntrospectionException("Cannot find get or set methods.");
+ }
+
+ Class arrayType = Array.newInstance(indexedPropertyType,0).getClass();
+
+ Class[] setArgs = new Class[1];
+ setArgs[0] = arrayType;
+ try {
+ setMethod = beanClass.getMethod(setMethodName,setArgs);
+ if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+ setMethod = null;
+ }
+ } catch(NoSuchMethodException E) {
+ }
+
+ Class[] getArgs = new Class[0];
+ try {
+ getMethod = beanClass.getMethod(getMethodName,getArgs);
+ if(!getMethod.getReturnType().equals(arrayType)) {
+ getMethod = null;
+ }
+ } catch(NoSuchMethodException E) {
+ }
+ } catch(SecurityException E) {
+ throw new IntrospectionException("SecurityException while trying to find methods.");
+ }
+ }
+}
diff --git a/libjava/java/beans/IntrospectionException.java b/libjava/java/beans/IntrospectionException.java
new file mode 100644
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 &lt;type&gt; getXXX(int)</CODE>
+ ** method, then XXX is a read-only indexed property of
+ ** type &lt;type&gt;. If there is a
+ ** <CODE>public void setXXX(int,&lt;type&gt;)</CODE>
+ ** method, then it is a read-write indexed property of
+ ** type &lt;type&gt;. There may also be a
+ ** <CODE>public &lt;type&gt;[] getXXX()</CODE> and a
+ ** <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ ** method as well.</CODE></LI>
+ ** <LI>If there is a
+ ** <CODE>public void setXXX(int,&lt;type&gt;)</CODE>
+ ** method, then it is a write-only indexed property of
+ ** type &lt;type&gt;. There may also be a
+ ** <CODE>public &lt;type&gt;[] getXXX()</CODE> and a
+ ** <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ ** method as well.</CODE></LI>
+ ** <LI>If there is a
+ ** <CODE>public &lt;type&gt; getXXX()</CODE> method,
+ ** then XXX is a read-only property of type
+ ** &lt;type&gt;. If there is a
+ ** <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ ** method, then it will be used for the property and
+ ** the property will be considered read-write.</LI>
+ ** <LI>If there is a
+ ** <CODE>public void setXXX(&lt;type&gt;)</CODE>
+ ** method, then as long as XXX is not already used as
+ ** the name of a property, XXX is assumed to be a
+ ** write-only property of type &lt;type&gt;.</LI>
+ ** <LI>In all of the above cases, if the setXXX() method
+ ** throws <CODE>PropertyVetoException</CODE>, then the
+ ** property in question is assumed to be constrained.
+ ** No properties are ever assumed to be bound
+ ** (<STRONG>Spec Note:</STRONG> this is not in the
+ ** spec, it just makes sense). See PropertyDescriptor
+ ** for a description of bound and constrained
+ ** properties.</LI>
+ ** </OL>
+ **
+ ** <STRONG>Events:</STRONG><P>
+ **
+ ** If there is a pair of methods,
+ ** <CODE>public void addXXX(&lt;type&gt;)</CODE> and
+ ** <CODE>public void removeXXX(&lt;type&gt;)</CODE>, where
+ ** &lt;type&gt; is a descendant of
+ ** <CODE>java.util.EventListener</CODE>, then the pair of
+ ** methods imply that this Bean will fire events to
+ ** listeners of type &lt;type&gt;.<P>
+ **
+ ** If the addXXX() method throws
+ ** <CODE>java.util.TooManyListenersException</CODE>, then
+ ** the event set is assumed to be <EM>unicast</EM>. See
+ ** EventSetDescriptor for a discussion of unicast event
+ ** sets.<P>
+ **
+ ** <STRONG>Spec Note:</STRONG> the spec seems to say that
+ ** the listener type's classname must be equal to the XXX
+ ** part of addXXX() and removeXXX(), but that is not the
+ ** case in Sun's implementation, so I am assuming it is
+ ** not the case in general.<P>
+ **
+ ** <STRONG>Methods:</STRONG><P>
+ **
+ ** Any public methods (including those which were used
+ ** for Properties or Events) are used as Methods.
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 29 Jul 1998
+ ** @see java.beans.BeanInfo
+ **/
+
+public class Introspector {
+ static String[] beanInfoSearchPath = {"gnu.java.beans.info", "sun.beans.infos"};
+ static Hashtable beanInfoCache = new Hashtable();
+
+ private Introspector() {}
+
+ /** Get the BeanInfo for class <CODE>beanClass</CODE>,
+ ** first by looking for explicit information, next by
+ ** using standard design patterns to determine
+ ** information about the class.
+ ** @param beanClass the class to get BeanInfo about.
+ ** @return the BeanInfo object representing the class.
+ **/
+ public static BeanInfo getBeanInfo(Class beanClass) throws IntrospectionException {
+ BeanInfo cachedInfo;
+ synchronized(beanClass) {
+ cachedInfo = (BeanInfo)beanInfoCache.get(beanClass);
+ if(cachedInfo != null) {
+ return cachedInfo;
+ }
+ cachedInfo = getBeanInfo(beanClass,null);
+ beanInfoCache.put(beanClass,cachedInfo);
+ return cachedInfo;
+ }
+ }
+
+ /** Get the BeanInfo for class <CODE>beanClass</CODE>,
+ ** first by looking for explicit information, next by
+ ** using standard design patterns to determine
+ ** information about the class. It crawls up the
+ ** inheritance tree until it hits <CODE>topClass</CODE>.
+ ** @param beanClass the Bean class.
+ ** @param stopClass the class to stop at.
+ ** @return the BeanInfo object representing the class.
+ **/
+ public static BeanInfo getBeanInfo(Class beanClass, Class stopClass) throws IntrospectionException {
+ ExplicitInfo explicit = new ExplicitInfo(beanClass,stopClass);
+
+ IntrospectionIncubator ii = new IntrospectionIncubator();
+ ii.setPropertyStopClass(explicit.propertyStopClass);
+ ii.setEventStopClass(explicit.eventStopClass);
+ ii.setMethodStopClass(explicit.methodStopClass);
+ ii.addMethods(beanClass.getMethods());
+
+ BeanInfoEmbryo currentInfo = ii.getBeanInfoEmbryo();
+ PropertyDescriptor[] p = explicit.explicitPropertyDescriptors;
+ if(p!=null) {
+ for(int i=0;i<p.length;i++) {
+ if(!currentInfo.hasProperty(p[i])) {
+ currentInfo.addProperty(p[i]);
+ }
+ }
+ if(explicit.defaultProperty != -1) {
+ currentInfo.setDefaultPropertyName(p[explicit.defaultProperty].getName());
+ }
+ }
+ EventSetDescriptor[] e = explicit.explicitEventSetDescriptors;
+ if(e!=null) {
+ for(int i=0;i<e.length;i++) {
+ if(!currentInfo.hasEvent(e[i])) {
+ currentInfo.addEvent(e[i]);
+ }
+ }
+ if(explicit.defaultEvent != -1) {
+ currentInfo.setDefaultEventName(e[explicit.defaultEvent].getName());
+ }
+ }
+ MethodDescriptor[] m = explicit.explicitMethodDescriptors;
+ if(m!=null) {
+ for(int i=0;i<m.length;i++) {
+ if(!currentInfo.hasMethod(m[i])) {
+ currentInfo.addMethod(m[i]);
+ }
+ }
+ }
+
+ if(explicit.explicitBeanDescriptor != null) {
+ currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,explicit.explicitBeanDescriptor.getCustomizerClass()));
+ } else {
+ currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,null));
+ }
+
+ currentInfo.setAdditionalBeanInfo(explicit.explicitBeanInfo);
+ currentInfo.setIcons(explicit.im);
+
+ return currentInfo.getBeanInfo();
+ }
+
+ /** Get the search path for BeanInfo classes.
+ ** @return the BeanInfo search path.
+ **/
+ public static String[] getBeanInfoSearchPath() {
+ return beanInfoSearchPath;
+ }
+
+ /** Set the search path for BeanInfo classes.
+ ** @param beanInfoSearchPath the new BeanInfo search
+ ** path.
+ **/
+ public static void setBeanInfoSearchPath(String[] beanInfoSearchPath) {
+ Introspector.beanInfoSearchPath = beanInfoSearchPath;
+ }
+
+ /** A helper method to convert a name to standard Java
+ ** naming conventions: anything with two capitals as the
+ ** first two letters remains the same, otherwise the
+ ** first letter is decapitalized. URL = URL, I = i,
+ ** MyMethod = myMethod.
+ ** @param name the name to decapitalize.
+ ** @return the decapitalized name.
+ **/
+ public static String decapitalize(String name) {
+ try {
+ if(!Character.isUpperCase(name.charAt(0))) {
+ return name;
+ } else {
+ try {
+ if(Character.isUpperCase(name.charAt(1))) {
+ return name;
+ } else {
+ char[] c = name.toCharArray();
+ c[0] = Character.toLowerCase(c[0]);
+ return new String(c);
+ }
+ } catch(StringIndexOutOfBoundsException E) {
+ char[] c = new char[1];
+ c[0] = Character.toLowerCase(name.charAt(0));
+ return new String(c);
+ }
+ }
+ } catch(StringIndexOutOfBoundsException E) {
+ return name;
+ } catch(NullPointerException E) {
+ return null;
+ }
+ }
+
+ static BeanInfo copyBeanInfo(BeanInfo b) {
+ java.awt.Image[] icons = new java.awt.Image[4];
+ for(int i=1;i<=4;i++) {
+ icons[i-1] = b.getIcon(i);
+ }
+ return new ExplicitBeanInfo(b.getBeanDescriptor(),b.getAdditionalBeanInfo(),
+ b.getPropertyDescriptors(),b.getDefaultPropertyIndex(),
+ b.getEventSetDescriptors(),b.getDefaultEventIndex(),
+ b.getMethodDescriptors(),icons);
+ }
+}
+
+class ExplicitInfo {
+ BeanDescriptor explicitBeanDescriptor;
+ BeanInfo[] explicitBeanInfo;
+
+ PropertyDescriptor[] explicitPropertyDescriptors;
+ EventSetDescriptor[] explicitEventSetDescriptors;
+ MethodDescriptor[] explicitMethodDescriptors;
+
+ int defaultProperty;
+ int defaultEvent;
+
+ java.awt.Image[] im = new java.awt.Image[4];
+
+ Class propertyStopClass;
+ Class eventStopClass;
+ Class methodStopClass;
+
+ ExplicitInfo(Class beanClass, Class stopClass) {
+ while(beanClass != null && !beanClass.equals(stopClass)) {
+ BeanInfo explicit = findExplicitBeanInfo(beanClass);
+ if(explicit != null) {
+ if(explicitBeanDescriptor == null) {
+ explicitBeanDescriptor = explicit.getBeanDescriptor();
+ }
+ if(explicitBeanInfo == null) {
+ explicitBeanInfo = explicit.getAdditionalBeanInfo();
+ }
+ if(explicitPropertyDescriptors == null) {
+ if(explicit.getPropertyDescriptors() != null) {
+ explicitPropertyDescriptors = explicit.getPropertyDescriptors();
+ defaultProperty = explicit.getDefaultPropertyIndex();
+ propertyStopClass = beanClass;
+ }
+ }
+ if(explicitEventSetDescriptors == null) {
+ if(explicit.getEventSetDescriptors() != null) {
+ explicitEventSetDescriptors = explicit.getEventSetDescriptors();
+ defaultEvent = explicit.getDefaultEventIndex();
+ eventStopClass = beanClass;
+ }
+ }
+ if(explicitMethodDescriptors == null) {
+ if(explicit.getMethodDescriptors() != null) {
+ explicitMethodDescriptors = explicit.getMethodDescriptors();
+ methodStopClass = beanClass;
+ }
+ }
+ if(im[0] == null
+ && im[1] == null
+ && im[2] == null
+ && im[3] == null) {
+ im[0] = explicit.getIcon(0);
+ im[1] = explicit.getIcon(1);
+ im[2] = explicit.getIcon(2);
+ im[3] = explicit.getIcon(3);
+ }
+ }
+ beanClass = beanClass.getSuperclass();
+ }
+ if(propertyStopClass == null) {
+ propertyStopClass = stopClass;
+ }
+ if(eventStopClass == null) {
+ eventStopClass = stopClass;
+ }
+ if(methodStopClass == null) {
+ methodStopClass = stopClass;
+ }
+ }
+
+ static Hashtable explicitBeanInfos = new Hashtable();
+ static Vector emptyBeanInfos = new Vector();
+
+ static BeanInfo findExplicitBeanInfo(Class beanClass) {
+ BeanInfo retval = (BeanInfo)explicitBeanInfos.get(beanClass);
+ if(retval != null) {
+ return retval;
+ } else if(emptyBeanInfos.indexOf(beanClass) != -1) {
+ return null;
+ } else {
+ retval = reallyFindExplicitBeanInfo(beanClass);
+ if(retval != null) {
+ explicitBeanInfos.put(beanClass,retval);
+ } else {
+ emptyBeanInfos.addElement(beanClass);
+ }
+ return retval;
+ }
+ }
+
+ static BeanInfo reallyFindExplicitBeanInfo(Class beanClass) {
+ try {
+ try {
+ return (BeanInfo)Class.forName(beanClass.getName()+"BeanInfo").newInstance();
+ } catch(ClassNotFoundException E) {
+ }
+ String newName = ClassHelper.getTruncatedClassName(beanClass) + "BeanInfo";
+ for(int i=0;i<Introspector.beanInfoSearchPath.length;i++) {
+ try {
+ if(Introspector.beanInfoSearchPath[i].equals("")) {
+ return (BeanInfo)Class.forName(newName).newInstance();
+ } else {
+ return (BeanInfo)Class.forName(Introspector.beanInfoSearchPath[i] + "." + newName).newInstance();
+ }
+ } catch(ClassNotFoundException E) {
+ }
+ }
+ } catch(IllegalAccessException E) {
+ } catch(InstantiationException E) {
+ }
+ return null;
+ }
+}
diff --git a/libjava/java/beans/MethodDescriptor.java b/libjava/java/beans/MethodDescriptor.java
new file mode 100644
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>&lt;propertyType&gt; &lt;getMethodName&gt;()</CODE></LI>
+ ** <LI>A set method must have signature
+ ** <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;)</CODE></LI>
+ ** <LI>Either method type may throw any exception.</LI>
+ ** <LI>Both methods must be public.</LI>
+ ** </OL>
+ **
+ ** @author John Keiser
+ ** @since JDK1.1
+ ** @version 1.1.0, 26 Jul 1998
+ **/
+
+public class PropertyDescriptor extends FeatureDescriptor {
+ Class propertyType;
+ Method getMethod;
+ Method setMethod;
+
+ Class propertyEditorClass;
+ boolean bound;
+ boolean constrained;
+
+ PropertyDescriptor(String name) {
+ setName(name);
+ }
+
+ /** Create a new PropertyDescriptor by introspection.
+ ** This form of constructor creates the PropertyDescriptor by
+ ** looking for a getter method named <CODE>get&lt;name&gt;()</CODE>
+ ** (or, optionally, if the property is boolean,
+ ** <CODE>is&lt;name&gt;()</CODE>) and
+ ** <CODE>set&lt;name&gt;()</CODE> in class
+ ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
+ ** first letter capitalized by the constructor.<P>
+ **
+ ** <B>Implementation note:</B> If there is a get method (or
+ ** boolean isXXX() method), then the return type of that method
+ ** is used to find the set method. If there is no get method,
+ ** then the set method is searched for exhaustively.<P>
+ **
+ ** <B>Spec note:</B>
+ ** If there is no get method and multiple set methods with
+ ** the same name and a single parameter (different type of course),
+ ** then an IntrospectionException is thrown. While Sun's spec
+ ** does not state this, it can make Bean behavior different on
+ ** different systems (since method order is not guaranteed) and as
+ ** such, can be treated as a bug in the spec. I am not aware of
+ ** whether Sun's implementation catches this.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param beanClass the class the get and set methods live in.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public PropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
+ setName(name);
+ String capitalized;
+ try {
+ capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+ } catch(StringIndexOutOfBoundsException e) {
+ capitalized = "";
+ }
+ findMethods(beanClass, "is" + capitalized, "get" + capitalized, "set" + capitalized);
+ }
+
+ /** Create a new PropertyDescriptor by introspection.
+ ** This form of constructor allows you to specify the
+ ** names of the get and set methods to search for.<P>
+ **
+ ** <B>Implementation note:</B> If there is a get method (or
+ ** boolean isXXX() method), then the return type of that method
+ ** is used to find the set method. If there is no get method,
+ ** then the set method is searched for exhaustively.<P>
+ **
+ ** <B>Spec note:</B>
+ ** If there is no get method and multiple set methods with
+ ** the same name and a single parameter (different type of course),
+ ** then an IntrospectionException is thrown. While Sun's spec
+ ** does not state this, it can make Bean behavior different on
+ ** different systems (since method order is not guaranteed) and as
+ ** such, can be treated as a bug in the spec. I am not aware of
+ ** whether Sun's implementation catches this.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param beanClass the class the get and set methods live in.
+ ** @param getMethodName the name of the get method.
+ ** @param setMethodName the name of the set method.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public PropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName) throws IntrospectionException {
+ setName(name);
+ findMethods(beanClass, getMethodName, null, setMethodName);
+ }
+
+ /** Create a new PropertyDescriptor using explicit Methods.
+ ** Note that the methods will be checked for conformance to standard
+ ** Property method rules, as described above at the top of this class.
+ **
+ ** @param name the programmatic name of the property, usually
+ ** starting with a lowercase letter (e.g. fooManChu
+ ** instead of FooManChu).
+ ** @param getMethod the get method.
+ ** @param setMethod the set method.
+ ** @exception IntrospectionException if the methods are not found or invalid.
+ **/
+ public PropertyDescriptor(String name, Method getMethod, Method setMethod) throws IntrospectionException {
+ setName(name);
+ if(getMethod != null && getMethod.getParameterTypes().length > 0) {
+ throw new IntrospectionException("get method has parameters");
+ }
+ if(setMethod != null && setMethod.getParameterTypes().length != 1) {
+ throw new IntrospectionException("set method does not have exactly one parameter");
+ }
+ if(getMethod != null && setMethod != null) {
+ if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
+ throw new IntrospectionException("set and get methods do not share the same type");
+ }
+ if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
+ && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
+ throw new IntrospectionException("set and get methods are not in the same class.");
+ }
+ }
+ this.getMethod = getMethod;
+ this.setMethod = setMethod;
+ if(getMethod != null) {
+ this.propertyType = getMethod.getReturnType();
+ } else {
+ this.propertyType = setMethod.getParameterTypes()[0];
+ }
+ }
+
+ /** Get the property type.
+ ** This is the type the get method returns and the set method
+ ** takes in.
+ **/
+ public Class getPropertyType() {
+ return propertyType;
+ }
+
+ /** Get the get method. Why they call it readMethod here and
+ ** get everywhere else is beyond me.
+ **/
+ public Method getReadMethod() {
+ return getMethod;
+ }
+
+ /** Get the set method. Why they call it writeMethod here and
+ ** set everywhere else is beyond me.
+ **/
+ public Method getWriteMethod() {
+ return setMethod;
+ }
+
+ /** Get whether the property is bound. Defaults to false. **/
+ public boolean isBound() {
+ return bound;
+ }
+
+ /** Set whether the property is bound.
+ ** As long as the the bean implements addPropertyChangeListener() and
+ ** removePropertyChangeListener(), setBound(true) may safely be called.<P>
+ ** If these things are not true, then the behavior of the system
+ ** will be undefined.<P>
+ **
+ ** When a property is bound, its set method is required to fire the
+ ** <CODE>PropertyChangeListener.propertyChange())</CODE event
+ ** after the value has changed.
+ ** @param bound whether the property is bound or not.
+ **/
+ public void setBound(boolean bound) {
+ this.bound = bound;
+ }
+
+ /** Get whether the property is constrained. Defaults to false. **/
+ public boolean isConstrained() {
+ return constrained;
+ }
+
+ /** Set whether the property is constrained.
+ ** If the set method throws <CODE>java.beans.PropertyVetoException</CODE>
+ ** (or subclass thereof) and the bean implements addVetoableChangeListener()
+ ** and removeVetoableChangeListener(), then setConstrained(true) may safely
+ ** be called. Otherwise, the system behavior is undefined.
+ ** <B>Spec note:</B> given those strict parameters, it would be nice if it
+ ** got set automatically by detection, but oh well.<P>
+ ** When a property is constrained, its set method is required to:<P>
+ ** <OL>
+ ** <LI>Fire the <CODE>VetoableChangeListener.vetoableChange()</CODE>
+ ** event notifying others of the change and allowing them a chance to
+ ** say it is a bad thing.</LI>
+ ** <LI>If any of the listeners throws a PropertyVetoException, then
+ ** it must fire another vetoableChange() event notifying the others
+ ** of a reversion to the old value (though, of course, the change
+ ** was never made). Then it rethrows the PropertyVetoException and
+ ** exits.</LI>
+ ** <LI>If all has gone well to this point, the value may be changed.</LI>
+ ** </OL>
+ ** @param constrained whether the property is constrained or not.
+ **/
+ public void setConstrained(boolean constrained) {
+ this.constrained = constrained;
+ }
+
+ /** Get the PropertyEditor class. Defaults to null. **/
+ public Class getPropertyEditorClass() {
+ return propertyEditorClass;
+ }
+
+ /** Set the PropertyEditor class. If the class does not implement
+ ** the PropertyEditor interface, you will likely get an exception
+ ** late in the game.
+ ** @param propertyEditorClass the PropertyEditor class for this class to use.
+ **/
+ public void setPropertyEditorClass(Class propertyEditorClass) {
+ this.propertyEditorClass = propertyEditorClass;
+ }
+
+ private void findMethods(Class beanClass, String getMethodName1, String getMethodName2, String setMethodName) throws IntrospectionException {
+ try {
+ if(getMethodName1 != null) {
+ try {
+ getMethod = beanClass.getMethod(getMethodName1, new Class[0]);
+ } catch(NoSuchMethodException E) {
+ }
+ if(getMethodName2 != null) {
+ if(getMethod != null && !getMethod.getReturnType().equals(java.lang.Boolean.TYPE)) {
+ // If the is() method exists but isn't boolean, we'll just go on and look for
+ // an ordinary get() method.
+ getMethod = null;
+ }
+
+ Method getMethod2;
+ try {
+ getMethod2 = beanClass.getMethod(getMethodName2, new Class[0]);
+ } catch(NoSuchMethodException E) {
+ getMethod2 = null;
+ }
+ if(getMethod2 != null) {
+ if(getMethod != null) {
+ if(!getMethod.getReturnType().equals(getMethod2.getReturnType())) {
+ throw new IntrospectionException("Both " + getMethodName1 + " and " + getMethodName2 + " exist, and have contradictory return types.");
+ }
+ } else {
+ getMethod = getMethod2;
+ }
+ }
+ }
+ }
+
+ if(getMethod != null) {
+ propertyType = getMethod.getReturnType();
+ if(setMethodName != null) {
+ Class[] setArgs = new Class[1];
+ setArgs[0] = propertyType;
+ try {
+ setMethod = beanClass.getMethod(setMethodName, setArgs);
+ if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) {
+ throw new IntrospectionException(setMethodName + " has non-void return type");
+ }
+ } catch(NoSuchMethodException E) {
+ }
+ }
+ } else if(setMethodName != null) {
+ Method[] m = beanClass.getMethods();
+ for(int i=0;i<m.length;i++) {
+ Method current = m[i];
+ if(current.getName().equals(setMethodName)
+ && current.getParameterTypes().length == 1
+ && current.getReturnType().equals(java.lang.Void.TYPE)) {
+ if(setMethod != null) {
+ throw new IntrospectionException("Multiple, different set methods found that fit the bill!");
+ } else {
+ setMethod = current;
+ propertyType = current.getParameterTypes()[0];
+ }
+ }
+ }
+ if(setMethod == null) {
+ throw new IntrospectionException("Cannot find get or set methods.");
+ }
+ } else {
+ throw new IntrospectionException("Cannot find get or set methods.");
+ }
+ } catch(SecurityException E) {
+ throw new IntrospectionException("SecurityException thrown on attempt to access methods.");
+ }
+ }
+}
diff --git a/libjava/java/beans/PropertyEditor.java b/libjava/java/beans/PropertyEditor.java
new file mode 100644
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);
+}