diff options
Diffstat (limited to 'libjava/java/beans')
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><Bean Class Name>BeanInfo</CODE> and place it in + ** the same package as the Bean, or in the bean info search path + ** (see Introspector for information on search paths).<P> + ** + ** A simple note about the way the Introspector interacts with + ** BeanInfo. Introspectors look at a Bean class and determine + ** if there is a BeanInfo class with it. If there is not a + ** BeanInfo class, it will behave as if the BeanInfo class + ** provided was a SimpleBeanInfo class (i.e. it will determine + ** all information automatically).<P>If there is a BeanInfo + ** class, then any methods that do *not* return null are + ** regarded as providing definitive information about the class + ** and all of its superclasses for those information types. + ** Even if a parent BeanInfo class explicitly returns that + ** information, it will not be used. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 28 Jul 1998 + **/ + +public interface BeanInfo { + /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/ + public static int ICON_COLOR_16x16 = 1; + /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/ + public static int ICON_COLOR_32x32 = 2; + /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/ + public static int ICON_MONO_16x16 = 3; + /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/ + public static int ICON_MONO_32x32 = 4; + + /** Get the general description of this Bean type. + ** @return the BeanDescriptor for the Bean, or null if + ** the BeanDescriptor should be obtained by + ** Introspection. + **/ + public abstract BeanDescriptor getBeanDescriptor(); + + /** Get the events this Bean type fires. + ** @return the EventDescriptors representing events this + ** Bean fires. Returns <CODE>null</CODE> if the + ** events are to be acquired by Introspection. + **/ + public abstract EventSetDescriptor[] getEventSetDescriptors(); + + /** Get the "default" event, basically the one a RAD tool + ** user is most likely to select. + ** @return the index into the getEventSetDescriptors() + ** that the user is most likely to use. Returns + ** <CODE>-1</CODE> if there is no default event. + **/ + public abstract int getDefaultEventIndex(); + + /** Get the properties (get/set method pairs) this Bean + ** type supports. + ** @return the PropertyDescriptors representing the + ** properties this Bean type supports. + ** Returns <CODE>null</CODE> if the properties + ** are to be obtained by Introspection. + **/ + public abstract PropertyDescriptor[] getPropertyDescriptors(); + + /** Get the "default" property, basically the one a RAD + ** tool user is most likely to select. + ** @return the index into the getPropertyDescriptors() + ** that the user is most likely to use. Returns + ** <CODE>-1</CODE> if there is no default event. + **/ + public abstract int getDefaultPropertyIndex(); + + /** Get the methods this Bean type supports. + ** @return the MethodDescriptors representing the + ** methods this Bean type supports. Returns + ** <CODE>null</CODE> if the methods are to be + ** obtained by Introspection. + **/ + public abstract MethodDescriptor[] getMethodDescriptors(); + + /** Get additional BeanInfos representing this Bean. + ** In this version of JavaBeans, this method is used so + ** that space and time can be saved by reading a BeanInfo + ** for each class in the hierarchy (super, super(super), + ** and so on).<P> + ** + ** The order of precedence when two pieces of BeanInfo + ** conflict (such as two PropertyDescriptors that have + ** the same name), in order from highest precedence to + ** lowest, is: + ** <OL> + ** <LI>This BeanInfo object.</LI> + ** <LI><CODE>getAdditionalBeanInfo()[getAdditionalBeanInfo().length]</CODE></LI> + ** <LI> ... </LI> + ** <LI><CODE>getAdditionalBeanInfo()[1]</CODE></LI> + ** <LI><CODE>getAdditionalBeanInfo()[0]</CODE></LI> + ** </OL><P> + ** + ** <STRONG>Spec Note:</STRONG> It is possible that + ** returning <CODE>null</CODE> from this method could + ** stop Introspection in its tracks, but it is unclear + ** from the spec whether this is the case. + ** + ** @return additional BeanInfos representing this Bean. + ** <CODE>null</CODE> may be returned (see Spec + ** Note, above). + **/ + public abstract BeanInfo[] getAdditionalBeanInfo(); + + /** Get a visual icon for this Bean. + ** A Bean does not have to support icons, and if it does + ** support icons, it does not have to support every single + ** type. Sun recommends that if you only support one + ** type, you support 16x16 color. Sun also notes that you + ** should try to use a type (like GIF) that allows for + ** transparent pixels, so that the background of the RAD + ** tool can show through.<P> + ** + ** <STRONG>Spec Note:</STRONG> If you do not support the + ** type of icon that is being asked for, but you do + ** support another type, it is unclear whether you should + ** return the other type or not. I would presume not. + ** + ** @param iconType the type of icon to get (see the + ** ICON_* constants in this class). + ** @return the icon, or null if that type of icon is + ** unsupported by this Bean. + **/ + public abstract java.awt.Image getIcon(int iconType); +} diff --git a/libjava/java/beans/Beans.java b/libjava/java/beans/Beans.java new file mode 100644 index 0000000..08e5623 --- /dev/null +++ b/libjava/java/beans/Beans.java @@ -0,0 +1,199 @@ +/* java.beans.Beans + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import java.io.*; +// import java.applet.*; +import gnu.java.io.*; + +/** + * <code>Beans</code> provides some helper methods that allow the basic operations of Bean-ness. + * + * @author John Keiser + * @since JDK1.1 + * @version 1.1.0, 29 Jul 1998 + * + */ +public class Beans { + static boolean designTime = false; + static boolean guiAvailable = true; + + + /** + * Once again, we have a java.beans class with only + * static methods that can be instantiated. When + * will the madness end? :) + */ + public Beans() { + } + + /** + * Allows you to instantiate a Bean. This method takes + * a ClassLoader from which to read the Bean and the + * name of the Bean.<P> + * + * The Bean name should be a dotted name, like a class. + * It can represent several things. Beans will search + * for the Bean using the name like this:<P> + * <OL> + * <LI>Searches for a serialized instance of the Bean + * using getResource(), mangling the Bean name by + * replacing the dots with slashes and appending .ser + * (for example, gnu.beans.BlahDeBlah would cause + * Beans to search for gnu/beans/BlahDeBlah.ser using + * getResource()).</LI> + * <LI>Searches for the Bean class using the beanName, + * and then instantiates it with the no-arg constructor. + * At that point, if it is an Applet, it provides it + * with AppletContext and AppletStub, and then calls + * init().</LI> + * </OL> + * @param cl the ClassLoader to use, or <CODE>null</CODE> + * to use the default ClassLoader. + * @param beanName the name of the Bean. + * @return the Bean. + * @XXX + */ + public static Object instantiate(ClassLoader cl, String beanName) throws IOException, ClassNotFoundException { + Object bean; + + InputStream serStream; + if(cl == null) { + serStream = ClassLoader.getSystemResourceAsStream(beanName.replace('.','/')+".ser"); + } else { + serStream = cl.getResourceAsStream(beanName.replace('.','/')+".ser"); + } + if(serStream != null) { + if(cl == null) { + ObjectInputStream ois = new ObjectInputStream(serStream); + bean = ois.readObject(); + } else { + ClassLoaderObjectInputStream ois = new ClassLoaderObjectInputStream(serStream, cl); + bean = ois.readObject(); + } + } else if(cl == null) { + Class beanClass = Class.forName(beanName); + try { + bean = beanClass.newInstance(); + } catch(IllegalAccessException E) { + bean = null; + } catch(InstantiationException E) { + bean = null; + } + } else { + Class beanClass = cl.loadClass(beanName); + try { + bean = beanClass.newInstance(); + } catch(IllegalAccessException E) { + bean = null; + } catch(InstantiationException E) { + bean = null; + } + } + +/* FIXME - Turned off since java.applet doesn't exist for libgcj. + * FIXME if(bean instanceof Applet) { + * FIXME Applet a = (Applet)bean; + * FIXME //a.setAppletContext(???); + * FIXME //a.setStub(???); + * FIXME if(serStream == null) { + * FIXME a.init(); + * FIXME } + * FIXME } + * FIXME ********************************************************/ + + return bean; + } + + /** + * Get the Bean as a different class type. + * This should be used instead of casting to get a new + * type view of a Bean, because in the future there may + * be new types of Bean, even Beans spanning multiple + * Objects. + * @param bean the Bean to cast. + * @param newClass the Class to cast it to. + * @return the Bean as a new view, or if the operation + * could not be performed, the Bean itself. + */ + public static Object getInstanceOf(Object bean, Class newClass) { + return bean; + } + + /** + * Determine whether the Bean can be cast to a different + * class type. + * This should be used instead of instanceof to determine + * a Bean's castability, because in the future there may + * be new types of Bean, even Beans spanning multiple + * Objects. + * @param bean the Bean to cast. + * @param newClass the Class to cast it to. + * @return whether the Bean can be cast to the class type + * in question. + */ + public static boolean isInstanceOf(Object bean, Class newBeanClass) { + return newBeanClass.isInstance(bean); + } + + /** + * Find out whether the GUI is available to use. + * Defaults to true. + * @return whether the GUI is available to use. + */ + public static boolean isGuiAvailable() { + return guiAvailable; + } + + /** + * Find out whether it is design time. Design time means + * we are in a RAD tool. + * Defaults to false. + * @return whether it is design time. + */ + public static boolean isDesignTime() { + return designTime; + } + + /** + * Set whether the GUI is available to use. + * @param guiAvailable whether the GUI is available to use. + */ + public static void setGuiAvailable(boolean guiAvailable) throws SecurityException { + Beans.guiAvailable = guiAvailable; + } + + /** + * Set whether it is design time. Design time means we + * are in a RAD tool. + * @param designTime whether it is design time. + */ + public static void setDesignTime(boolean designTime) throws SecurityException { + Beans.designTime = designTime; + } +} diff --git a/libjava/java/beans/Customizer.java b/libjava/java/beans/Customizer.java new file mode 100644 index 0000000..1fecd4f --- /dev/null +++ b/libjava/java/beans/Customizer.java @@ -0,0 +1,75 @@ +/* java.beans.Customizer + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + ** You may explicitly provide a Customizer for your Bean + ** class, which allows you complete control of the editing + ** of the Bean.<P> + ** + ** A Customizer is meant to be embedded in an RAD tool, + ** and thus must be a descendant of <CODE>java.awt.Component</CODE>.<P> + ** + ** It must also have a constructor with no arguments. This + ** is the constructor that will be called by the RAD tool to + ** instantiate the Customizer.<P> + ** + ** Over its lifetime, an instance of a Customizer will only + ** customize one single Bean. A new instance of the + ** Customizer will be instantiated to edit any other Beans.<P> + ** + ** The Customizer is responsible for notifying its + ** PropertyChangeListeners of any changes that are made, + ** according to the rules of PropertyChangeListeners (i.e. + ** notify the clients <EM>after</EM> the property has + ** changed). + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 29 Jul 1998 + ** @see java.beans.BeanDescriptor.getCustomizerClass() + **/ + +public interface Customizer { + /** Set the object to Customize. This will always be a + ** Bean that had a BeanDescriptor indicating this + ** Customizer. + ** @param bean the Bean to customize. + **/ + public abstract void setObject(Object bean); + + /** Add a PropertyChangeListener. + ** @param l the PropertyChangeListener to add. + **/ + public abstract void addPropertyChangeListener(PropertyChangeListener l); + + /** Remove a PropertyChangeListener. + ** @param l the PropertyChangeListener to remove. + **/ + public abstract void removePropertyChangeListener(PropertyChangeListener l); +} diff --git a/libjava/java/beans/DesignMode.java b/libjava/java/beans/DesignMode.java new file mode 100644 index 0000000..b7782f9 --- /dev/null +++ b/libjava/java/beans/DesignMode.java @@ -0,0 +1,82 @@ +/* java.beans.DesignMode + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + * <code>BeanContextChild</code> implementors implement this to get information about whether they are in a design time or runtime environment. + * The reason this is restricted to <code>BeanContextChild</code>ren is that + * only things in the <code>BeanContext</code> hierarchy are given this + * information in the first place. + * + * @author John Keiser + * @since JDK1.2 + * @see java.beans.beancontext.BeanContextChild + */ + +public interface DesignMode { + /** + * Use this name when firing <code>PropertyChangeEvent</code>s from your Bean. + * @fixme Check whether PROPERTYNAME is set to same value as Sun. + */ + public static final String PROPERTYNAME = "designTime"; + + /** + * The environment will call this method on your + * <code>BeanContextChild</code> when it is registered in a parent + * <code>BeanContext</code> or when behavior needs to switch from + * design time to runtime behavior (or vice versa). + * <P> + * + * <code>BeanContext</code>s are required to fire + * <code>PropertyChangeEvent</code>s when properties change. + * <code>designTime</code> is a property, and therefore when you + * implement <code>setDesignTime()</code>, you need to fire a + * <code>PropertyChangeEvent</code> with the old value, the new + * value and using <code>PROPERTYNAME</code> as the property name. + * + * @param designTime the new value of design time, + * <code>true</code> if it is design time, + * <code>false</code> if it is runtime. + * + * @fixme I'm frankly not really sure whether it's the case that + * the BeanContext can <em>change</em> the status of the Bean from + * design time to runtime. But it appears that it may be so. + * + * @see java.util.PropertyChangeEvent + * @see java.beans.beancontext.BeanContext + * @see #PROPERTYNAME + */ + public void setDesignTime(boolean designTime); + + /** + * This method should tell whether it is design time or runtime. + * @return <code>true</code> if design time, <code>false</code> if + * runtime. + */ + public boolean isDesignTime(); +} diff --git a/libjava/java/beans/EventSetDescriptor.java b/libjava/java/beans/EventSetDescriptor.java new file mode 100644 index 0000000..c0840fe --- /dev/null +++ b/libjava/java/beans/EventSetDescriptor.java @@ -0,0 +1,429 @@ +/* java.beans.EventSetDescriptor + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import java.util.*; +import java.lang.reflect.*; +import gnu.java.lang.*; + +/** + ** EventSetDescriptor describes the hookup between an event source + ** class and an event listener class. + ** + ** EventSets have several attributes: the listener class, the events + ** that can be fired to the listener (methods in the listener class), and + ** an add and remove listener method from the event firer's class.<P> + ** + ** The methods have these constraints on them:<P> + ** <UL> + ** <LI>event firing methods: must have <CODE>void</CODE> return value. Any + ** parameters and exceptions are allowed. May be public, protected or + ** package-protected. (Don't ask me why that is, I'm just following the spec. + ** The only place it is even mentioned is in the Java Beans white paper, and + ** there it is only implied.)</LI> + ** <LI>add listener method: must have <CODE>void</CODE> return value. Must + ** take exactly one argument, of the listener class's type. May fire either + ** zero exceptions, or one exception of type <CODE>java.util.TooManyListenersException</CODE>. + ** Must be public.</LI> + ** <LI>remove listener method: must have <CODE>void</CODE> return value. + ** Must take exactly one argument, of the listener class's type. May not + ** fire any exceptions. Must be public.</LI> + ** </UL> + ** + ** A final constraint is that event listener classes must extend from EventListener.<P> + ** + ** There are also various design patterns associated with some of the methods + ** of construction. Those are explained in more detail in the appropriate + ** constructors.<P> + ** + ** <STRONG>Documentation Convention:</STRONG> for proper + ** Internalization of Beans inside an RAD tool, sometimes there + ** are two names for a property or method: a programmatic, or + ** locale-independent name, which can be used anywhere, and a + ** localized, display name, for ease of use. In the + ** documentation I will specify different String values as + ** either <EM>programmatic</EM> or <EM>localized</EM> to + ** make this distinction clear. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 31 May 1998 + **/ + +public class EventSetDescriptor extends FeatureDescriptor { + private Method addListenerMethod; + private Method removeListenerMethod; + private Class listenerType; + private MethodDescriptor[] listenerMethodDescriptors; + private Method[] listenerMethods; + + private boolean unicast; + private boolean inDefaultEventSet = true; + + /** Create a new EventSetDescriptor. + ** This version of the constructor enforces the rules imposed on the methods + ** described at the top of this class, as well as searching for:<P> + ** <OL> + ** <LI>The event-firing method must be non-private with signature + ** <CODE>void <listenerMethodName>(<eventSetName>Event)</CODE> + ** (where <CODE><eventSetName></CODE> has its first character capitalized + ** by the constructor and the Event is a descendant of + ** <CODE>java.util.EventObject</CODE>) in class <CODE>listenerType</CODE> + ** (any exceptions may be thrown). + ** <B>Implementation note:</B> Note that there could conceivably be multiple + ** methods with this type of signature (example: java.util.MouseEvent vs. + ** my.very.own.MouseEvent). In this implementation, all methods fitting the + ** description will be put into the <CODE>EventSetDescriptor</CODE>, even + ** though the spec says only one should be chosen (they probably weren't thinking as + ** pathologically as I was). I don't like arbitrarily choosing things. + ** If your class has only one such signature, as most do, you'll have no problems.</LI> + ** <LI>The add and remove methods must be public and named + ** <CODE>void add<eventSetName>Listener(<listenerType>)</CODE> and + ** <CODE>void remove<eventSetName>Listener(<listenerType>)</CODE> in + ** in class <CODE>eventSourceClass</CODE>, where + ** <CODE><eventSetName></CODE> will have its first letter capitalized. + ** Standard exception rules (see class description) apply.</LI> + ** </OL> + ** @param eventSourceClass the class containing the add/remove listener methods. + ** @param eventSetName the programmatic name of the event set, generally starting + ** with a lowercase letter (i.e. fooManChu instead of FooManChu). This will be used + ** to generate the name of the event object as well as the names of the add and + ** remove methods. + ** @param listenerType the class containing the event firing method. + ** @param listenerMethodName the name of the event firing method. + ** @exception IntrospectionException if listenerType is not an EventListener, + ** or if methods are not found or are invalid. + **/ + public EventSetDescriptor(Class eventSourceClass, + String eventSetName, + Class listenerType, + String listenerMethodName) throws IntrospectionException { + setName(eventSetName); + if(!java.util.EventListener.class.isAssignableFrom(listenerType)) { + throw new IntrospectionException("Listener type is not an EventListener."); + } + + String[] names = new String[1]; + names[0] = listenerMethodName; + + try { + eventSetName = Character.toUpperCase(eventSetName.charAt(0)) + eventSetName.substring(1); + } catch(StringIndexOutOfBoundsException e) { + eventSetName = ""; + } + + findMethods(eventSourceClass,listenerType,names,"add"+eventSetName+"Listener","remove"+eventSetName+"Listener",eventSetName+"Event"); + this.listenerType = listenerType; + checkAddListenerUnicast(); + if(this.removeListenerMethod.getExceptionTypes().length > 0) { + throw new IntrospectionException("Listener remove method throws exceptions."); + } + } + + /** Create a new EventSetDescriptor. + ** This form of the constructor allows you to specify the names of the methods and adds + ** no new constraints on top of the rules already described at the top of the class.<P> + ** + ** @param eventSourceClass the class containing the add and remove listener methods. + ** @param eventSetName the programmatic name of the event set, generally starting + ** with a lowercase letter (i.e. fooManChu instead of FooManChu). + ** @param listenerType the class containing the event firing methods. + ** @param listenerMethodNames the names of the even firing methods. + ** @param addListenerMethodName the name of the add listener method. + ** @param removeListenerMethodName the name of the remove listener method. + ** @exception IntrospectionException if listenerType is not an EventListener + ** or if methods are not found or are invalid. + **/ + public EventSetDescriptor(Class eventSourceClass, + String eventSetName, + Class listenerType, + String[] listenerMethodNames, + String addListenerMethodName, + String removeListenerMethodName) throws IntrospectionException { + setName(eventSetName); + if(!java.util.EventListener.class.isAssignableFrom(listenerType)) { + throw new IntrospectionException("Listener type is not an EventListener."); + } + + findMethods(eventSourceClass,listenerType,listenerMethodNames,addListenerMethodName,removeListenerMethodName,null); + this.listenerType = listenerType; + checkAddListenerUnicast(); + if(this.removeListenerMethod.getExceptionTypes().length > 0) { + throw new IntrospectionException("Listener remove method throws exceptions."); + } + } + + /** Create a new EventSetDescriptor. + ** This form of constructor allows you to explicitly say which methods do what, and + ** no reflection is done by the EventSetDescriptor. The methods are, however, + ** checked to ensure that they follow the rules set forth at the top of the class. + ** @param eventSetName the programmatic name of the event set, generally starting + ** with a lowercase letter (i.e. fooManChu instead of FooManChu). + ** @param listenerType the class containing the listenerMethods. + ** @param listenerMethods the event firing methods. + ** @param addListenerMethod the add listener method. + ** @param removeListenerMethod the remove listener method. + ** @exception IntrospectionException if the listenerType is not an EventListener, + ** or any of the methods are invalid. + **/ + public EventSetDescriptor(String eventSetName, + Class listenerType, + Method[] listenerMethods, + Method addListenerMethod, + Method removeListenerMethod) throws IntrospectionException { + setName(eventSetName); + if(!java.util.EventListener.class.isAssignableFrom(listenerType)) { + throw new IntrospectionException("Listener type is not an EventListener."); + } + + this.listenerMethods = listenerMethods; + this.addListenerMethod = addListenerMethod; + this.removeListenerMethod = removeListenerMethod; + this.listenerType = listenerType; + checkMethods(); + checkAddListenerUnicast(); + if(this.removeListenerMethod.getExceptionTypes().length > 0) { + throw new IntrospectionException("Listener remove method throws exceptions."); + } + } + + /** Create a new EventSetDescriptor. + ** This form of constructor allows you to explicitly say which methods do what, and + ** no reflection is done by the EventSetDescriptor. The methods are, however, + ** checked to ensure that they follow the rules set forth at the top of the class. + ** @param eventSetName the programmatic name of the event set, generally starting + ** with a lowercase letter (i.e. fooManChu instead of FooManChu). + ** @param listenerType the class containing the listenerMethods. + ** @param listenerMethodDescriptors the event firing methods. + ** @param addListenerMethod the add listener method. + ** @param removeListenerMethod the remove listener method. + ** @exception IntrospectionException if the listenerType is not an EventListener, + ** or any of the methods are invalid. + **/ + public EventSetDescriptor(String eventSetName, + Class listenerType, + MethodDescriptor[] listenerMethodDescriptors, + Method addListenerMethod, + Method removeListenerMethod) throws IntrospectionException { + setName(eventSetName); + if(!java.util.EventListener.class.isAssignableFrom(listenerType)) { + throw new IntrospectionException("Listener type is not an EventListener."); + } + + this.listenerMethodDescriptors = listenerMethodDescriptors; + this.listenerMethods = new Method[listenerMethodDescriptors.length]; + for(int i=0;i<this.listenerMethodDescriptors.length;i++) { + this.listenerMethods[i] = this.listenerMethodDescriptors[i].getMethod(); + } + + this.addListenerMethod = addListenerMethod; + this.removeListenerMethod = removeListenerMethod; + this.listenerType = listenerType; + checkMethods(); + checkAddListenerUnicast(); + if(this.removeListenerMethod.getExceptionTypes().length > 0) { + throw new IntrospectionException("Listener remove method throws exceptions."); + } + } + + /** Get the class that contains the event firing methods. **/ + public Class getListenerType() { + return listenerType; + } + + /** Get the event firing methods. **/ + public Method[] getListenerMethods() { + return listenerMethods; + } + + /** Get the event firing methods as MethodDescriptors. **/ + public MethodDescriptor[] getListenerMethodDescriptors() { + if(listenerMethodDescriptors == null) { + listenerMethodDescriptors = new MethodDescriptor[listenerMethods.length]; + for(int i=0;i<listenerMethods.length;i++) { + listenerMethodDescriptors[i] = new MethodDescriptor(listenerMethods[i]); + } + } + return listenerMethodDescriptors; + } + + /** Get the add listener method. **/ + public Method getAddListenerMethod() { + return addListenerMethod; + } + + /** Get the remove listener method. **/ + public Method getRemoveListenerMethod() { + return removeListenerMethod; + } + + /** Set whether or not multiple listeners may be added. + ** @param unicast whether or not multiple listeners may be added. + **/ + public void setUnicast(boolean unicast) { + this.unicast = unicast; + } + + /** Get whether or not multiple listeners may be added. (Defaults to false.) **/ + public boolean isUnicast() { + return unicast; + } + + /** Set whether or not this is in the default event set. + ** @param inDefaultEventSet whether this is in the default event set. + **/ + public void setInDefaultEventSet(boolean inDefaultEventSet) { + this.inDefaultEventSet = inDefaultEventSet; + } + + /** Get whether or not this is in the default event set. (Defaults to true.)**/ + public boolean isInDefaultEventSet() { + return inDefaultEventSet; + } + + private void checkAddListenerUnicast() throws IntrospectionException { + Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes(); + if(addListenerExceptions.length > 1) { + throw new IntrospectionException("Listener add method throws too many exceptions."); + } else if(addListenerExceptions.length == 1 + && !java.util.TooManyListenersException.class.isAssignableFrom(addListenerExceptions[0])) { + throw new IntrospectionException("Listener add method throws too many exceptions."); + } + } + + private void checkMethods() throws IntrospectionException { + if(!addListenerMethod.getDeclaringClass().isAssignableFrom(removeListenerMethod.getDeclaringClass()) + && !removeListenerMethod.getDeclaringClass().isAssignableFrom(addListenerMethod.getDeclaringClass())) { + throw new IntrospectionException("add and remove listener methods do not come from the same class. This is bad."); + } + if(!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE) + || addListenerMethod.getParameterTypes().length != 1 + || !listenerType.equals(addListenerMethod.getParameterTypes()[0]) + || !Modifier.isPublic(addListenerMethod.getModifiers())) { + throw new IntrospectionException("Add Listener Method invalid."); + } + if(!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE) + || removeListenerMethod.getParameterTypes().length != 1 + || !listenerType.equals(removeListenerMethod.getParameterTypes()[0]) + || removeListenerMethod.getExceptionTypes().length > 0 + || !Modifier.isPublic(removeListenerMethod.getModifiers())) { + throw new IntrospectionException("Remove Listener Method invalid."); + } + + for(int i=0;i<listenerMethods.length;i++) { + if(!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE) + || Modifier.isPrivate(listenerMethods[i].getModifiers())) { + throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " non-void or private."); + } + if(!listenerMethods[i].getDeclaringClass().isAssignableFrom(listenerType)) { + throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " not from class " + listenerType.getName()); + } + } + } + + private void findMethods(Class eventSourceClass, + Class listenerType, + String listenerMethodNames[], + String addListenerMethodName, + String removeListenerMethodName, + String absurdEventClassCheckName) throws IntrospectionException { + + /* Find add listener method and remove listener method. */ + Class[] listenerArgList = new Class[1]; + listenerArgList[0] = listenerType; + try { + this.addListenerMethod = eventSourceClass.getMethod(addListenerMethodName,listenerArgList); + } catch(SecurityException E) { + throw new IntrospectionException("SecurityException trying to access method " + addListenerMethodName + "."); + } catch(NoSuchMethodException E) { + throw new IntrospectionException("Could not find method " + addListenerMethodName + "."); + } + + if(this.addListenerMethod == null || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) { + throw new IntrospectionException("Add listener method does not exist, is not public, or is not void."); + } + + try { + this.removeListenerMethod = eventSourceClass.getMethod(removeListenerMethodName,listenerArgList); + } catch(SecurityException E) { + throw new IntrospectionException("SecurityException trying to access method " + removeListenerMethodName + "."); + } catch(NoSuchMethodException E) { + throw new IntrospectionException("Could not find method " + removeListenerMethodName + "."); + } + if(this.removeListenerMethod == null || !this.removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) { + throw new IntrospectionException("Remove listener method does not exist, is not public, or is not void."); + } + + /* Find the listener methods. */ + Method[] methods; + try { + methods = ClassHelper.getAllMethods(listenerType); + } catch(SecurityException E) { + throw new IntrospectionException("Security: You cannot access fields in this class."); + } + + Vector chosenMethods = new Vector(); + boolean[] listenerMethodFound = new boolean[listenerMethodNames.length]; + for(int i=0;i<methods.length;i++) { + if(Modifier.isPrivate(methods[i].getModifiers())) { + continue; + } + Method currentMethod = methods[i]; + Class retval = currentMethod.getReturnType(); + if(retval.equals(java.lang.Void.TYPE)) { + for(int j=0;j<listenerMethodNames.length;j++) { + if(currentMethod.getName().equals(listenerMethodNames[j]) + && (absurdEventClassCheckName == null + || (currentMethod.getParameterTypes().length == 1 + && ((currentMethod.getParameterTypes()[0]).getName().equals(absurdEventClassCheckName) + || (currentMethod.getParameterTypes()[0]).getName().endsWith("."+absurdEventClassCheckName) + ) + ) + ) + ) { + chosenMethods.addElement(currentMethod); + listenerMethodFound[j] = true; + } + } + } + } + + /* Make sure we found all the methods we were looking for. */ + for(int i=0;i<listenerMethodFound.length;i++) { + if(!listenerMethodFound[i]) { + throw new IntrospectionException("Could not find event method " + listenerMethodNames[i]); + } + } + + /* Now that we've chosen the listener methods we want, store them. */ + this.listenerMethods = new Method[chosenMethods.size()]; + for(int i=0;i<chosenMethods.size();i++) { + this.listenerMethods[i] = (Method)chosenMethods.elementAt(i); + } + } +} diff --git a/libjava/java/beans/FeatureDescriptor.java b/libjava/java/beans/FeatureDescriptor.java new file mode 100644 index 0000000..102a3a3 --- /dev/null +++ b/libjava/java/beans/FeatureDescriptor.java @@ -0,0 +1,155 @@ +/* java.beans.FeatureDescriptor + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import java.util.*; + +/** + ** FeatureDescriptor is the common superclass for all JavaBeans Descriptor classes. + ** JavaBeans descriptors are abstract descriptors of properties, + ** events, methods, beans, etc.<P> + ** + ** <STRONG>Documentation Convention:</STRONG> for proper + ** Internalization of Beans inside an RAD tool, sometimes there + ** are two names for a property or method: a programmatic, or + ** locale-independent name, which can be used anywhere, and a + ** localized, display name, for ease of use. In the + ** documentation I will specify different String values as + ** either <EM>programmatic</EM> or <EM>localized</EM> to + ** make this distinction clear. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 31 May 1998 + **/ + +public class FeatureDescriptor { + String name; + String displayName; + String shortDescription; + boolean expert; + boolean hidden; + + Hashtable valueHash; + + /** Instantiate this FeatureDescriptor with appropriate default values.**/ + public FeatureDescriptor() { + valueHash = new Hashtable(); + } + + /** Get the programmatic name of this feature. **/ + public String getName() { + return name; + } + + /** Set the programmatic name of this feature. + ** @param name the new name for this feature. + **/ + public void setName(String name) { + this.name = name; + } + + /** Get the localized (display) name of this feature. **/ + public String getDisplayName() { + return displayName; + } + + /** Set the localized (display) name of this feature. + ** @param displayName the new display name for this feature. + **/ + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** Get the localized short description for this feature. **/ + public String getShortDescription() { + return shortDescription; + } + + /** Set the localized short description for this feature. + ** @param shortDescription the new short description for this feature. + **/ + public void setShortDescription(String shortDescription) { + this.shortDescription = shortDescription; + } + + /** Indicates whether this feature is for expert use only. + ** @return true if for use by experts only, or false if anyone can use it. + **/ + public boolean isExpert() { + return expert; + } + + /** Set whether this feature is for expert use only. + ** @param expert true if for use by experts only, or false if anyone can use it. + **/ + public void setExpert(boolean expert) { + this.expert = expert; + } + + /** Indicates whether this feature is for use by tools only. + ** If it is for use by tools only, then it should not be displayed. + ** @return true if tools only should use it, or false if anyone can see it. + **/ + public boolean isHidden() { + return hidden; + } + + /** Set whether this feature is for use by tools only. + ** If it is for use by tools only, then it should not be displayed. + ** @param hidden true if tools only should use it, or false if anyone can see it. + **/ + public void setHidden(boolean hidden) { + this.hidden = hidden; + } + + + /** Get an arbitrary value set with setValue(). + ** @param name the programmatic name of the key. + ** @return the value associated with this name, or null if there is none. + **/ + public Object getValue(String name) { + return valueHash.get(name); + } + + /** Set an arbitrary string-value pair with this feature. + ** @param name the programmatic name of the key. + ** @param value the value to associate with the name. + **/ + public void setValue(String name, Object value) { + valueHash.put(name, value); + } + + /** Get a list of the programmatic key names set with setValue(). + ** @return an Enumerator over all the programmatic key names associated + ** with this feature. + **/ + public Enumeration attributeNames() { + return valueHash.keys(); + } +} diff --git a/libjava/java/beans/IndexedPropertyDescriptor.java b/libjava/java/beans/IndexedPropertyDescriptor.java new file mode 100644 index 0000000..daf8441 --- /dev/null +++ b/libjava/java/beans/IndexedPropertyDescriptor.java @@ -0,0 +1,296 @@ +/* java.beans.IndexedPropertyDescriptor + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import java.util.*; +import java.lang.reflect.*; + +/** + ** IndexedPropertyDescriptor describes information about a JavaBean + ** indexed property, by which we mean an array-like property that + ** has been exposed via a pair of get and set methods and another + ** pair that allows you to get to the property by an index.<P> + ** + ** An example property would have four methods like this:<P> + ** <CODE>FooBar[] getFoo()</CODE><BR> + ** <CODE>void setFoo(FooBar[])</CODE><BR> + ** <CODE>FooBar getFoo(int)</CODE><BR> + ** <CODE>void setFoo(int,FooBar)</CODE><P> + ** + ** The constraints put on get and set methods are:<P> + ** <OL> + ** <LI>There must be at least a get(int) or a set(int,...) method. + ** Nothing else is required. <B>Spec note:</B>One nice restriction + ** would be that if there is a get() there must be a get(int), same + ** with set, but that is not in the spec and is fairly harmless.)</LI> + ** <LI>A get array method must have signature + ** <CODE><propertyType>[] <getMethodName>()</CODE></LI> + ** <LI>A set array method must have signature + ** <CODE>void <setMethodName>(<propertyType>[])</CODE></LI> + ** <LI>A get index method must have signature + ** <CODE><propertyType> <getMethodName>(int)</CODE></LI> + ** <LI>A set index method must have signature + ** <CODE>void <setMethodName>(int,<propertyType>)</CODE></LI> + ** <LI>All these methods may throw any exception.</LI> + ** <LI>All these methods must be public.</LI> + ** </OL> + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 26 Jul 1998 + **/ + +public class IndexedPropertyDescriptor extends PropertyDescriptor { + private Class indexedPropertyType; + private Method setIndex; + private Method getIndex; + + /** Create a new IndexedPropertyDescriptor by introspection. + ** This form of constructor creates the PropertyDescriptor by + ** looking for getter methods named <CODE>get<name>()</CODE> + ** and setter methods named + ** <CODE>set<name>()</CODE> in class + ** <CODE><beanClass></CODE>, where <name> has its + ** first letter capitalized by the constructor.<P> + ** + ** <B>Implementation note:</B> If there is a get(int) method, + ** then the return type of that method is used to find the + ** remaining methods. If there is no get method, then the + ** set(int) method is searched for exhaustively and that type + ** is used to find the others.<P> + ** + ** <B>Spec note:</B> + ** If there is no get(int) method and multiple set(int) methods with + ** the same name and the correct parameters (different type of course), + ** then an IntrospectionException is thrown. While Sun's spec + ** does not state this, it can make Bean behavior different on + ** different systems (since method order is not guaranteed) and as + ** such, can be treated as a bug in the spec. I am not aware of + ** whether Sun's implementation catches this. + ** + ** @param name the programmatic name of the property, usually + ** starting with a lowercase letter (e.g. fooManChu + ** instead of FooManChu). + ** @param beanClass the class the get and set methods live in. + ** @exception IntrospectionException if the methods are not found or invalid. + **/ + public IndexedPropertyDescriptor(String name, Class beanClass) throws IntrospectionException { + super(name); + String capitalized; + try { + capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1); + } catch(StringIndexOutOfBoundsException e) { + capitalized = ""; + } + findMethods(beanClass, "get" + capitalized, "set" + capitalized, "get" + capitalized, "set" + capitalized); + } + + /** Create a new IndexedPropertyDescriptor by introspection. + ** This form of constructor allows you to specify the + ** names of the get and set methods to search for.<P> + ** + ** <B>Implementation note:</B> If there is a get(int) method, + ** then the return type of that method is used to find the + ** remaining methods. If there is no get method, then the + ** set(int) method is searched for exhaustively and that type + ** is used to find the others.<P> + ** + ** <B>Spec note:</B> + ** If there is no get(int) method and multiple set(int) methods with + ** the same name and the correct parameters (different type of course), + ** then an IntrospectionException is thrown. While Sun's spec + ** does not state this, it can make Bean behavior different on + ** different systems (since method order is not guaranteed) and as + ** such, can be treated as a bug in the spec. I am not aware of + ** whether Sun's implementation catches this. + ** + ** @param name the programmatic name of the property, usually + ** starting with a lowercase letter (e.g. fooManChu + ** instead of FooManChu). + ** @param beanClass the class the get and set methods live in. + ** @param getMethodName the name of the get array method. + ** @param setMethodName the name of the set array method. + ** @param getIndexName the name of the get index method. + ** @param setIndexName the name of the set index method. + ** @exception IntrospectionException if the methods are not found or invalid. + **/ + public IndexedPropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException { + super(name); + findMethods(beanClass, getMethodName, setMethodName, getIndexName, setIndexName); + } + + /** Create a new PropertyDescriptor using explicit Methods. + ** Note that the methods will be checked for conformance to standard + ** Property method rules, as described above at the top of this class. + ** + ** @param name the programmatic name of the property, usually + ** starting with a lowercase letter (e.g. fooManChu + ** instead of FooManChu). + ** @param getMethod the get array method. + ** @param setMethod the set array method. + ** @param getIndex the get index method. + ** @param setIndex the set index method. + ** @exception IntrospectionException if the methods are not found or invalid. + **/ + public IndexedPropertyDescriptor(String name, Method getMethod, Method setMethod, Method getIndex, Method setIndex) throws IntrospectionException { + super(name); + if(getMethod != null && getMethod.getParameterTypes().length > 0) { + throw new IntrospectionException("get method has parameters"); + } + if(getMethod != null && setMethod.getParameterTypes().length != 1) { + throw new IntrospectionException("set method does not have exactly one parameter"); + } + if(getMethod != null && setMethod != null) { + if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) { + throw new IntrospectionException("set and get methods do not share the same type"); + } + if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass()) + && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) { + throw new IntrospectionException("set and get methods are not in the same class."); + } + } + + if(getIndex != null && (getIndex.getParameterTypes().length != 1 + || !(getIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) { + throw new IntrospectionException("get index method has wrong parameters"); + } + if(setIndex != null && (setIndex.getParameterTypes().length != 2 + || !(setIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) { + throw new IntrospectionException("set index method has wrong parameters"); + } + if(getIndex != null && setIndex != null) { + if(!getIndex.getReturnType().equals(setIndex.getParameterTypes()[1])) { + throw new IntrospectionException("set index methods do not share the same type"); + } + if(!getIndex.getDeclaringClass().isAssignableFrom(setIndex.getDeclaringClass()) + && !setIndex.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) { + throw new IntrospectionException("get and set index methods are not in the same class."); + } + } + + if(getIndex != null && getMethod != null && !getIndex.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass()) + && !getMethod.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) { + throw new IntrospectionException("methods are not in the same class."); + } + + if(getIndex != null && getMethod != null && !Array.newInstance(getIndex.getReturnType(),0).getClass().equals(getMethod.getReturnType())) { + throw new IntrospectionException("array methods do not match index methods."); + } + + this.getMethod = getMethod; + this.setMethod = setMethod; + this.getIndex = getIndex; + this.setIndex = getIndex; + this.indexedPropertyType = getIndex != null ? getIndex.getReturnType() : setIndex.getParameterTypes()[1]; + this.propertyType = getMethod != null ? getMethod.getReturnType() : (setMethod != null ? setMethod.getParameterTypes()[0] : Array.newInstance(this.indexedPropertyType,0).getClass()); + } + + public Class getIndexedPropertyType() { + return indexedPropertyType; + } + + public Method getIndexedReadMethod() { + return getIndex; + } + + public Method getIndexedWriteMethod() { + return setIndex; + } + + private void findMethods(Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException { + try { + if(getIndexName != null) { + try { + Class[] getArgs = new Class[1]; + getArgs[0] = java.lang.Integer.TYPE; + getIndex = beanClass.getMethod(getIndexName,getArgs); + indexedPropertyType = getIndex.getReturnType(); + } catch(NoSuchMethodException E) { + } + } + if(getIndex != null) { + if(setIndexName != null) { + try { + Class[] setArgs = new Class[2]; + setArgs[0] = java.lang.Integer.TYPE; + setArgs[1] = indexedPropertyType; + setIndex = beanClass.getMethod(setIndexName,setArgs); + if(!setIndex.getReturnType().equals(java.lang.Void.TYPE)) { + throw new IntrospectionException(setIndexName + " has non-void return type"); + } + } catch(NoSuchMethodException E) { + } + } + } else if(setIndexName != null) { + Method[] m = beanClass.getMethods(); + for(int i=0;i<m.length;i++) { + Method current = m[i]; + if(current.getName().equals(setIndexName) + && current.getParameterTypes().length == 2 + && (current.getParameterTypes()[0]).equals(java.lang.Integer.TYPE) + && current.getReturnType().equals(java.lang.Void.TYPE)) { + if(setIndex != null) { + throw new IntrospectionException("Multiple, different set methods found that fit the bill!"); + } else { + setIndex = current; + indexedPropertyType = current.getParameterTypes()[1]; + } + } + } + if(setIndex == null) { + throw new IntrospectionException("Cannot find get or set methods."); + } + } else { + throw new IntrospectionException("Cannot find get or set methods."); + } + + Class arrayType = Array.newInstance(indexedPropertyType,0).getClass(); + + Class[] setArgs = new Class[1]; + setArgs[0] = arrayType; + try { + setMethod = beanClass.getMethod(setMethodName,setArgs); + if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) { + setMethod = null; + } + } catch(NoSuchMethodException E) { + } + + Class[] getArgs = new Class[0]; + try { + getMethod = beanClass.getMethod(getMethodName,getArgs); + if(!getMethod.getReturnType().equals(arrayType)) { + getMethod = null; + } + } catch(NoSuchMethodException E) { + } + } catch(SecurityException E) { + throw new IntrospectionException("SecurityException while trying to find methods."); + } + } +} diff --git a/libjava/java/beans/IntrospectionException.java b/libjava/java/beans/IntrospectionException.java new file mode 100644 index 0000000..0bbd579 --- /dev/null +++ b/libjava/java/beans/IntrospectionException.java @@ -0,0 +1,46 @@ +/* java.beans.IntrospectionException + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + ** IntrospectionException is thrown when the Introspector fails. Surprise, surprise. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 31 May 1998 + ** @see java.beans.Introspector + **/ + +public class IntrospectionException extends Exception { + /** Instantiate this exception with the given message. + ** @param msg the message for the exception. + **/ + public IntrospectionException(String msg) { + super(msg); + } +} diff --git a/libjava/java/beans/Introspector.java b/libjava/java/beans/Introspector.java new file mode 100644 index 0000000..a191971 --- /dev/null +++ b/libjava/java/beans/Introspector.java @@ -0,0 +1,427 @@ +/* java.beans.Introspector + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import gnu.java.beans.*; +import java.util.*; +import java.lang.reflect.*; +import gnu.java.lang.*; + +/** + ** Introspector is the class that does the bulk of the + ** design-time work in Java Beans. Every class must have + ** a BeanInfo in order for an RAD tool to use it; but, as + ** promised, you don't have to write the BeanInfo class + ** yourself if you don't want to. All you have to do is + ** call getBeanInfo() in the Introspector and it will use + ** standard JavaBeans-defined method signatures to + ** determine the information about your class.<P> + ** + ** Don't worry about it too much, though: you can provide + ** JavaBeans with as much customized information as you + ** want, or as little as you want, using the BeanInfo + ** interface (see BeanInfo for details).<P> + ** + ** <STRONG>Order of Operations</STRONG><P> + ** + ** When you call getBeanInfo(class c), the Introspector + ** first searches for BeanInfo class to see if you + ** provided any explicit information. It searches for a + ** class named <bean class name>BeanInfo in different + ** packages, first searching the bean class's package + ** and then moving on to search the beanInfoSearchPath.<P> + ** + ** If it does not find a BeanInfo class, it acts as though + ** it had found a BeanInfo class returning null from all + ** methods (meaning it should discover everything through + ** Introspection). If it does, then it takes the + ** information it finds in the BeanInfo class to be + ** canonical (that is, the information speaks for its + ** class as well as all superclasses).<P> + ** + ** When it has introspected the class, calls + ** getBeanInfo(c.getSuperclass) and adds that information + ** to the information it has, not adding to any information + ** it already has that is canonical.<P> + ** + ** <STRONG>Introspection Design Patterns</STRONG><P> + ** + ** When the Introspector goes in to read the class, it + ** follows a well-defined order in order to not leave any + ** methods unaccounted for. Its job is to step over all + ** of the public methods in a class and determine whether + ** they are part of a property, an event, or a method (in + ** that order). + ** + ** + ** <STRONG>Properties:</STRONG><P> + ** + ** <OL> + ** <LI>If there is a <CODE>public boolean isXXX()</CODE> + ** method, then XXX is a read-only boolean property. + ** <CODE>boolean getXXX()</CODE> may be supplied in + ** addition to this method, although isXXX() is the + ** one that will be used in this case and getXXX() + ** will be ignored. If there is a + ** <CODE>public void setXXX(boolean)</CODE> method, + ** it is part of this group and makes it a read-write + ** property.</LI> + ** <LI>If there is a + ** <CODE>public <type> getXXX(int)</CODE> + ** method, then XXX is a read-only indexed property of + ** type <type>. If there is a + ** <CODE>public void setXXX(int,<type>)</CODE> + ** method, then it is a read-write indexed property of + ** type <type>. There may also be a + ** <CODE>public <type>[] getXXX()</CODE> and a + ** <CODE>public void setXXX(<type>)</CODE> + ** method as well.</CODE></LI> + ** <LI>If there is a + ** <CODE>public void setXXX(int,<type>)</CODE> + ** method, then it is a write-only indexed property of + ** type <type>. There may also be a + ** <CODE>public <type>[] getXXX()</CODE> and a + ** <CODE>public void setXXX(<type>)</CODE> + ** method as well.</CODE></LI> + ** <LI>If there is a + ** <CODE>public <type> getXXX()</CODE> method, + ** then XXX is a read-only property of type + ** <type>. If there is a + ** <CODE>public void setXXX(<type>)</CODE> + ** method, then it will be used for the property and + ** the property will be considered read-write.</LI> + ** <LI>If there is a + ** <CODE>public void setXXX(<type>)</CODE> + ** method, then as long as XXX is not already used as + ** the name of a property, XXX is assumed to be a + ** write-only property of type <type>.</LI> + ** <LI>In all of the above cases, if the setXXX() method + ** throws <CODE>PropertyVetoException</CODE>, then the + ** property in question is assumed to be constrained. + ** No properties are ever assumed to be bound + ** (<STRONG>Spec Note:</STRONG> this is not in the + ** spec, it just makes sense). See PropertyDescriptor + ** for a description of bound and constrained + ** properties.</LI> + ** </OL> + ** + ** <STRONG>Events:</STRONG><P> + ** + ** If there is a pair of methods, + ** <CODE>public void addXXX(<type>)</CODE> and + ** <CODE>public void removeXXX(<type>)</CODE>, where + ** <type> is a descendant of + ** <CODE>java.util.EventListener</CODE>, then the pair of + ** methods imply that this Bean will fire events to + ** listeners of type <type>.<P> + ** + ** If the addXXX() method throws + ** <CODE>java.util.TooManyListenersException</CODE>, then + ** the event set is assumed to be <EM>unicast</EM>. See + ** EventSetDescriptor for a discussion of unicast event + ** sets.<P> + ** + ** <STRONG>Spec Note:</STRONG> the spec seems to say that + ** the listener type's classname must be equal to the XXX + ** part of addXXX() and removeXXX(), but that is not the + ** case in Sun's implementation, so I am assuming it is + ** not the case in general.<P> + ** + ** <STRONG>Methods:</STRONG><P> + ** + ** Any public methods (including those which were used + ** for Properties or Events) are used as Methods. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 29 Jul 1998 + ** @see java.beans.BeanInfo + **/ + +public class Introspector { + static String[] beanInfoSearchPath = {"gnu.java.beans.info", "sun.beans.infos"}; + static Hashtable beanInfoCache = new Hashtable(); + + private Introspector() {} + + /** Get the BeanInfo for class <CODE>beanClass</CODE>, + ** first by looking for explicit information, next by + ** using standard design patterns to determine + ** information about the class. + ** @param beanClass the class to get BeanInfo about. + ** @return the BeanInfo object representing the class. + **/ + public static BeanInfo getBeanInfo(Class beanClass) throws IntrospectionException { + BeanInfo cachedInfo; + synchronized(beanClass) { + cachedInfo = (BeanInfo)beanInfoCache.get(beanClass); + if(cachedInfo != null) { + return cachedInfo; + } + cachedInfo = getBeanInfo(beanClass,null); + beanInfoCache.put(beanClass,cachedInfo); + return cachedInfo; + } + } + + /** Get the BeanInfo for class <CODE>beanClass</CODE>, + ** first by looking for explicit information, next by + ** using standard design patterns to determine + ** information about the class. It crawls up the + ** inheritance tree until it hits <CODE>topClass</CODE>. + ** @param beanClass the Bean class. + ** @param stopClass the class to stop at. + ** @return the BeanInfo object representing the class. + **/ + public static BeanInfo getBeanInfo(Class beanClass, Class stopClass) throws IntrospectionException { + ExplicitInfo explicit = new ExplicitInfo(beanClass,stopClass); + + IntrospectionIncubator ii = new IntrospectionIncubator(); + ii.setPropertyStopClass(explicit.propertyStopClass); + ii.setEventStopClass(explicit.eventStopClass); + ii.setMethodStopClass(explicit.methodStopClass); + ii.addMethods(beanClass.getMethods()); + + BeanInfoEmbryo currentInfo = ii.getBeanInfoEmbryo(); + PropertyDescriptor[] p = explicit.explicitPropertyDescriptors; + if(p!=null) { + for(int i=0;i<p.length;i++) { + if(!currentInfo.hasProperty(p[i])) { + currentInfo.addProperty(p[i]); + } + } + if(explicit.defaultProperty != -1) { + currentInfo.setDefaultPropertyName(p[explicit.defaultProperty].getName()); + } + } + EventSetDescriptor[] e = explicit.explicitEventSetDescriptors; + if(e!=null) { + for(int i=0;i<e.length;i++) { + if(!currentInfo.hasEvent(e[i])) { + currentInfo.addEvent(e[i]); + } + } + if(explicit.defaultEvent != -1) { + currentInfo.setDefaultEventName(e[explicit.defaultEvent].getName()); + } + } + MethodDescriptor[] m = explicit.explicitMethodDescriptors; + if(m!=null) { + for(int i=0;i<m.length;i++) { + if(!currentInfo.hasMethod(m[i])) { + currentInfo.addMethod(m[i]); + } + } + } + + if(explicit.explicitBeanDescriptor != null) { + currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,explicit.explicitBeanDescriptor.getCustomizerClass())); + } else { + currentInfo.setBeanDescriptor(new BeanDescriptor(beanClass,null)); + } + + currentInfo.setAdditionalBeanInfo(explicit.explicitBeanInfo); + currentInfo.setIcons(explicit.im); + + return currentInfo.getBeanInfo(); + } + + /** Get the search path for BeanInfo classes. + ** @return the BeanInfo search path. + **/ + public static String[] getBeanInfoSearchPath() { + return beanInfoSearchPath; + } + + /** Set the search path for BeanInfo classes. + ** @param beanInfoSearchPath the new BeanInfo search + ** path. + **/ + public static void setBeanInfoSearchPath(String[] beanInfoSearchPath) { + Introspector.beanInfoSearchPath = beanInfoSearchPath; + } + + /** A helper method to convert a name to standard Java + ** naming conventions: anything with two capitals as the + ** first two letters remains the same, otherwise the + ** first letter is decapitalized. URL = URL, I = i, + ** MyMethod = myMethod. + ** @param name the name to decapitalize. + ** @return the decapitalized name. + **/ + public static String decapitalize(String name) { + try { + if(!Character.isUpperCase(name.charAt(0))) { + return name; + } else { + try { + if(Character.isUpperCase(name.charAt(1))) { + return name; + } else { + char[] c = name.toCharArray(); + c[0] = Character.toLowerCase(c[0]); + return new String(c); + } + } catch(StringIndexOutOfBoundsException E) { + char[] c = new char[1]; + c[0] = Character.toLowerCase(name.charAt(0)); + return new String(c); + } + } + } catch(StringIndexOutOfBoundsException E) { + return name; + } catch(NullPointerException E) { + return null; + } + } + + static BeanInfo copyBeanInfo(BeanInfo b) { + java.awt.Image[] icons = new java.awt.Image[4]; + for(int i=1;i<=4;i++) { + icons[i-1] = b.getIcon(i); + } + return new ExplicitBeanInfo(b.getBeanDescriptor(),b.getAdditionalBeanInfo(), + b.getPropertyDescriptors(),b.getDefaultPropertyIndex(), + b.getEventSetDescriptors(),b.getDefaultEventIndex(), + b.getMethodDescriptors(),icons); + } +} + +class ExplicitInfo { + BeanDescriptor explicitBeanDescriptor; + BeanInfo[] explicitBeanInfo; + + PropertyDescriptor[] explicitPropertyDescriptors; + EventSetDescriptor[] explicitEventSetDescriptors; + MethodDescriptor[] explicitMethodDescriptors; + + int defaultProperty; + int defaultEvent; + + java.awt.Image[] im = new java.awt.Image[4]; + + Class propertyStopClass; + Class eventStopClass; + Class methodStopClass; + + ExplicitInfo(Class beanClass, Class stopClass) { + while(beanClass != null && !beanClass.equals(stopClass)) { + BeanInfo explicit = findExplicitBeanInfo(beanClass); + if(explicit != null) { + if(explicitBeanDescriptor == null) { + explicitBeanDescriptor = explicit.getBeanDescriptor(); + } + if(explicitBeanInfo == null) { + explicitBeanInfo = explicit.getAdditionalBeanInfo(); + } + if(explicitPropertyDescriptors == null) { + if(explicit.getPropertyDescriptors() != null) { + explicitPropertyDescriptors = explicit.getPropertyDescriptors(); + defaultProperty = explicit.getDefaultPropertyIndex(); + propertyStopClass = beanClass; + } + } + if(explicitEventSetDescriptors == null) { + if(explicit.getEventSetDescriptors() != null) { + explicitEventSetDescriptors = explicit.getEventSetDescriptors(); + defaultEvent = explicit.getDefaultEventIndex(); + eventStopClass = beanClass; + } + } + if(explicitMethodDescriptors == null) { + if(explicit.getMethodDescriptors() != null) { + explicitMethodDescriptors = explicit.getMethodDescriptors(); + methodStopClass = beanClass; + } + } + if(im[0] == null + && im[1] == null + && im[2] == null + && im[3] == null) { + im[0] = explicit.getIcon(0); + im[1] = explicit.getIcon(1); + im[2] = explicit.getIcon(2); + im[3] = explicit.getIcon(3); + } + } + beanClass = beanClass.getSuperclass(); + } + if(propertyStopClass == null) { + propertyStopClass = stopClass; + } + if(eventStopClass == null) { + eventStopClass = stopClass; + } + if(methodStopClass == null) { + methodStopClass = stopClass; + } + } + + static Hashtable explicitBeanInfos = new Hashtable(); + static Vector emptyBeanInfos = new Vector(); + + static BeanInfo findExplicitBeanInfo(Class beanClass) { + BeanInfo retval = (BeanInfo)explicitBeanInfos.get(beanClass); + if(retval != null) { + return retval; + } else if(emptyBeanInfos.indexOf(beanClass) != -1) { + return null; + } else { + retval = reallyFindExplicitBeanInfo(beanClass); + if(retval != null) { + explicitBeanInfos.put(beanClass,retval); + } else { + emptyBeanInfos.addElement(beanClass); + } + return retval; + } + } + + static BeanInfo reallyFindExplicitBeanInfo(Class beanClass) { + try { + try { + return (BeanInfo)Class.forName(beanClass.getName()+"BeanInfo").newInstance(); + } catch(ClassNotFoundException E) { + } + String newName = ClassHelper.getTruncatedClassName(beanClass) + "BeanInfo"; + for(int i=0;i<Introspector.beanInfoSearchPath.length;i++) { + try { + if(Introspector.beanInfoSearchPath[i].equals("")) { + return (BeanInfo)Class.forName(newName).newInstance(); + } else { + return (BeanInfo)Class.forName(Introspector.beanInfoSearchPath[i] + "." + newName).newInstance(); + } + } catch(ClassNotFoundException E) { + } + } + } catch(IllegalAccessException E) { + } catch(InstantiationException E) { + } + return null; + } +} diff --git a/libjava/java/beans/MethodDescriptor.java b/libjava/java/beans/MethodDescriptor.java new file mode 100644 index 0000000..bb052f7 --- /dev/null +++ b/libjava/java/beans/MethodDescriptor.java @@ -0,0 +1,77 @@ +/* java.beans.MethodDescriptor + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import java.lang.reflect.*; + +/** MethodDescriptor describes information about a JavaBeans method. + ** It's a fairly straightforward class (at least something in this + ** package is straightforward!). + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 26 Jul 1998 + **/ +public class MethodDescriptor extends FeatureDescriptor { + private Method m; + private ParameterDescriptor[] parameterDescriptors; + + /** Create a new MethodDescriptor. + ** This method sets the name to the name of the method (Method.getName()). + ** @param m the method it will represent. + **/ + public MethodDescriptor(Method m) { + setName(m.getName()); + this.m = m; + } + + /** Create a new MethodDescriptor. + ** This method sets the name to the name of the method (Method.getName()). + ** @param m the method it will represent. + ** @param parameterDescriptors descriptions of the parameters (especially names). + **/ + public MethodDescriptor(Method m, ParameterDescriptor[] parameterDescriptors) { + setName(m.getName()); + this.m = m; + this.parameterDescriptors = parameterDescriptors; + } + + /** Get the parameter descriptors from this method. + ** Since MethodDescriptor has no way of determining what + ** the parameter names were, this defaults to null. + **/ + public ParameterDescriptor[] getParameterDescriptors() { + return parameterDescriptors; + } + + /** Get the method this MethodDescriptor represents. **/ + public Method getMethod() { + return m; + } +} + diff --git a/libjava/java/beans/ParameterDescriptor.java b/libjava/java/beans/ParameterDescriptor.java new file mode 100644 index 0000000..664d5ca --- /dev/null +++ b/libjava/java/beans/ParameterDescriptor.java @@ -0,0 +1,41 @@ +/* java.beans.MethodDescriptor + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** ParameterDescriptor represents a single parameter to a method. + ** As it turns out, FeatureDescriptor is sufficient to hold all + ** the information. Use its constructor and methods to set + ** the appropriate values. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 26 Jul 1998 + **/ +public class ParameterDescriptor extends FeatureDescriptor { + +} diff --git a/libjava/java/beans/PropertyChangeEvent.java b/libjava/java/beans/PropertyChangeEvent.java new file mode 100644 index 0000000..f07577c --- /dev/null +++ b/libjava/java/beans/PropertyChangeEvent.java @@ -0,0 +1,111 @@ +/* java.beans.PropertyChangeEvent + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + ** PropertyChangeEvents are fired in the PropertyChange + ** and VetoableChange event classes. They represent the + ** old and new values as well as the source Bean.<P> + ** + ** If the old or new value is a primitive type, it must + ** be wrapped in the appropriate wrapper type + ** (java.lang.Integer for int, etc., etc.).<P> + ** + ** If the old or new values are unknown (although why + ** that would be I do not know), they may be null.<P> + ** + ** Right now Sun put in a propagationId, reserved for + ** future use. Read the comments on the constructor + ** and on setPropagationId for more information. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 29 Jul 1998 + **/ + +public class PropertyChangeEvent extends java.util.EventObject { + String propertyName; + Object oldVal; + Object newVal; + Object propagationId; + + /** Create a new PropertyChangeEvent. Remember that if + ** you received a PropertyChangeEvent and are sending + ** a new one, you should also set the propagation ID + ** from the old PropertyChangeEvent. + ** @param source the Bean containing the property. + ** @param propertyName the property's name. + ** @param oldVal the old value of the property. + ** @param newVal the new value of the property. + **/ + public PropertyChangeEvent(Object source, String propertyName, Object oldVal, Object newVal) { + super(source); + this.propertyName = propertyName; + this.oldVal = oldVal; + this.newVal = newVal; + } + + /** Get the property name. + ** @return the property name. + **/ + public String getPropertyName() { + return propertyName; + } + + /** Get the property's old value. + ** @return the property's old value. + **/ + public Object getOldValue() { + return oldVal; + } + + /** Get the property's new value. + ** @return the property's new value. + **/ + public Object getNewValue() { + return newVal; + } + + /** Set the propagation ID. This is a way for the event + ** to be passed from hand to hand and retain a little + ** extra state. Right now it is unused, but it should + ** be propagated anyway so that future versions of + ** JavaBeans can use it, for God knows what. + ** @param propagationId the propagation ID. + **/ + public void setPropagationId(Object propagationId) { + this.propagationId = propagationId; + } + + /** Get the propagation ID. + ** @return the propagation ID. + **/ + public Object getPropagationId() { + return propagationId; + } +} diff --git a/libjava/java/beans/PropertyChangeListener.java b/libjava/java/beans/PropertyChangeListener.java new file mode 100644 index 0000000..7f1df72 --- /dev/null +++ b/libjava/java/beans/PropertyChangeListener.java @@ -0,0 +1,48 @@ +/* java.beans.PropertyChangeListener + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + ** PropertyChangeListener allows a class to monitor + ** properties of a Bean for changes.<P> + ** + ** A propertyChange() event will only be fired + ** <EM>after</EM> the property has changed. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 29 Jul 1998 + ** @see java.beans.PropertyChangeSupport + **/ + +public interface PropertyChangeListener { + /** Fired after a Bean's property has changed. + ** @param e the change (containing the old and new values) + **/ + public abstract void propertyChange(PropertyChangeEvent e); +} diff --git a/libjava/java/beans/PropertyChangeSupport.java b/libjava/java/beans/PropertyChangeSupport.java new file mode 100644 index 0000000..512c8ed --- /dev/null +++ b/libjava/java/beans/PropertyChangeSupport.java @@ -0,0 +1,203 @@ +/* java.beans.PropertyChangeSupport + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; +import java.util.Hashtable; +import java.util.Vector; + +/** + ** PropertyChangeSupport makes it easy to fire property + ** change events and handle listeners. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.2.0, 15 Mar 1999 + **/ + +public class PropertyChangeSupport implements java.io.Serializable { + Hashtable propertyListeners = new Hashtable(); + Vector listeners = new Vector(); + Object bean; + + /** Create PropertyChangeSupport to work with a specific + ** source bean. + ** @param bean the source bean to use. + **/ + public PropertyChangeSupport(Object bean) { + this.bean = bean; + } + + /** Adds a PropertyChangeListener to the list of listeners. + ** All property change events will be sent to this listener. + ** <P> + ** + ** The listener add is not unique: that is, <em>n</em> adds with + ** the same listener will result in <em>n</em> events being sent + ** to that listener for every property change. + ** <P> + ** + ** Adding a null listener will cause undefined behavior. + ** + ** @param l the listener to add. + **/ + public void addPropertyChangeListener(PropertyChangeListener l) { + listeners.addElement(l); + } + + /** Adds a PropertyChangeListener listening on the specified property. + ** Events will be sent to the listener for that particular property. + ** <P> + ** + ** The listener add is not unique; that is, <em>n</em> adds on a + ** particular property for a particular listener will result in + ** <em>n</em> events being sent to that listener when that + ** property is changed. + ** <P> + ** + ** The effect is cumulative, too; if you are registered to listen + ** to receive events on all property changes, and then you + ** register on a particular property, you will receive change + ** events for that property twice. + ** <P> + ** + ** Adding a null listener will cause undefined behavior. + ** + ** @param propertyName the name of the property to listen on. + ** @param l the listener to add. + **/ + public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) { + synchronized(propertyListeners) { + Vector v = (Vector)propertyListeners.get(propertyName); + try { + v.addElement(l); + } catch(NullPointerException e) { + /* If v is not found, create a new vector. */ + v = new Vector(); + v.addElement(l); + propertyListeners.put(propertyName, v); + } + } + } + + /** Removes a PropertyChangeListener from the list of listeners. + ** If any specific properties are being listened on, they must + ** be deregistered by themselves; this will only remove the + ** general listener to all properties. + ** <P> + ** + ** If <code>add()</code> has been called multiple times for a + ** particular listener, <code>remove()</code> will have to be + ** called the same number of times to deregister it. + ** + ** @param l the listener to remove. + **/ + public void removePropertyChangeListener(PropertyChangeListener l) { + listeners.removeElement(l); + } + + /** Removes a PropertyChangeListener from listening to a specific property. + ** <P> + ** + ** If <code>add()</code> has been called multiple times for a + ** particular listener on a property, <code>remove()</code> will + ** have to be called the same number of times to deregister it. + ** + ** @param propertyName the property to stop listening on. + ** @param l the listener to remove. + **/ + public void removePropertyChangeListener(String propertyName, PropertyChangeListener l) { + synchronized(propertyListeners) { + Vector v = (Vector)propertyListeners.get(propertyName); + try { + v.removeElement(l); + if(v.size() == 0) { + propertyListeners.remove(propertyName); + } + } catch(NullPointerException e) { + /* if v is not found, do nothing. */ + } + } + } + + /** Fire a PropertyChangeEvent to all the listeners. + ** + ** @param event the event to fire. + **/ + public void firePropertyChange(PropertyChangeEvent event) { + for(int i=0;i<listeners.size();i++) { + ((PropertyChangeListener)listeners.elementAt(i)).propertyChange(event); + } + Vector moreListeners = (Vector)propertyListeners.get(event.getPropertyName()); + if(moreListeners != null) { + for(int i=0;i<moreListeners.size();i++) { + ((PropertyChangeListener)moreListeners.elementAt(i)).propertyChange(event); + } + } + } + + /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners. + ** + ** @param propertyName the name of the property that changed. + ** @param oldVal the old value. + ** @param newVal the new value. + **/ + public void firePropertyChange(String propertyName, Object oldVal, Object newVal) { + firePropertyChange(new PropertyChangeEvent(bean,propertyName,oldVal,newVal)); + } + + /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners. + ** + ** @param propertyName the name of the property that changed. + ** @param oldVal the old value. + ** @param newVal the new value. + **/ + public void firePropertyChange(String propertyName, boolean oldVal, boolean newVal) { + firePropertyChange(new PropertyChangeEvent(bean, propertyName, new Boolean(oldVal), new Boolean(newVal))); + } + + /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners. + ** + ** @param propertyName the name of the property that changed. + ** @param oldVal the old value. + ** @param newVal the new value. + **/ + public void firePropertyChange(String propertyName, int oldVal, int newVal) { + firePropertyChange(new PropertyChangeEvent(bean, propertyName, new Integer(oldVal), new Integer(newVal))); + } + + /** Tell whether the specified property is being listened on or not. + ** This will only return <code>true</code> if there are listeners + ** on all properties or if there is a listener specifically on this + ** property. + ** + ** @param propertyName the property that may be listened on + ** @return whether the property is being listened on + **/ + public boolean hasListeners(String propertyName) { + return listeners.size() > 0 || propertyListeners.get(propertyName) != null; + } +} diff --git a/libjava/java/beans/PropertyDescriptor.java b/libjava/java/beans/PropertyDescriptor.java new file mode 100644 index 0000000..ec14312 --- /dev/null +++ b/libjava/java/beans/PropertyDescriptor.java @@ -0,0 +1,333 @@ +/* java.beans.PropertyDescriptor + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import java.util.*; +import java.lang.reflect.*; + + +/** + ** PropertyDescriptor describes information about a JavaBean property, + ** by which we mean a property that has been exposed via a pair of + ** get and set methods. (There may be no get method, which means + ** the property is write-only, or no set method, which means the + ** the property is read-only.)<P> + ** + ** The constraints put on get and set methods are:<P> + ** <OL> + ** <LI>A get method must have signature + ** <CODE><propertyType> <getMethodName>()</CODE></LI> + ** <LI>A set method must have signature + ** <CODE>void <setMethodName>(<propertyType>)</CODE></LI> + ** <LI>Either method type may throw any exception.</LI> + ** <LI>Both methods must be public.</LI> + ** </OL> + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 26 Jul 1998 + **/ + +public class PropertyDescriptor extends FeatureDescriptor { + Class propertyType; + Method getMethod; + Method setMethod; + + Class propertyEditorClass; + boolean bound; + boolean constrained; + + PropertyDescriptor(String name) { + setName(name); + } + + /** Create a new PropertyDescriptor by introspection. + ** This form of constructor creates the PropertyDescriptor by + ** looking for a getter method named <CODE>get<name>()</CODE> + ** (or, optionally, if the property is boolean, + ** <CODE>is<name>()</CODE>) and + ** <CODE>set<name>()</CODE> in class + ** <CODE><beanClass></CODE>, where <name> has its + ** first letter capitalized by the constructor.<P> + ** + ** <B>Implementation note:</B> If there is a get method (or + ** boolean isXXX() method), then the return type of that method + ** is used to find the set method. If there is no get method, + ** then the set method is searched for exhaustively.<P> + ** + ** <B>Spec note:</B> + ** If there is no get method and multiple set methods with + ** the same name and a single parameter (different type of course), + ** then an IntrospectionException is thrown. While Sun's spec + ** does not state this, it can make Bean behavior different on + ** different systems (since method order is not guaranteed) and as + ** such, can be treated as a bug in the spec. I am not aware of + ** whether Sun's implementation catches this. + ** + ** @param name the programmatic name of the property, usually + ** starting with a lowercase letter (e.g. fooManChu + ** instead of FooManChu). + ** @param beanClass the class the get and set methods live in. + ** @exception IntrospectionException if the methods are not found or invalid. + **/ + public PropertyDescriptor(String name, Class beanClass) throws IntrospectionException { + setName(name); + String capitalized; + try { + capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1); + } catch(StringIndexOutOfBoundsException e) { + capitalized = ""; + } + findMethods(beanClass, "is" + capitalized, "get" + capitalized, "set" + capitalized); + } + + /** Create a new PropertyDescriptor by introspection. + ** This form of constructor allows you to specify the + ** names of the get and set methods to search for.<P> + ** + ** <B>Implementation note:</B> If there is a get method (or + ** boolean isXXX() method), then the return type of that method + ** is used to find the set method. If there is no get method, + ** then the set method is searched for exhaustively.<P> + ** + ** <B>Spec note:</B> + ** If there is no get method and multiple set methods with + ** the same name and a single parameter (different type of course), + ** then an IntrospectionException is thrown. While Sun's spec + ** does not state this, it can make Bean behavior different on + ** different systems (since method order is not guaranteed) and as + ** such, can be treated as a bug in the spec. I am not aware of + ** whether Sun's implementation catches this. + ** + ** @param name the programmatic name of the property, usually + ** starting with a lowercase letter (e.g. fooManChu + ** instead of FooManChu). + ** @param beanClass the class the get and set methods live in. + ** @param getMethodName the name of the get method. + ** @param setMethodName the name of the set method. + ** @exception IntrospectionException if the methods are not found or invalid. + **/ + public PropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName) throws IntrospectionException { + setName(name); + findMethods(beanClass, getMethodName, null, setMethodName); + } + + /** Create a new PropertyDescriptor using explicit Methods. + ** Note that the methods will be checked for conformance to standard + ** Property method rules, as described above at the top of this class. + ** + ** @param name the programmatic name of the property, usually + ** starting with a lowercase letter (e.g. fooManChu + ** instead of FooManChu). + ** @param getMethod the get method. + ** @param setMethod the set method. + ** @exception IntrospectionException if the methods are not found or invalid. + **/ + public PropertyDescriptor(String name, Method getMethod, Method setMethod) throws IntrospectionException { + setName(name); + if(getMethod != null && getMethod.getParameterTypes().length > 0) { + throw new IntrospectionException("get method has parameters"); + } + if(setMethod != null && setMethod.getParameterTypes().length != 1) { + throw new IntrospectionException("set method does not have exactly one parameter"); + } + if(getMethod != null && setMethod != null) { + if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) { + throw new IntrospectionException("set and get methods do not share the same type"); + } + if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass()) + && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) { + throw new IntrospectionException("set and get methods are not in the same class."); + } + } + this.getMethod = getMethod; + this.setMethod = setMethod; + if(getMethod != null) { + this.propertyType = getMethod.getReturnType(); + } else { + this.propertyType = setMethod.getParameterTypes()[0]; + } + } + + /** Get the property type. + ** This is the type the get method returns and the set method + ** takes in. + **/ + public Class getPropertyType() { + return propertyType; + } + + /** Get the get method. Why they call it readMethod here and + ** get everywhere else is beyond me. + **/ + public Method getReadMethod() { + return getMethod; + } + + /** Get the set method. Why they call it writeMethod here and + ** set everywhere else is beyond me. + **/ + public Method getWriteMethod() { + return setMethod; + } + + /** Get whether the property is bound. Defaults to false. **/ + public boolean isBound() { + return bound; + } + + /** Set whether the property is bound. + ** As long as the the bean implements addPropertyChangeListener() and + ** removePropertyChangeListener(), setBound(true) may safely be called.<P> + ** If these things are not true, then the behavior of the system + ** will be undefined.<P> + ** + ** When a property is bound, its set method is required to fire the + ** <CODE>PropertyChangeListener.propertyChange())</CODE event + ** after the value has changed. + ** @param bound whether the property is bound or not. + **/ + public void setBound(boolean bound) { + this.bound = bound; + } + + /** Get whether the property is constrained. Defaults to false. **/ + public boolean isConstrained() { + return constrained; + } + + /** Set whether the property is constrained. + ** If the set method throws <CODE>java.beans.PropertyVetoException</CODE> + ** (or subclass thereof) and the bean implements addVetoableChangeListener() + ** and removeVetoableChangeListener(), then setConstrained(true) may safely + ** be called. Otherwise, the system behavior is undefined. + ** <B>Spec note:</B> given those strict parameters, it would be nice if it + ** got set automatically by detection, but oh well.<P> + ** When a property is constrained, its set method is required to:<P> + ** <OL> + ** <LI>Fire the <CODE>VetoableChangeListener.vetoableChange()</CODE> + ** event notifying others of the change and allowing them a chance to + ** say it is a bad thing.</LI> + ** <LI>If any of the listeners throws a PropertyVetoException, then + ** it must fire another vetoableChange() event notifying the others + ** of a reversion to the old value (though, of course, the change + ** was never made). Then it rethrows the PropertyVetoException and + ** exits.</LI> + ** <LI>If all has gone well to this point, the value may be changed.</LI> + ** </OL> + ** @param constrained whether the property is constrained or not. + **/ + public void setConstrained(boolean constrained) { + this.constrained = constrained; + } + + /** Get the PropertyEditor class. Defaults to null. **/ + public Class getPropertyEditorClass() { + return propertyEditorClass; + } + + /** Set the PropertyEditor class. If the class does not implement + ** the PropertyEditor interface, you will likely get an exception + ** late in the game. + ** @param propertyEditorClass the PropertyEditor class for this class to use. + **/ + public void setPropertyEditorClass(Class propertyEditorClass) { + this.propertyEditorClass = propertyEditorClass; + } + + private void findMethods(Class beanClass, String getMethodName1, String getMethodName2, String setMethodName) throws IntrospectionException { + try { + if(getMethodName1 != null) { + try { + getMethod = beanClass.getMethod(getMethodName1, new Class[0]); + } catch(NoSuchMethodException E) { + } + if(getMethodName2 != null) { + if(getMethod != null && !getMethod.getReturnType().equals(java.lang.Boolean.TYPE)) { + // If the is() method exists but isn't boolean, we'll just go on and look for + // an ordinary get() method. + getMethod = null; + } + + Method getMethod2; + try { + getMethod2 = beanClass.getMethod(getMethodName2, new Class[0]); + } catch(NoSuchMethodException E) { + getMethod2 = null; + } + if(getMethod2 != null) { + if(getMethod != null) { + if(!getMethod.getReturnType().equals(getMethod2.getReturnType())) { + throw new IntrospectionException("Both " + getMethodName1 + " and " + getMethodName2 + " exist, and have contradictory return types."); + } + } else { + getMethod = getMethod2; + } + } + } + } + + if(getMethod != null) { + propertyType = getMethod.getReturnType(); + if(setMethodName != null) { + Class[] setArgs = new Class[1]; + setArgs[0] = propertyType; + try { + setMethod = beanClass.getMethod(setMethodName, setArgs); + if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) { + throw new IntrospectionException(setMethodName + " has non-void return type"); + } + } catch(NoSuchMethodException E) { + } + } + } else if(setMethodName != null) { + Method[] m = beanClass.getMethods(); + for(int i=0;i<m.length;i++) { + Method current = m[i]; + if(current.getName().equals(setMethodName) + && current.getParameterTypes().length == 1 + && current.getReturnType().equals(java.lang.Void.TYPE)) { + if(setMethod != null) { + throw new IntrospectionException("Multiple, different set methods found that fit the bill!"); + } else { + setMethod = current; + propertyType = current.getParameterTypes()[0]; + } + } + } + if(setMethod == null) { + throw new IntrospectionException("Cannot find get or set methods."); + } + } else { + throw new IntrospectionException("Cannot find get or set methods."); + } + } catch(SecurityException E) { + throw new IntrospectionException("SecurityException thrown on attempt to access methods."); + } + } +} diff --git a/libjava/java/beans/PropertyEditor.java b/libjava/java/beans/PropertyEditor.java new file mode 100644 index 0000000..b861b52 --- /dev/null +++ b/libjava/java/beans/PropertyEditor.java @@ -0,0 +1,198 @@ +/* java.beans.PropertyEditor + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + ** PropertyEditors are custom GUI editors for specific types of values. + ** + ** A PropertyEditor can be used, for example, if you are editing a type of value + ** that can be more easily represented graphically, such as a Point, or one that + ** can be more easily represented by a list, such as a boolean (true/false).<P> + ** + ** A PropertyEditor must be able to display its contents when asked to and + ** be able to allow the user to change its underlying field value. However, it + ** is not the PropertyEditor's responsibility to make the change to the + ** underlying Object; in fact, the PropertyEditor does not even know about the + ** Object it is actually editing--only about the property it is currently + ** editing. When a change is made to the property, the PropertyEditor must + ** simply fire a PropertyChangeEvent and allow the RAD tool to actually set + ** the property in the underlying Bean.<P> + ** + ** PropertyEditors should not change the Objects they are given by setValue(). + ** These Objects may or may not be the actual Objects which are properties of + ** the Bean being edited. Instead, PropertyEditors should create a new Object + ** and fire a PropertyChangeEvent with the old and new values.<P> + ** + ** PropertyEditors also must support the ability to return a Java + ** initialization string. See the getJavaInitializationString() method for + ** details.<P> + ** + ** There are several different ways a PropertyEditor may display and control + ** editing of its value. When multiple types of input and display are + ** given by a single PropertyEditor, the RAD tool may decide which of the call + ** to support. Some RAD tools may even be text-only, so even if you support + ** a graphical set and get, it may choose the text set and get whenever it can. + ** <OL> + ** <LI>Every PropertyEditor must support getValue() and setValue(). For + ** setValue(), the component must only support it when the argument is + ** the same type that the PropertyEditor supports.</LI> + ** <LI>Every PropertyEditor must support getJavaInitializationString().</LI> + ** <LI>You may support painting the value yourself if you wish. To do this, + ** have isPaintable() return true and implement the paintValue() method. + ** This method does not determine in any way how the value is edited; + ** merely how it is displayed.</LI> + ** <LU>Let the caller of the PropertyEditor give the user a text input. Do + ** this by returning a non-null String from getAsText(). If you support + ** text input, you *must* support setAsText().</LI> + ** <LI>Give the caller a set of possible values, such as "true"/"false", that + ** the user must select from. To do this, return the list of Strings + ** from the getTags() method. The RAD tool may choose to implement the + ** user input any way it wishes, and only guarantees that setAsText() will + ** only be called with one of the Strings returned from getTags().</LI> + ** <LI>You may support a whole custom editing control by supporting + ** getCustomEditor(). To do this, return true from supportsCustomEditor() + ** and return a Component that does the job. It is the component's job, + ** or the PropertyEditor's job, to make sure that when the editor changes + ** its value, the PropertyChangeEvent is thrown.</LI> + ** </OL> + ** + ** The PropertyEditor for a particular Bean can be found using the + ** PropertyEditorManager class, which goes through a series of different + ** checks to find the appropriate class.<P> + ** + ** A PropertyChangeEvent should be thrown from the PropertyEditor whenever a + ** bound property (a property PropertyDescriptor.isBound() set to true) + ** changes. When this happens, the editor itself should *not* change the value + ** itself, but rather allow the RAD tool to call setValue() or setAsText(). + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 30 June 1998 + ** @see java.beans.PropertyEditorManager + ** @see java.beans.PropertyEditorSupport + **/ + +public interface PropertyEditor { + /** Called by the RAD tool to set the value of this property for the PropertyEditor. + ** If the property type is native, it should be wrapped in the appropriate + ** wrapper type. + ** @param value the value to set this property to. + **/ + public abstract void setValue(Object value); + + /** Accessor method to get the current value the PropertyEditor is working with. + ** If the property type is native, it will be wrapped in the appropriate + ** wrapper type. + ** @return the current value of the PropertyEditor. + **/ + public abstract Object getValue(); + + + /** Set the value of this property using a String. + ** Whether or not this PropertyEditor is editing a String type, this converts + ** the String into the type of the PropertyEditor. + ** @param text the text to set it to. + ** @exception IllegalArgumentException if the String is in the wrong format or setAsText() is not supported. + **/ + public abstract void setAsText(String text) throws IllegalArgumentException; + + /** Get the value of this property in String format. + ** Many times this can simply use Object.toString().<P> + ** Return null if you do not support getAsText()/setAsText(). + ** <code>setAsText(getAsText())</code> should be valid; i.e. the stuff you spit out in + ** getAsText() should be able to go into setAsText(). + ** @return the value of this property in String format. + **/ + public abstract String getAsText(); + + /** Get a list of possible Strings which this property type can have. + ** The value of these will be used by the RAD tool to construct some sort + ** of list box or to check text box input, and the resulting String passed + ** to setAsText() should be one of these. Note, however, that like most things + ** with this mammoth, unwieldy interface, this is not guaranteed. Thus, you + ** must check the value in setAsText() anyway. + ** @return the list of possible String values for this property type. + **/ + public abstract String[] getTags(); + + + /** The RAD tool calls this to find out whether the PropertyEditor can paint itself. + ** @return true if it can paint itself graphically, false if it cannot. + **/ + public abstract boolean isPaintable(); + + /** The RAD tool calls this to paint the actual value of the property. + ** The Graphics context will have the same current font, color, etc. as the + ** parent Container. You may safely change the font, color, etc. and not + ** change them back.<P> + ** This method should do a silent no-op if isPaintable() is false. + ** @param g the Graphics context to paint on + ** @param bounds the rectangle you have reserved to work in + **/ + public abstract void paintValue(java.awt.Graphics g, java.awt.Rectangle bounds); + + + /** The RAD tool calls this to find out whether the PropertyEditor supports a custom component to edit and display itself. + ** @return true if getCustomEditor() will return a component, false if not. + **/ + public abstract boolean supportsCustomEditor(); + + /** The RAD tool calls this to grab the component that can edit this type. + ** The component may be painted anywhere the RAD tool wants to paint it-- + ** even in its own window.<P> + ** The component must hook up with the PropertyEditor and, whenever a + ** change to the value is made, fire a PropertyChangeEvent to the source.<P> + ** @return the custom editor for this property type. + **/ + public abstract java.awt.Component getCustomEditor(); + + + /** Adds a property change listener to this PropertyEditor. + ** @param listener the listener to add + **/ + public abstract void addPropertyChangeListener(PropertyChangeListener listener); + + /** Removes a property change listener from this PropertyEditor. + ** @param listener the listener to remove + **/ + public abstract void removePropertyChangeListener(PropertyChangeListener listener); + + /** Get a Java language-specific String which could be used to create an Object + ** of the specified type. Every PropertyEditor must support this.<P> + ** The reason for this is that while most RAD tools will serialize the Beans + ** and deserialize them at runtime, some RAD tools will generate code that + ** creates the Beans. Examples of Java initialization strings would be:<P> + ** <OL> + ** <LI><CODE>2</CODE></LI> + ** <LI><CODE>"I am a String"</CODE></LI> + ** <LI><CODE>new MyObject(2, "String", new StringBuffer())</CODE></LI> + ** </OL> + ** @return the initialization string for this object in Java. + **/ + public abstract String getJavaInitializationString(); +} diff --git a/libjava/java/beans/PropertyEditorManager.java b/libjava/java/beans/PropertyEditorManager.java new file mode 100644 index 0000000..b64b2a8 --- /dev/null +++ b/libjava/java/beans/PropertyEditorManager.java @@ -0,0 +1,150 @@ +/* java.beans.PropertyEditorManager + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import gnu.java.lang.ClassHelper; + +/** + ** PropertyEditorManager is used to find property editors + ** for various types (not necessarily Beans).<P> + ** + ** It first checks to see if the property editor is + ** already registered; if it is, that property editor is + ** used. Next it takes the type's classname and appends + ** "Editor" to it, and searches first in the class's + ** package and then in the property editor search path.<P> + ** + ** Default property editors are provided for:<P> + ** <OL> + ** <LI>boolean, byte, short, int, long, float, and double</LI> + ** <LI>java.lang.String</LI> + ** <LI>java.awt.Color</LI> + ** <LI>java.awt.Font</LI> + ** <OL> + ** + ** <STRONG>Spec Suggestion:</STRONG> Perhaps an editor for + ** Filename or something like it should be provided. As well + ** as char. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 29 Jul 1998 + **/ + +public class PropertyEditorManager { + static java.util.Hashtable editors = new java.util.Hashtable(); + static String[] editorSearchPath = {"gnu.java.beans.editors","sun.beans.editors"}; + + static { + registerEditor(java.lang.Boolean.TYPE, gnu.java.beans.editors.NativeBooleanEditor.class); + registerEditor(java.lang.Byte.TYPE, gnu.java.beans.editors.NativeByteEditor.class); + registerEditor(java.lang.Short.TYPE, gnu.java.beans.editors.NativeShortEditor.class); + registerEditor(java.lang.Integer.TYPE, gnu.java.beans.editors.NativeIntEditor.class); + registerEditor(java.lang.Long.TYPE, gnu.java.beans.editors.NativeLongEditor.class); + registerEditor(java.lang.Float.TYPE, gnu.java.beans.editors.NativeFloatEditor.class); + registerEditor(java.lang.Double.TYPE, gnu.java.beans.editors.NativeDoubleEditor.class); + registerEditor(java.lang.String.class, gnu.java.beans.editors.StringEditor.class); + registerEditor(java.awt.Color.class, gnu.java.beans.editors.ColorEditor.class); + registerEditor(java.awt.Font.class, gnu.java.beans.editors.FontEditor.class); + } + + /** Beats me why this class can be instantiated, but there + ** you have it. + **/ + public PropertyEditorManager() { } + + /** Register an editor for a class. Replaces old editor + ** if there was one registered before. + ** @param editedClass the class that the property editor + ** will edit. + ** @param editorClass the PropertyEditor class. + **/ + public static void registerEditor(Class editedClass, Class editorClass) { + editors.put(editedClass, editorClass); + } + + /** Returns a new instance of the property editor for the + ** specified class. + ** @param editedClass the class that the property editor + ** will edit. + ** @return a PropertyEditor instance that can edit the + ** specified class. + **/ + public static PropertyEditor findEditor(Class editedClass) { + try { + + Class found = (Class)editors.get(editedClass); + if(found != null) { + return (PropertyEditor)found.newInstance(); + } + + try { + found = Class.forName(editedClass.getName()+"Editor"); + registerEditor(editedClass,found); + return (PropertyEditor)found.newInstance(); + } catch(ClassNotFoundException E) { + } + + String appendName = "." + ClassHelper.getTruncatedClassName(editedClass) + "Editor"; + synchronized(editorSearchPath) { + for(int i=0;i<editorSearchPath.length;i++) { + try { + found = Class.forName(editorSearchPath[i] + appendName); + registerEditor(editedClass,found); + return (PropertyEditor)found.newInstance(); + } catch(ClassNotFoundException E) { + } + } + } + + } catch(InstantiationException E) { + } catch(IllegalAccessException E) { + } + return null; + } + + /** Get the editor search path. + ** As a minor departure from the spec, the default value + ** for the editor search path is "gnu.java.beans.editors", + ** "sun.beans.editors". + ** @return the editor search path. + **/ + public static String[] getEditorSearchPath() { + return editorSearchPath; + } + + /** Set the editor search path. + ** @param editorSearchPath the new value for the editor + ** search path. + **/ + public static void setEditorSearchPath(String[] editorSearchPath) { + synchronized(editorSearchPath) { + PropertyEditorManager.editorSearchPath = editorSearchPath; + } + } +} diff --git a/libjava/java/beans/PropertyEditorSupport.java b/libjava/java/beans/PropertyEditorSupport.java new file mode 100644 index 0000000..6fadacc --- /dev/null +++ b/libjava/java/beans/PropertyEditorSupport.java @@ -0,0 +1,195 @@ +/* java.beans.PropertyEditorSupport + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + ** PropertyEditorSupport helps with PropertyEditors, + ** implementing base functionality that they usually must + ** have but which is a pain to implement. You may extend + ** from this class or use it as a standalone.<P> + ** + ** This class does not do any painting or actual editing. + ** For that, you must use or extend it. See the + ** PropertyEditor class for better descriptions of what + ** the various methods do. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 29 Jul 1998 + **/ + +public class PropertyEditorSupport implements PropertyEditor { + Object eventSource; + Object val; + PropertyChangeSupport pSupport; + + /** Call this constructor when you are deriving from + ** PropertyEditorSupport. + **/ + protected PropertyEditorSupport() { + this.eventSource = this; + this.pSupport = new PropertyChangeSupport(this); + } + + /** Call this constructor when you are using + ** PropertyEditorSupport as a helper object. + ** @param eventSource the source to use when firing + ** property change events. + **/ + protected PropertyEditorSupport(Object eventSource) { + this.eventSource = eventSource; + this.pSupport = new PropertyChangeSupport(this); + } + + /** Set the current value of the property. + ** <STRONG>Implementation Note</STRONG> Sun does not + ** state what exactly this version of the method does. + ** Thus, in this implementation, it sets the value, and + ** then if the old and new values are different, it + ** fires a property change event with no property name + ** and the old and new values. + ** @param val the new value for the property. + **/ + public void setValue(Object val) { + Object oldVal = val; + this.val = val; + if(!oldVal.equals(val)) { + pSupport.firePropertyChange(null,oldVal,val); + } + } + + /** Get the current value of the property. + ** @return the current value of the property. + **/ + public Object getValue() { + return val; + } + + /** Get whether this object is paintable or not. + ** @return <CODE>false</CODE> + **/ + public boolean isPaintable() { + return false; + } + + /** Paint this object. This class does nothing in + ** this method. + **/ + public void paintValue(java.awt.Graphics g, java.awt.Rectangle r) { + } + + /** Get the Java initialization String for the current + ** value of the Object. This class returns gibberish or + ** null (though the spec does not say which).<P> + ** <STRONG>Implementation Note:</STRONG> This class + ** returns the string "@$#^" to make sure the code will + ** be broken, so that you will know to override it when + ** you create your own property editor. + ** @return the Java initialization string. + **/ + public String getJavaInitializationString() { + return "@$#^"; + } + + /** Get the value as text. + ** In this class, you cannot count on getAsText() doing + ** anything useful, although in this implementation I + ** do toString(). + ** @return the value as text. + **/ + public String getAsText() { + return val != null ? val.toString() : "null"; + } + + /** Set the value as text. + ** In this class, you cannot count on setAsText() doing + ** anything useful across implementations. + ** <STRONG>Implementation Note:</STRONG> In this + ** implementation it checks if the String is "null", and + ** if it is, sets the value to null, otherwise it throws + ** an IllegalArgumentException. + ** @param s the text to convert to a new value. + ** @exception IllegalArgumentException if the text is + ** malformed. + **/ + public void setAsText(String s) throws IllegalArgumentException { + if(s.equals("null")) { + setValue(null); + } else { + throw new IllegalArgumentException(); + } + } + + /** Returns a list of possible choices for the value. + ** @return <CODE>null</CODE> + **/ + public String[] getTags() { + return null; + } + + /** Return a custom component to edit the value. + ** @return <CODE>null</CODE> in this class. + **/ + public java.awt.Component getCustomEditor() { + return null; + } + + /** Find out whether this property editor supports a + ** custom component to edit its value. + ** @return <CODE>false</CODE> in this class. + **/ + public boolean supportsCustomEditor() { + return false; + } + + /** Add a property change listener to this property editor. + ** @param l the listener to add. + **/ + public void addPropertyChangeListener(PropertyChangeListener l) { + pSupport.addPropertyChangeListener(l); + } + + /** Remove a property change listener from this property editor. + ** @param l the listener to remove. + **/ + public void removePropertyChangeListener(PropertyChangeListener l) { + pSupport.removePropertyChangeListener(l); + } + + + /** Notify people that we've changed, although we don't + ** tell them just how. The only thing I can think of to + ** send in the event is the new value (since the old value + ** is unavailable and there is no property name). + ** I confess I do not understand the point of this method. + **/ + public void firePropertyChange() { + pSupport.firePropertyChange(null,null,val); + } +} + diff --git a/libjava/java/beans/PropertyVetoException.java b/libjava/java/beans/PropertyVetoException.java new file mode 100644 index 0000000..51a5642 --- /dev/null +++ b/libjava/java/beans/PropertyVetoException.java @@ -0,0 +1,55 @@ +/* java.beans.PropertyVetoException + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + ** PropertyVetoException is thrown when a VetoableChangeListener doesn't like the proposed change. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 31 May 1998 + ** @see java.beans.VetoableChangeListener + **/ + +public class PropertyVetoException extends Exception { + PropertyChangeEvent changeEvent; + + /** Instantiate this exception with the given message and property change. + ** @param msg the reason for the veto. + ** @param changeEvent the PropertyChangeEvent that was thrown. + **/ + public PropertyVetoException(String msg, PropertyChangeEvent changeEvent) { + super(msg); + this.changeEvent = changeEvent; + } + + /** Get the PropertyChange event that was vetoed. **/ + public PropertyChangeEvent getPropertyChangeEvent() { + return changeEvent; + } +} diff --git a/libjava/java/beans/SimpleBeanInfo.java b/libjava/java/beans/SimpleBeanInfo.java new file mode 100644 index 0000000..e8b6777 --- /dev/null +++ b/libjava/java/beans/SimpleBeanInfo.java @@ -0,0 +1,127 @@ +/* java.beans.SimpleBeanInfo + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +import java.awt.*; + +/** + ** SimpleBeanInfo is a class you may extend to more easily + ** provide select information to the Introspector. It + ** implements all of the methods in BeanInfo by returning + ** null and forces the Introspector to behave exactly as + ** if there were no BeanInfo class at all (Introspecting + ** everything).<P> + ** + ** Overriding one or two of these functions + ** to give explicit information on only those things you + ** wish to give explicit information is perfectly safe, + ** and even desirable.<P> + ** + ** See the BeanInfo class for information on what the + ** various methods actually do. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.1.0, 29 Jul 1998 + ** @see java.beans.BeanInfo + **/ + +public class SimpleBeanInfo implements BeanInfo { + /** Force Introspection of the general bean info. + ** @return <CODE>null</CODE>. + **/ + public BeanDescriptor getBeanDescriptor() { + return null; + } + + /** Force Introspection of the events this Bean type + ** fires. + ** @return <CODE>null</CODE> + **/ + public EventSetDescriptor[] getEventSetDescriptors() { + return null; + } + + /** Say that there is no "default" event set. + ** @return <CODE>-1</CODE>. + **/ + public int getDefaultEventIndex() { + return -1; + } + + /** Force Introspection of the Bean properties. + ** @return <CODE>null</CODE>. + **/ + public PropertyDescriptor[] getPropertyDescriptors() { + return null; + } + + /** Say that there is no "default" property. + ** @return <CODE>-1</CODE>. + **/ + public int getDefaultPropertyIndex() { + return -1; + } + + /** Force Introspection of the Bean's methods. + ** @return <CODE>null</CODE>. + **/ + public MethodDescriptor[] getMethodDescriptors() { + return null; + } + + /** Tell the Introspector to go look for other BeanInfo + ** itself. + ** @return <CODE>null</CODE>. + **/ + public BeanInfo[] getAdditionalBeanInfo() { + return null; + } + + /** Say that this Bean has no icons. + ** @param iconType the type of icon + ** @return <CODE>null</CODE>. + **/ + public Image getIcon(int iconType) { + return null; + } + + /** Helper method to load an image using the Bean class + ** getResource() method on the BeanInfo class (using + ** getClass(), since you'll extend this class to get + ** the BeanInfo). Basically it's assumed that the Bean + ** and its BeanInfo are both loaded by the same + ** ClassLoader, generally a reasonable assumption. + ** @param location the URL relative + ** @return the Image in question. + **/ + public Image loadImage(String location) { + return Toolkit.getDefaultToolkit().getImage(getClass().getResource(location)); + } +} + diff --git a/libjava/java/beans/VetoableChangeListener.java b/libjava/java/beans/VetoableChangeListener.java new file mode 100644 index 0000000..253d712 --- /dev/null +++ b/libjava/java/beans/VetoableChangeListener.java @@ -0,0 +1,62 @@ +/* java.beans.VetoableChangeListener + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + ** VetoableChangeListener allows a class to monitor + ** proposed changes to properties of a Bean and, if + ** desired, prevent them from occurring.<P> + ** + ** A vetoableChange() event will be fired <EM>before</EM> + ** the property has changed. If any listener rejects the + ** change by throwing the PropertyChangeException, a new + ** vetoableChange() event will be fired to all listeners + ** who received a vetoableChange() event in the first + ** place informing them of a reversion to the old value. + ** The value, of course, never actually changed.<P> + ** + ** <STRONG>Note:</STRONG> This class may not be reliably + ** used to determine whether a property has actually + ** changed. Use the PropertyChangeListener interface + ** for that instead. + ** + ** @author John Keiser + ** @version 1.1.0, 29 Jul 1998 + ** @since JDK1.1 + ** @see java.beans.PropertyChangeListener + ** @see java.beans.VetoableChangeSupport + **/ + +public interface VetoableChangeListener { + /** Fired before a Bean's property changes. + ** @param e the change (containing the old and new values) + ** @exception PropertyChangeException if the listener + ** does not desire the change to be made. + **/ + public abstract void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException; +} diff --git a/libjava/java/beans/VetoableChangeSupport.java b/libjava/java/beans/VetoableChangeSupport.java new file mode 100644 index 0000000..6d0ff0c --- /dev/null +++ b/libjava/java/beans/VetoableChangeSupport.java @@ -0,0 +1,245 @@ +/* + * java.beans.VetoableChangeSupport: part of the Java Class Libraries project. + * Copyright (C) 1998 Free Software Foundation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package java.beans; +import java.util.Hashtable; +import java.util.Vector; + +/** + ** VetoableChangeSupport makes it easy to fire vetoable + ** change events and handle listeners as well as reversion + ** of old values when things go wrong. + ** + ** @author John Keiser + ** @since JDK1.1 + ** @version 1.2.0, 15 Mar 1998 + **/ + +public class VetoableChangeSupport implements java.io.Serializable { + Hashtable propertyListeners = new Hashtable(); + Vector listeners = new Vector(); + Object bean; + + /** Create VetoableChangeSupport to work with a specific + ** source bean. + ** @param bean the source bean to use. + **/ + public VetoableChangeSupport(Object bean) { + this.bean = bean; + } + + /** Adds a VetoableChangeListener to the list of listeners. + ** All property change events will be sent to this listener. + ** <P> + ** + ** The listener add is not unique: that is, <em>n</em> adds with + ** the same listener will result in <em>n</em> events being sent + ** to that listener for every property change. + ** <P> + ** + ** Adding a null listener will cause undefined behavior. + ** + ** @param l the listener to add. + **/ + public void addVetoableChangeListener(VetoableChangeListener l) { + listeners.addElement(l); + } + + /** Adds a VetoableChangeListener listening on the specified property. + ** Events will be sent to the listener for that particular property. + ** <P> + ** + ** The listener add is not unique; that is, <em>n</em> adds on a + ** particular property for a particular listener will result in + ** <em>n</em> events being sent to that listener when that + ** property is changed. + ** <P> + ** + ** The effect is cumulative, too; if you are registered to listen + ** to receive events on all property changes, and then you + ** register on a particular property, you will receive change + ** events for that property twice. + ** <P> + ** + ** Adding a null listener will cause undefined behavior. + ** + ** @param propertyName the name of the property to listen on. + ** @param l the listener to add. + **/ + public void addVetoableChangeListener(String propertyName, VetoableChangeListener l) { + synchronized(propertyListeners) { + Vector v = (Vector)propertyListeners.get(propertyName); + try { + v.addElement(l); + } catch(NullPointerException e) { + /* If v is not found, create a new vector. */ + v = new Vector(); + v.addElement(l); + propertyListeners.put(propertyName, v); + } + } + } + + /** Removes a VetoableChangeListener from the list of listeners. + ** If any specific properties are being listened on, they must + ** be deregistered by themselves; this will only remove the + ** general listener to all properties. + ** <P> + ** + ** If <code>add()</code> has been called multiple times for a + ** particular listener, <code>remove()</code> will have to be + ** called the same number of times to deregister it. + ** + ** @param l the listener to remove. + **/ + public void removeVetoableChangeListener(VetoableChangeListener l) { + listeners.removeElement(l); + } + + /** Removes a VetoableChangeListener from listening to a specific property. + ** <P> + ** + ** If <code>add()</code> has been called multiple times for a + ** particular listener on a property, <code>remove()</code> will + ** have to be called the same number of times to deregister it. + ** + ** @param propertyName the property to stop listening on. + ** @param l the listener to remove. + **/ + public void removeVetoableChangeListener(String propertyName, VetoableChangeListener l) { + synchronized(propertyListeners) { + Vector v = (Vector)propertyListeners.get(propertyName); + try { + v.removeElement(l); + if(v.size() == 0) { + propertyListeners.remove(propertyName); + } + } catch(NullPointerException e) { + /* if v is not found, do nothing. */ + } + } + } + + + /** Fire a VetoableChangeEvent to all the listeners. + ** If any listener objects, a reversion event will be sent to + ** those listeners who received the initial event. + ** + ** @param proposedChange the event to send. + ** @exception PropertyVetoException if the change is vetoed. + **/ + public void fireVetoableChange(PropertyChangeEvent proposedChange) throws PropertyVetoException { + int currentListener=0; + try { + for(;currentListener<listeners.size();currentListener++) { + ((VetoableChangeListener)listeners.elementAt(currentListener)).vetoableChange(proposedChange); + } + } catch(PropertyVetoException e) { + PropertyChangeEvent reversion = new PropertyChangeEvent(proposedChange.getSource(),proposedChange.getPropertyName(),proposedChange.getNewValue(),proposedChange.getOldValue()); + for(int sendAgain=0;sendAgain<currentListener;sendAgain++) { + try { + ((VetoableChangeListener)listeners.elementAt(sendAgain)).vetoableChange(reversion); + } catch(PropertyVetoException e2) { + } + } + throw e; + } + + Vector moreListeners = (Vector)propertyListeners.get(proposedChange.getPropertyName()); + if(moreListeners != null) { + try { + for(currentListener = 0; currentListener < moreListeners.size(); currentListener++) { + ((VetoableChangeListener)moreListeners.elementAt(currentListener)).vetoableChange(proposedChange); + } + } catch(PropertyVetoException e) { + PropertyChangeEvent reversion = new PropertyChangeEvent(proposedChange.getSource(),proposedChange.getPropertyName(),proposedChange.getNewValue(),proposedChange.getOldValue()); + for(int sendAgain=0;sendAgain<listeners.size();sendAgain++) { + try { + ((VetoableChangeListener)listeners.elementAt(currentListener)).vetoableChange(proposedChange); + } catch(PropertyVetoException e2) { + } + } + + for(int sendAgain=0;sendAgain<currentListener;sendAgain++) { + try { + ((VetoableChangeListener)moreListeners.elementAt(sendAgain)).vetoableChange(reversion); + } catch(PropertyVetoException e2) { + } + } + throw e; + } + } + } + + /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners. + ** If any listener objects, a reversion event will be sent to + ** those listeners who received the initial event. + ** + ** @param propertyName the name of the property that + ** changed. + ** @param oldVal the old value. + ** @param newVal the new value. + ** @exception PropertyVetoException if the change is vetoed. + **/ + public void fireVetoableChange(String propertyName, Object oldVal, Object newVal) throws PropertyVetoException { + fireVetoableChange(new PropertyChangeEvent(bean,propertyName,oldVal,newVal)); + } + + /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners. + ** If any listener objects, a reversion event will be sent to + ** those listeners who received the initial event. + ** + ** @param propertyName the name of the property that + ** changed. + ** @param oldVal the old value. + ** @param newVal the new value. + ** @exception PropertyVetoException if the change is vetoed. + **/ + public void fireVetoableChange(String propertyName, boolean oldVal, boolean newVal) throws PropertyVetoException { + fireVetoableChange(new PropertyChangeEvent(bean,propertyName,new Boolean(oldVal),new Boolean(newVal))); + } + + /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners. + ** If any listener objects, a reversion event will be sent to + ** those listeners who received the initial event. + ** + ** @param propertyName the name of the property that + ** changed. + ** @param oldVal the old value. + ** @param newVal the new value. + ** @exception PropertyVetoException if the change is vetoed. + **/ + public void fireVetoableChange(String propertyName, int oldVal, int newVal) throws PropertyVetoException { + fireVetoableChange(new PropertyChangeEvent(bean,propertyName,new Integer(oldVal),new Integer(newVal))); + } + + + /** Tell whether the specified property is being listened on or not. + ** This will only return <code>true</code> if there are listeners + ** on all properties or if there is a listener specifically on this + ** property. + ** + ** @param propertyName the property that may be listened on + ** @return whether the property is being listened on + **/ + public boolean hasListeners(String propertyName) { + return listeners.size() > 0 || propertyListeners.get(propertyName) != null; + } +} diff --git a/libjava/java/beans/Visibility.java b/libjava/java/beans/Visibility.java new file mode 100644 index 0000000..ca8c404 --- /dev/null +++ b/libjava/java/beans/Visibility.java @@ -0,0 +1,74 @@ +/* java.beans.Visibility + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans; + +/** + * Visibility is an interface a Bean may implement so that the environment + * can tell the Bean whether there is a GUI or not, and so that the Bean + * can tell the environment whether it needs one or can run without one. + * <P> + * + * Sun decided not to use standard Introspection patterns so that these + * methods did not get included when the Introspector made its sweep on + * the class. + * + * @author John Keiser + * @since JDK1.1 + * @version 1.1.0, 29 Jul 1998 + */ + +public interface Visibility { + /** + * Tells whether the Bean can run without a GUI or not. + * @return false if Bean can run without a GUI, else true. + */ + public abstract boolean needsGui(); + + /** + * Tells whether Bean is trying not to use the GUI. + * If needsGui() is true, this method should always return false. + * @return true if definitely not using GUI, otherwise false. + */ + public abstract boolean avoidingGui(); + + /** + * Tells the Bean not to use GUI methods. + * If needsGUI() is false, then after this method is called, + * avoidingGui() should return true. + */ + public abstract void dontUseGui(); + + /** + * Tells the Bean it may use the GUI. + * The Bean is not required to use the GUI in this case, it is + * merely being <EM>permitted</EM> to use it. If needsGui() is + * false, avoidingGui() may return true or false after this method + * is called. + */ + public abstract void okToUseGui(); +} diff --git a/libjava/java/beans/beancontext/BeanContext.java b/libjava/java/beans/beancontext/BeanContext.java new file mode 100644 index 0000000..d5274d8 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContext.java @@ -0,0 +1,261 @@ +/* java.beans.beancontext.BeanContext + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.util.Collection; +import java.beans.Visibility; +import java.beans.DesignMode; +import java.net.URL; +import java.io.InputStream; +import java.io.IOException; + +/** + * Acts as a container for sub-beans and as a sub-bean, + * so that an entire hierarchy of beans can be made up of + * <code>BeanContext</code>s. + * <P> + * + * Since I can't sprinkle the <code>Collections</code> interface + * documentation with special information for <code>BeanContext</code> + * implementors, I'll have to document special requirements for + * implementors of those functions here. + * <P> + * + * <code><strong>add()</strong></code> or <code>addAll()</code>: + * <br> + * <OL> + * <LI> + * May add any <code>Object</code> into the hierarchy as well as a + * <code>BeanContextChild</code>, <code>BeanContext</code> or + * <code>BeanContextProxy</code> object. + * This way, any Bean can be in the hierarchy. + * </LI> + * <LI> + * Must synchronize on <code>BeanContext.globalHierarchyLock</code>. + * </LI> + * <LI> + * Don't add the <code>Object</code> if it's already there (only once + * per <code>BeanContext</code>). + * </LI> + * <LI> + * If it is a <code>BeanContextChild</code> implementor, call + * <code>setBeanContext()</code> on it. If it's a + * <code>BeanContextProxy</code> implementor, call + * <code>getBeanContextProxy().setBeanContext()</code> on it. + * If <code>setBeanContext()</code> vetoes the change, back out + * all changes so far and throw <code>IllegalStateException</code>. + * </LI> + * <LI> + * If it (or its proxy) implements <code>Visibility</code>, call + * <code>dontUseGui()</code> or <code>okToUseGui()</code> on it, + * depending on whether you (the <code>BeanContext</code>) feel like + * allowing it to use the GUI or not. + * </LI> + * <LI> + * If it implements <code>BeanContextChild</code> or + * <code>BeanContextProxy</code>, register yourself (the + * <code>BeanContext</code>) as both a + * <code>PropertyChangeListener</code> and + * <code>VetoableChangeListener</code> on the "beanContext" + * property (it may also add itself on any other properties it wishes + * to). + * </LI> + * <LI> + * If it is a listener or event source that you (the + * <code>BeanContext</code>) are interested in, you may register + * yourself to it or register it to you. + * </LI> + * <LI> + * Fire a <code>java.beans.beancontext.BeanContextMembershipEvent</code> + * before exiting. <code>addAll()</code> should wait until everything + * is done changing before firing the event (or events) so that if a + * failure occurs, the backing-out process can proceed without any + * events being fired at all. + * </LI> + * </OL> + * <P> + * + * <code><strong>remove()</strong></code> or <code>removeAll()</code>: + * <br> + * <OL> + * <LI> + * Must synchronize on <code>BeanContext.globalHierarchyLock</code>. + * </LI> + * <LI> + * If the specified <code>Object</code> is not a child of this + * <code>BeanContext</code>, just exit without performing any actions. + * </LI> + * <LI> + * Remove the <code>Object</code> from your collection of children. + * </LI> + * <LI> + * If it is a <code>BeanContextChild</code> implementor, call + * <code>setBeanContext(null)</code> on it. If it's a + * <code>BeanContextProxy</code> implementor, call + * <code>getBeanContextProxy().setBeanContext(null)</code> on it. + * If <code>setBeanContext()</code> vetoes the change, back out + * all changes so far and throw <code>IllegalStateException</code>. + * </LI> + * <LI> + * If you registered the <code>Object</code> to listen to you or + * registered yourself as a listener on the <code>Object</code> during + * <code>add()</code> or <code>addAll()</code>, undo the registration + * bycalling the appropriate <code>removeListener()</code> method. + * </LI> + * <LI> + * Fire a <code>java.beans.beancontext.BeanContextMembershipEvent</code> + * before exiting. <code>removeAll()</code> should wait until + * everything is done changing before firing the event (or events) so + * that if a failure occurs, the backing-out process can proceed + * without any events being fired at all. + * </LI> + * </OL> + * <P> + * + * <code>addAll()</code>, <code>removeAll()</code>, + * <code>retainAll()</code> and <code>clear()</code> do not need to be + * implemented, but may be if so desired. + * <P> + * + * Similarly, <code>Visibility</code> and <code>DesignMode</code> methods + * should propagate changed values to children that implement interfaces + * of the same name. + * <P> + * + * A hierarchy of beans is mainly useful so that different sets of beans + * can be established, each with their own set of resources. + * + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContext + extends Collection, BeanContextChild, Visibility, DesignMode { + + /** + * The global lock on changing any BeanContext hierarchy. + * It kinda sucks that there is only one lock, since there can be + * multiple hierarchies. Oh well, I didn't design, I just code. + * <P> + * + * Methods that must (or do) synchronize on the global lock: + * <BR> + * <UL> + * <LI> + * Implementors of <CODE>BeanContext.add()</CODE> and <code>addAll()</code> + * </LI> + * </UL> + * @fixme fill in the rest of the methods which use the global lock. + */ + public static final Object globalHierarchyLock = new Object(); + + /** + * Instantiate a Bean using this Bean's <code>ClassLoader</code> + * and this <code>BeanContext</code> as the parent. + * <P> + * + * This method exists mainly so that <code>BeanContext</code> + * implementations can perform extra actions on Beans that are + * created within them. + * + * @param beanName the name of the bean to instantiate + * @return the created Bean + * + * @see java.beans.Beans#instantiate(java.lang.ClassLoader,java.lang.String) + * @see java.beans.Beans#instantiate(java.lang.ClassLoader,java.lang.String,java.lang.BeanContext) + * @exception IOException if there is an I/O problem during + * instantiation. + * @exception ClassNotFoundException if a serialized Bean's class + * is not found. + */ + public Object instantiateChild(String beanName) + throws IOException, + ClassNotFoundException; + + /** + * Get a resource. The <code>BeanContext</code> will typically + * call <code>ClassLoader.getResource()</code>, but may do it any + * way it wants to. This allows a <code>BeanContext</code> to + * have its own set of resources separate from the rest of the + * system. + * <P> + * + * Beans should call this method on their parent rather than the + * associated <code>ClassLoader</code> method. + * <P> + * + * I am assuming, but am not entirely sure, that if a + * <code>BeanContext</code> cannot find a resource, its + * responsibility is to call the <code>getResource</code> method + * of its parent <code>BeanContext</code>. + * + * @return a URL to the requested resource. + * @param resourceName the name of the resource requested. + * @param requestor a reference to the child requesting the resource. + * @see java.lang.ClassLoader#getResource(java.lang.String) + */ + public URL getResource(String resourceName, BeanContextChild requestor); + + /** + * Get a resource as a stream. The <code>BeanContext</code> will + * typically call <code>ClassLoader.getResourceAsStream()</code>, + * but may do it any way it wants to. This allows a + * <code>BeanContext</code>'s children to have their own set of + * resources separate from the rest of the system. + * <P> + * + * Beans should call this method on their parent rather than the + * associated <code>ClassLoader</code> method. + * <P> + * + * I am assuming, but am not entirely sure, that if a + * <code>BeanContext</code> cannot find a resource, its + * responsibility is to call the <code>getResourceAsStream</code> + * method of its parent <code>BeanContext</code>. + * + * @return the requested resource as a stream. + * @param resourceName the name of the resource requested. + * @param requestor a reference to the child requesting the resource. + * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String) + */ + public InputStream getResourceAsStream(String resourceName, BeanContextChild requestor); + + /** + * Add a listener on changes to the membership of this + * <code>BeanContext</code> object. + * @param listener the listener to add. + */ + public void addBeanContextMembershipListener(BeanContextMembershipListener listener); + + /** + * Remove a listener on changes to the membership of this + * <code>BeanContext</code> object. + * @param listener the listener to remove. + */ + public void removeBeanContextMembershipListener(BeanContextMembershipListener listener); +} diff --git a/libjava/java/beans/beancontext/BeanContextChild.java b/libjava/java/beans/beancontext/BeanContextChild.java new file mode 100644 index 0000000..d8bcb5e --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextChild.java @@ -0,0 +1,162 @@ +/* java.beans.beancontext.BeanContextChild + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.beans.PropertyChangeListener; +import java.beans.VetoableChangeListener; +import java.beans.PropertyVetoException; + +/** + * Beans implement this to get information about the execution environment and its services and to be placed in the hierarchy. + * <P> + * + * The difference between a <code>BeanContext</code> and a + * <code>BeanContextChild</code>, mainly, is that a + * <code>BeanContext</code> may be a parent. + * <P> + * + * <code>BeanContextChild</code> instances will be serialized at some + * point in their life, but you need to make sure your bean context does + * not contain a serializable reference (directly or indirectly) to the + * parent <code>BeanContext</code>, to any of the other + * <code>BeanContext</code>s in the tree, or to any resources obtained + * via the <code>BeanContextServices</code> interface. One way to do this + * is to mark any fields that contain such references as + * <code>transient</code>. Another way is to use a custom serializer. + * <P> + * + * If you do not do this, when the <code>BeanContext</code> is serialized, + * all the other <code>BeanContext</code>s and other unnecessary things + * will be serialized along with it. + * <P> + * + * Before dying, a <code>BeanContextChild</code> should call + * <code>getBeanContext().remove(this)</code> to detach from the + * hierarchy and exit cleanly. + * + * @author John Keiser + * @since JDK1.2 + * @see java.beans.beancontext.BeanContext + */ + +public interface BeanContextChild { + /** + * Set the parent <code>BeanContext</code>. + * <P> + * + * This method is called from <code>BeanContext.add()</code> and + * should not be called directly. + * <P> + * + * When this Object is being added to a new BeanContext or moved + * from an old one, a non-null value will be passed in. + * <P> + * + * When this Object is being removed from the current + * <code>BeanContext</code>, <code>setBeanContext()</code> will + * receive the parameter <code>null</code>. + * <P> + * + * When being removed from the current <code>BeanContext</code>, + * it is the <code>BeanContextChild</code>'s responsibility to + * release all services it has obtained. + * <P> + * + * This change should generate <code>PropertyChangeEvent</code> + * and <code>VetoableChangeEvent</code>s with the property name + * "beanContext". If the change is vetoed, it must re-throw the + * exception and not change anything. In this way, the parent + * <code>BeanContextChild</code>, who has registered himself with + * you, will have a chance to remove this child from its + * collection. + * <P> + * + * If the Bean does not wish to change the parent or be removed + * from one, it may throw the <code>PropertyVetoException</code>. + * If you veto a <code>setBeanContext(null)</code> call, then you + * should try your hardest to remedy whatever problem is keeping + * you from being removed from the <code>BeanContext</code> so + * that you can <em>not</em> veto it the next time. + * Otherwise, nasty pathological recursion stuff could occur in + * certain situations. + * <P> + * + * If you do veto the change, you must first back out any changes + * you made prior to the veto. Best not to make any such changes + * prior to the veto in the first place. + * <P> + * + * This method is called from <code>BeanContext.add()</code> and + * should not be called directly. + * + * @param parent the new parent for the <code>BeanContextChild</code>, + * or <code>null</code> to signify removal from a tree. + * @exception PropertyVetoException if the + * <code>BeanContextChild</code> implementor does not + * wish to have its parent changed. + */ + public void setBeanContext(BeanContext parent) + throws PropertyVetoException; + + /** + * Get the parent <code>BeanContext</code>. + * @return the parent <code>BeanContext</code>. + */ + public BeanContext getBeanContext(); + + /** + * Add a listener that will be notified when a specific property changes. + * @param prop the name of the property to listen on + * @param listener the listener to listen on the property. + */ + public void addPropertyChangeListener(String prop, PropertyChangeListener listener); + + /** + * Remove a listener to a certain property. + * @param prop the name of the property being listened on + * @param listener the listener listening on the property. + */ + public void removePropertyChangeListener(String prop, PropertyChangeListener listener); + + /** + * Add a listener that will be notified when a specific property + * change is requested (a PropertyVetoException may be thrown) as + * well as after the change is successfully made. + * + * @param prop the name of the property to listen on + * @param listener the listener to listen on the property. + */ + public void addVetoableChangeListener(String prop, VetoableChangeListener listener); + + /** + * Remove a listener to a certain property. + * @param prop the name of the property being listened on + * @param listener the listener listening on the property. + */ + public void removeVetoableChangeListener(String prop, VetoableChangeListener listener); +} diff --git a/libjava/java/beans/beancontext/BeanContextChildComponentProxy.java b/libjava/java/beans/beancontext/BeanContextChildComponentProxy.java new file mode 100644 index 0000000..f8ef7ca --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextChildComponentProxy.java @@ -0,0 +1,49 @@ +/* java.beans.beancontext.BeanContextChildComponentProxy + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.awt.Component; + +/** + * Interface for <code>BeanContextChild</code>s which wish to associate an + * AWT component with them. The proxy is provided because the + * <code>addPropertyChangeListener()</code> method would conflict with + * <code>Component</code> if you tried to extend. + * + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContextChildComponentProxy { + /** + * Get the <code>Component</code> associated with this <code>BeanContextChild</code>. + * @return the <code>Component</code> associated with this + * <code>BeanContextChild</code>. + */ + public Component getComponent(); +} diff --git a/libjava/java/beans/beancontext/BeanContextChildSupport.java b/libjava/java/beans/beancontext/BeanContextChildSupport.java new file mode 100644 index 0000000..08d2a71 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextChildSupport.java @@ -0,0 +1,356 @@ +/* java.beans.beancontext.BeanContextChildSupport + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.beans.PropertyChangeListener; +import java.beans.VetoableChangeListener; +import java.beans.PropertyVetoException; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeSupport; +import java.beans.VetoableChangeSupport; +import java.io.Serializable; + +/** + * Support for creating a <code>BeanContextChild</code>. + * This class contains the most common implementations of the methods in + * the <code>BeanContextChild</code> + * + * @specnote This class is not very well specified. I had to "fill in the + * blanks" in most places with what I thought was reasonable + * behavior. If there are problems, let me know. + * + * @author John Keiser + * @since JDK1.2 + * @see java.beans.beancontext.BeanContextChild + */ + +public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable { + /** + * The peer on which to perform <code>set</code> actions. + * This is here so that this class can be used as a peer. + * <P> + * + * When extending this class, this variable will be set to + * <code>this</code>. + */ + public BeanContextChild beanContextChildPeer; + + /** + * The parent <code>BeanContext</code>. + */ + protected transient BeanContext beanContext; + + /** + * If <code>setBeanContext()</code> was vetoed once before, this + * is set to <code>true</code> so that the next time, vetoes will + * be ignored. + */ + protected transient boolean rejectedSetBCOnce; + + /** + * Listeners are registered here and events are fired through here. + */ + protected PropertyChangeSupport pcSupport; + + /** + * Listeners are registered here and events are fired through here. + */ + protected VetoableChangeSupport vcSupport; + + + /** + * Create a new <code>BeanContextChildSupport</code> with itself as the peer. + * This is meant to be used when you subclass + * <code>BeanContextChildSupport</code> to create your child. + */ + public BeanContextChildSupport() { + this(null); + }; + + /** + * Create a new <code>BeanContextChildSupport</code> with the specified peer. + * @param peer the peer to use, or <code>null</code> to specify + * <code>this</code>. + */ + public BeanContextChildSupport(BeanContextChild peer) { + if(peer == null) { + peer = this; + } + + beanContextChildPeer = peer; + pcSupport = new PropertyChangeSupport(peer); + vcSupport = new VetoableChangeSupport(peer); + } + + /** + * Set the parent <code>BeanContext</code>. + * <P> + * + * When this Object is being added to a new BeanContext or moved + * from an old one, a non-null value will be passed in. + * <P> + * + * When this Object is being removed from the current + * <code>BeanContext</code>, <code>setBeanContext()</code> will + * receive the parameter <code>null</code>. + * <P> + * + * Order of events: + * <OL> + * <LI> + * If the new <code>BeanContext</code> is the same as the old + * one, nothing happens. + * </LI> + * <LI> + * If the change has not been rejected or vetoed before, call + * <code>validatePendingSetBeanContext()</code>. If this call + * returns <code>false</code>, the change is rejected and a + * <code>PropertyVetoException</code> is thrown. + * </LI> + * <LI> + * If the change has not been rejected or vetoed before, + * <code>VetoableChangeEvent</code>s are fired with the name + * <code>"beanContext"</code>, using the + * <code>fireVetoableChange()</code> method. If a veto + * occurs, reversion events are fired using the same method, + * the change is rejected, and the veto is rethrown. + * </LI> + * <LI> + * <code>releaseBeanContextResources()</code> is called. + * </LI> + * <LI> + * The change is made. + * </LI> + * <LI> + * <code>PropertyChangeEvent</code>s are fired using the + * <code>firePropertyChange()</code> method. + * </LI> + * <LI> + * <code>initializeBeanContextResources()</code> is called. + * </LI> + * </OL> + * <P> + * + * @param newBeanContext the new parent for the + * <code>BeanContextChild</code>, or <code>null</code> to + * signify removal from a tree. + * @exception PropertyVetoException if the + * <code>BeanContextChild</code> implementor does not + * wish to have its parent changed. + */ + public void setBeanContext(BeanContext newBeanContext) + throws PropertyVetoException { + synchronized(beanContextChildPeer) { + if(newBeanContext == beanContext) + return; + + if(!rejectedSetBCOnce) { + if(!validatePendingSetBeanContext(newBeanContext)) { + rejectedSetBCOnce = true; + throw new PropertyVetoException("validatePendingSetBeanContext() rejected change", + new PropertyChangeEvent(beanContextChildPeer, "beanContext", beanContext, newBeanContext)); + } + try { + fireVetoableChange("beanContext", beanContext, newBeanContext); + } catch(PropertyVetoException e) { + rejectedSetBCOnce = true; + throw e; + } + } + + releaseBeanContextResources(); + + beanContext = newBeanContext; + rejectedSetBCOnce = false; + + firePropertyChange("beanContext", beanContext, newBeanContext); + + initializeBeanContextResources(); + } + } + + /** + * Get the parent <code>BeanContext</code>. + * @return the parent <code>BeanContext</code>. + */ + public BeanContext getBeanContext() { + return beanContext; + } + + /** + * Get the peer (or <code>this</code> if there is no peer). + * @return the peer, or <code>this</code> if there is no peer. + */ + public BeanContextChild getBeanContextChildPeer() { + return beanContextChildPeer; + } + + /** + * Determine whether there is a peer. + * This is true iff <code>getBeanContextChildPeer() == this</code>. + * @return whether there is a peer. + */ + public boolean isDelegated() { + return beanContextChildPeer == this; + } + + /** + * Add a listener that will be notified when a specific property changes. + * @param propertyName the name of the property to listen on. + * @param listener the listener to listen on the property. + */ + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcSupport.addPropertyChangeListener(propertyName, listener); + } + + /** + * Remove a listener to a certain property. + * + * @param propertyName the name of the property being listened on. + * @param listener the listener listening on the property. + */ + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcSupport.removePropertyChangeListener(propertyName, listener); + } + + /** + * Add a listener that will be notified when a specific property + * change is requested (a PropertyVetoException may be thrown) as + * well as after the change is successfully made. + * + * @param propertyName the name of the property to listen on. + * @param listener the listener to listen on the property. + */ + public void addVetoableChangeListener(String propertyName, VetoableChangeListener listener) { + vcSupport.addVetoableChangeListener(propertyName, listener); + } + + /** + * Remove a listener to a certain property. + * + * @param propertyName the name of the property being listened on + * @param listener the listener listening on the property. + */ + public void removeVetoableChangeListener(String propertyName, VetoableChangeListener listener) { + vcSupport.removeVetoableChangeListener(propertyName, listener); + } + + /** + * Fire a property change. + * + * @param propertyName the name of the property that changed + * @param oldVal the old value of the property + * @param newVal the new value of the property + */ + public void firePropertyChange(String propertyName, Object oldVal, Object newVal) { + pcSupport.firePropertyChange(propertyName, oldVal, newVal); + } + + /** + * Fire a vetoable property change. + * + * @param propertyName the name of the property that changed + * @param oldVal the old value of the property + * @param newVal the new value of the property + * @exception PropertyVetoException if the change is vetoed. + */ + public void fireVetoableChange(String propertyName, Object oldVal, Object newVal) + throws PropertyVetoException { + vcSupport.fireVetoableChange(propertyName, oldVal, newVal); + } + + /** + * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked. + * If you have a reference to such a service, it should be + * discarded and may no longer function properly. + * <code>getService()</code> will no longer work on the specified + * service class after this event has been fired. + * <P> + * + * <EM>This method is meant to be overriden.</EM> + * <code>BeanContextChildSupport</code>'s implementation does + * nothing. + * + * @param event the service revoked event. + * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean) + */ + public void serviceRevoked(BeanContextServiceRevokedEvent event) { + } + + /** + * Called by <code>BeanContextServices</code> whenever a service is made available. + * <P> + * + * <EM>This method is meant to be overriden.</EM> + * <code>BeanContextChildSupport</code>'s implementation does + * nothing. + * + * @param event the service revoked event, with useful information + * about the new service. + */ + public void serviceAvailable(BeanContextServiceAvailableEvent event) { + } + + /** + * Called by <code>setBeanContext()</code> to determine whether the set should be rejected. + * <P> + * + * <EM>This method is meant to be overriden.</EM> + * <code>BeanContextChildSupport</code>'s implementation simply + * returns <code>true</code>. + * + * @param newBeanContext the new parent. + * @return whether to allow the parent to be changed to the new + * value. + */ + public boolean validatePendingSetBeanContext(BeanContext newBeanContext) { + return true; + } + + /** + * Called by <code>setBeanContext()</code> to release resources of a what will soon no longer be the parent. + * <P> + * + * <EM>This method is meant to be overriden.</EM> + * <code>BeanContextChildSupport</code>'s implementation does + * nothing. + */ + protected void releaseBeanContextResources() { + } + + /** + * Called by <code>setBeanContext()</code> to grab resources when the parent has been set. + * <P> + * + * <EM>This method is meant to be overriden.</EM> + * <code>BeanContextChildSupport</code>'s implementation does + * nothing. + */ + protected void initializeBeanContextResources() { + } +} diff --git a/libjava/java/beans/beancontext/BeanContextContainerProxy.java b/libjava/java/beans/beancontext/BeanContextContainerProxy.java new file mode 100644 index 0000000..28d967b0 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextContainerProxy.java @@ -0,0 +1,52 @@ +/* java.beans.beancontext.BeanContextContainerProxy + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.awt.Container; + +/** + * Interface for <code>BeanContext</code>s which wish to associate an + * AWT container with them. The proxy is provided because the + * <code>addPropertyChangeListener()</code> and <code>add()</code> methods + * would conflict with <code>Component</code> and <code>Container</code> + * if you tried to extend. + * + * @specnote It is unclear whether anything besides <code>BeanContext</code>s + * are allowed to implement this interface. + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContextContainerProxy { + /** + * Get the <code>Container</code> associated with this <code>BeanContext</code>. + * @return the <code>Container</code> associated with this + * <code>BeanContext</code>. + */ + public Container getContainer(); +} diff --git a/libjava/java/beans/beancontext/BeanContextEvent.java b/libjava/java/beans/beancontext/BeanContextEvent.java new file mode 100644 index 0000000..0e4f20a --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextEvent.java @@ -0,0 +1,91 @@ +/* java.beans.beancontext.BeanContextEvent + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.util.EventObject; + +/** + * Generic superclass for events fired by <code>BeanContext</code>s. + * + * @author John Keiser + * @since JDK1.2 + */ + +public abstract class BeanContextEvent extends EventObject { + /** + * The <code>BeanContext</code> that most recently passed this + * event on. + */ + protected BeanContext propagatedFrom; + + /** + * Create a new event, from the specified <code>BeanContext</code>. + * <code>propagatedFrom</code> will be initialized to + * <code>null</code>. + * + * @param source the source of the event. + */ + protected BeanContextEvent(BeanContext source) { + super(source); + } + + /** + * Get the <code>BeanContext</code> that originated this event. + * @return the originator of this event. + */ + public BeanContext getBeanContext() { + return (BeanContext)getSource(); + } + + /** + * Get the most recent propagator of this event. + * If this value is <code>null</code>, you have received the event + * straight from the source. + * + * @return the most recent propagator of this event. + */ + public BeanContext getPropagatedFrom() { + return propagatedFrom; + } + + /** + * Tell whether this event has been propagated. + * @return <code>true</code> iff <code>getPropagatedFrom() != null</code>. + */ + public boolean isPropagated() { + return propagatedFrom != null; + } + + /** + * Set the most recent propagator of this event. + * @param propagator the most recent propagator of this event. + */ + public void setPropagatedFrom(BeanContext propagator) { + propagatedFrom = propagator; + } +} diff --git a/libjava/java/beans/beancontext/BeanContextMembershipEvent.java b/libjava/java/beans/beancontext/BeanContextMembershipEvent.java new file mode 100644 index 0000000..d808735 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextMembershipEvent.java @@ -0,0 +1,102 @@ +/* java.beans.beancontext.BeanContextMembershipEvent + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.util.Collection; +import java.util.Arrays; +import java.util.Iterator; + +/** + * Event fired when children are added to or removed from a <code>BeanContext</code>. + * Whether they were added or removed depends entirely on which method + * of the listener interface was called. + * + * @author John Keiser + * @since JDK1.2 + * @see java.beans.beancontext.BeanContextMembershipListener + */ + +public class BeanContextMembershipEvent extends BeanContextEvent { + /** + * The children that were added or removed. + */ + protected Collection children; + + /** + * Create a new membership event. + * @param context the event source. + * @param children the children added to or removed from the source. + */ + public BeanContextMembershipEvent(BeanContext context, Collection children) { + super(context); + this.children = children; + } + + /** + * Create a new membership event. + * @param context the event source. + * @param children the children added to or removed from the source. + */ + public BeanContextMembershipEvent(BeanContext context, Object[] children) { + super(context); + this.children = Arrays.asList(children); + } + + /** + * The number of children removed or added. + * @return the number of children removed or added. + */ + public int size() { + return children.size(); + } + + /** + * An iterator that will step through all the children. + * @return an iterator over all the children. + */ + public Iterator iterator() { + return children.iterator(); + } + + /** + * An array of the children. + * @return an array of the children. + */ + public Object[] toArray() { + return children.toArray(); + } + + /** + * Tell whether the <code>Object</code> is one of the children added or removed. + * @param child the child to check. + * @return whether the <code>Object</code> is added or removed. + */ + public boolean contains(Object child) { + return children.contains(child); + } +} diff --git a/libjava/java/beans/beancontext/BeanContextMembershipListener.java b/libjava/java/beans/beancontext/BeanContextMembershipListener.java new file mode 100644 index 0000000..fc0b5b6 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextMembershipListener.java @@ -0,0 +1,59 @@ +/* java.beans.beancontext.BeanContextMembershipListener + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.util.EventListener; + +/** + * This is the interface to which <code>BeanContextMembershipEvent</code>s are sent. + * This happens when children are added to or removed from a + * <code>BeanContext</code>. + * + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContextMembershipListener extends EventListener { + /** + * When beans are added to a <code>BeanContext</code>, + * this method is called to fire the event. + * + * @param event the event, including which children were added. + * @see java.beans.beancontext.BeanContext#add(java.lang.Object) + */ + public void childrenAdded(BeanContextMembershipEvent event); + + /** + * When beans are removed from a <code>BeanContext</code>, + * this method is called to fire the event. + * + * @param event the event, including which children were removed. + * @see java.beans.beancontext.BeanContext#remove(java.lang.Object) + */ + public void childrenRemoved(BeanContextMembershipEvent event); +} diff --git a/libjava/java/beans/beancontext/BeanContextProxy.java b/libjava/java/beans/beancontext/BeanContextProxy.java new file mode 100644 index 0000000..129e4f8 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextProxy.java @@ -0,0 +1,54 @@ +/* java.beans.beancontext.BeanContextProxy + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +/** + * Beans that wish to have a <code>BeanContextChild</code> or <code>BeanContext</code> associated with them + * but do not wish to implement those interfaces directly, can implement this interface. + * <P> + * + * Don't shoot yourself in the foot: if you already implement + * <code>BeanContextChild</code>, directly or indirectly, the whole + * workings of this package will be unpredictable because it is + * indeterminate as to whether the <code>BeanContextChild</code> is used + * in preference to its proxy or vice versa. + * + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContextProxy { + /** + * Return the <code>BeanContextChild</code> associated with this + * <code>Object</code>. + * + * @return the <code>BeanContextChild</code> associated with this + * <code>Object</code>. + */ + public BeanContextChild getBeanContextProxy(); +} diff --git a/libjava/java/beans/beancontext/BeanContextServiceAvailableEvent.java b/libjava/java/beans/beancontext/BeanContextServiceAvailableEvent.java new file mode 100644 index 0000000..933ef3d --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceAvailableEvent.java @@ -0,0 +1,84 @@ +/* java.beans.beancontext.BeanContextServiceAvailableEvent + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.util.Iterator; + +/** + * Event fired when new services become available through a <code>BeanContextServices</code>. + * + * @author John Keiser + * @since JDK1.2 + * @see java.beans.beancontext.BeanContextServicesListener + */ + +public class BeanContextServiceAvailableEvent extends BeanContextEvent { + /** + * The <code>Class</code> representing the service which is now + * available. + */ + protected Class serviceClass; + + /** + * Create a new service available event. + * @param services the <code>BeanContextServices</code> through + * which the service is available. This is also the source + * of the event. + * @param serviceClass the service class that is now available. + */ + public BeanContextServiceAvailableEvent(BeanContextServices services, Class serviceClass) { + super(services); + this.serviceClass = serviceClass; + } + + /** + * Get the current service selectors of the service class. + * This is identical to <code>getSourceAsBeanContextServices().getCurrentServiceSelectors(getServiceClass())</code> + * @return the current service selectors of the service class. + */ + public Iterator getCurrentServiceSelectors() { + return getSourceAsBeanContextServices().getCurrentServiceSelectors(serviceClass); + } + + /** + * Get the newly available service class. + * @return the service class. + */ + public Class getServiceClass() { + return serviceClass; + } + + /** + * Get the <code>BeanContextServices</code> through which the new service is available. + * @return the <code>BeanContextServices</code> through which the + * new service is available. + */ + public BeanContextServices getSourceAsBeanContextServices() { + return (BeanContextServices)getSource(); + } +} diff --git a/libjava/java/beans/beancontext/BeanContextServiceProvider.java b/libjava/java/beans/beancontext/BeanContextServiceProvider.java new file mode 100644 index 0000000..c7a570e --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceProvider.java @@ -0,0 +1,129 @@ +/* java.beans.beancontext.BeanContextServiceProvider + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.util.Iterator; + +/** + * An actual factory for services. + * <P> + * + * It is the <code>BeanContextServiceProvider</code>'s responsibility to + * register itself with whatever <code>BeanContextServices</code> object + * it wishes to provide services through using the + * <code>addService()</code> method. + * <P> + * + * If for some reason it can no longer provide services for a particular + * class, this class must invoke + * <code>BeanContextServices.revokeService(serviceClass,this,true)</code> + * for all the places it has registered the service. + * + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContextServiceProvider { + /** + * Get a service. + * Called from <code>BeanContextServices.getService(). + * <P> + * + * If the requested service class is not available, or if this + * <code>BeanContextServiceProvider</code> chooses not honor the + * request for some reason, then this method will return + * <code>null</code>. + * <P> + * + * This method may throw unchecked exceptions, so watch out. + * + * @param services the <code>BeanContextServices</code> that wants + * to get the service. Only weak references to this will + * be retained, and it will never be changed, only queried + * in a read-only manner. + * @param requestor the actual requestor of the service. Only + * weak references to this will be retained, and it will + * never be changed, only queried in a read-only manner. + * @param serviceClass the <code>Class</code> of the service being + * requested. + * @param serviceSelector a parameter to customize the service + * returned with. + * @return an instance of <code>serviceClass</code> (such that + * <code>instanceof</code> serviceClass is true), or + * <code>null</code>. + * @see java.beans.beancontext.BeanContextServices#getService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Class,java.lang.Object,java.beans.beancontext.BeanContextServiceRevokedListener) + */ + public Object getService(BeanContextServices services, Object requestor, Class serviceClass, Object serviceSelector); + + /** + * Release the service. + * <P> + * + * Called by <code>BeanContextServices.releaseService()</code>. + * <P> + * + * Most <code>BeanContextServiceProvider</code>s won't have to do + * anything here. + * + * @param services the <code>BeanContextServices</code> that wants + * to release the service. Only weak references to this will + * be retained, and it will never be changed, only queried + * in a read-only manner. + * @param requestor the original requestor of the service. + * @param service the service to relinquish + * @see java.beans.beancontext.BeanContextServices#releaseService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Object) + */ + public void releaseService(BeanContextServices services, Object requestor, Object service); + + /** + * Get a list of valid service selectors for the specified service class. + * This method is called from + * <code>BeanContextServices.getCurrentServiceSelectors()</code>. + * <P> + * + * If the specified service class does not have a finite number of + * valid service selectors, it should return <code>null</code>. + * If it takes a general <code>Integer</code> parameter, for + * example, you may as well return <code>null</code> or the poor + * soul who called this method will be iterating all day. + * <P> + * + * If it has no valid service selectors, it should still return an empty + * <code>Iterator</code>. + * + * @param services the <code>BeanContextServices</code> that wants + * to get the service selectors. Only weak references to this will + * be retained, and it will never be changed, only queried + * in a read-only manner. + * @param serviceClass the service class to get selectors for. + * @return a list of valid service selectors for the service + * class, or <code>null</code>. + * @see java.beans.beancontext.BeanContextServices#getCurrentServiceSelectors(java.lang.Class) + */ + public Iterator getCurrentServiceSelectors(BeanContextServices services, Class serviceClass); +} diff --git a/libjava/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java b/libjava/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java new file mode 100644 index 0000000..d751f70 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java @@ -0,0 +1,49 @@ +/* java.beans.beancontext.BeanContextServiceProviderBeanInfo + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.beans.BeanInfo; + +/** + * <code>BeanContextServiceProvider</code>s implement this to provide information about all of the services they provide. + * <P> + * + * This is apparently so that you can import a bunch of services into a + * RAD tool and it will know about all of them and export them to the + * user in a readable manner. + * + * @author John Keiser + * @since JDK1.2 + */ +public interface BeanContextServiceProviderBeanInfo extends BeanInfo { + /** + * Get <code>BeanInfo</code>s for all of the service classes of this <code>BeanInfoServiceProvider</code>. + * @return <code>BeanInfo</code>s for all provided service classes. + */ + public BeanInfo[] getServicesBeanInfo(); +} diff --git a/libjava/java/beans/beancontext/BeanContextServiceRevokedEvent.java b/libjava/java/beans/beancontext/BeanContextServiceRevokedEvent.java new file mode 100644 index 0000000..32520bc --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceRevokedEvent.java @@ -0,0 +1,99 @@ +/* java.beans.beancontext.BeanContextServiceRevokedEvent + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +/** + * Event fired when services are revoked from a <code>BeanContextServices</code>. + * + * @author John Keiser + * @since JDK1.2 + * @see java.beans.beancontext.BeanContextServiceRevokedListener + */ + +public class BeanContextServiceRevokedEvent extends BeanContextEvent { + /** + * The <code>Class</code> representing the service which is now + * available. + */ + protected Class serviceClass; + private boolean revokeNow; + + /** + * Create a new service revoked event. + * @param services the <code>BeanContextServices</code> through + * which the service was available. This is also the source + * of the event. + * @param serviceClass the service class that is now revoked. + * @param revokeNow whether the revocation is immediate for all + * classes or just a suggestion. + */ + public BeanContextServiceRevokedEvent(BeanContextServices services, Class serviceClass, boolean revokeNow) { + super(services); + this.serviceClass = serviceClass; + this.revokeNow = revokeNow; + } + + /** + * Get the revoked service class. + * @return the service class. + */ + public Class getServiceClass() { + return serviceClass; + } + + /** + * Tell whether the revoked service class is the same as the specified class. + * Identical to <code>getServiceClass().equals(c)</code>. + * @param c the class to compare. + * @return whether the clases are equal. + */ + public boolean isServiceClass(Class c) { + return serviceClass.equals(c); + } + + /** + * Get the <code>BeanContextServices</code> through which the service was available. + * @return the <code>BeanContextServices</code> through which the + * service was available. + */ + public BeanContextServices getSourceAsBeanContextServices() { + return (BeanContextServices)getSource(); + } + + /** + * Tell whether current instances of the revoked service are usable or not. + * This is determined by whether the service was revoked + * immediately. + * + * @return whether current instances of the revoked service are + * usable. + */ + public boolean isCurrentServiceInvalidNow() { + return revokeNow; + } +} diff --git a/libjava/java/beans/beancontext/BeanContextServiceRevokedListener.java b/libjava/java/beans/beancontext/BeanContextServiceRevokedListener.java new file mode 100644 index 0000000..8caf357 --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServiceRevokedListener.java @@ -0,0 +1,51 @@ +/* java.beans.beancontext.BeanContextServiceRevokedListener + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.util.EventListener; + +/** + * Listens for service revoke events. + * + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContextServiceRevokedListener extends EventListener { + /** + * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked. + * If you have a reference to such a service, it should be + * discarded and may no longer function properly. + * <code>getService()</code> will no longer work on the specified + * service class after this event has been fired. + * + * @param event the service revoked event. + * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean) + */ + public void serviceRevoked(BeanContextServiceRevokedEvent event); +} diff --git a/libjava/java/beans/beancontext/BeanContextServices.java b/libjava/java/beans/beancontext/BeanContextServices.java new file mode 100644 index 0000000..e67687b --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServices.java @@ -0,0 +1,195 @@ +/* java.beans.beancontext.BeanContextServices + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +import java.util.Iterator; + +/** + * Allows a <code>BeanContext</code> to provide services to its children. + * + * @specnote it is unclear whether a <code>BeanContextServices</code> + * should delegate unhandled requests to parents. I assume so. + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContextServices extends BeanContext, BeanContextServicesListener { + /** + * Register a service to make it available to others. + * This class may refuse to add the service based on whatever + * information it can gather, including whether the service + * provider is trusted. + * + * @param serviceClass the service class. + * @param provider the factory that will actually provide the service. + * @return whether the service was added or not. + */ + public boolean addService(Class serviceClass, BeanContextServiceProvider provider); + + /** + * Make it so that no one else can use this service. + * <P> + * + * If <code>revokeNow</code> is <code>false</code>, the only + * effect of this method is to make all subsequent calls to + * <code>getService()</code> on this service class fail. + * <P> + * + * If it is <code>true</code>, a message is also sent out to all + * listeners on the service and all references to it are released. + * + * @param serviceClass the service class to revoke. + * @param provider the service provider providing the service class. + * @param revokeNow whether to release all current references to + * the service. + */ + public void revokeService(Class serviceClass, BeanContextServiceProvider provider, boolean revokeNow); + + /** + * Release your copy of this service. + * <P> + * + * If all copies of the service's class have been relinquished by + * the requestor, the <code>BeanContextServiceRevokedListener</code> + * previously registered by <code>getService()</code> will be + * unregistered. + * + * @param requestorChild the original <code>BeanContextChild</code> + * requesting the service. + * @param requestor the original requestor of the service. + * @param service the service to relinquish + * @see #getService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Class,java.lang.Object,java.beans.beancontext.BeanContextServiceRevokedListener) + */ + public void releaseService(BeanContextChild requestorChild, Object requestor, Object service); + + /** + * Get a service from this <code>BeanContextServices</code>. + * <P> + * + * The specified listener will be registered to receive a + * revocation notice for the specified serviceClass. One + * notification per service class per requestor object will be + * sent. + * <P> + * + * The listener will be unregistered when all services that were + * obtained by that requestor for that service class are released. + * <P> + * + * If the requested service class is not available, or if this + * <code>BeanContextServices</code> object chooses not honor the + * request because the service class has been revoked or for some + * other reason, then this method will return <code>null</code>. + * <P> + * + * This method may throw unchecked exceptions, so watch out. + * + * @specnote it is not specified what happens when two subsequent + * calls are made to <code>getService()</code> with the + * same requestor object and service class but different + * listeners. Which listener is to be notified? + * + * @param requestorChild the <code>BeanContextChild</code> + * associated with the requestor. Typically this will be + * the same as the requestor itself, but since any + * <code>Object</code>, even one outside the hierarchy, may + * make a request, this parameter is necessary. Only weak + * references to this will be retained, and it will never + * be changed, only queried in a read-only manner. + * @param requestor the actual requestor of the service. Only + * weak references to this will be retained, and it will + * never be changed, only queried in a read-only manner. + * @param serviceClass the <code>Class</code> of the service being + * requested. + * @param serviceSelector a parameter to customize the service + * returned with. + * @param listener a listener that will be notified if the service + * being requested is revoked. + * @return an instance of <code>serviceClass</code> (such that + * <code>instanceof</code> serviceClass is true), or + * <code>null</code>. + */ + public Object getService(BeanContextChild requestorChild, Object requestor, Class serviceClass, Object serviceSelector, BeanContextServiceRevokedListener listener); + + /** + * Get a list of all service classes supported. + * <P> + * + * This method must synchronize on + * <code>BeanContext.globalHierarchyLock</code>. + * + * @return a list of all service classes supported. + * @see java.beans.beancontext.BeanContext#globalHierarchyLock + */ + public Iterator getCurrentServiceClasses(); + + /** + * Get a list of valid service selectors for the specified service class. + * <P> + * + * If the specified service class does not have a finite number of + * valid service selectors, it should return <code>null</code>. + * If it takes a general <code>Integer</code> parameter, for + * example, you may as well return <code>null</code> or the poor + * soul who called this method will be iterating all day. + * <P> + * + * If it has no valid service selectors, it should still return an empty + * <code>Iterator</code>. + * + * @param serviceClass the service class to get selectors for. + * @return a list of valid service selectors for the service + * class, or <code>null</code>. + */ + public Iterator getCurrentServiceSelectors(Class serviceClass); + + /** + * Tell whether the specified service class is available. + * Iff getService() could return a non-null value for the + * specified service, this method will return <code>true</code>. + * + * @param serviceClass the service class to check on. + * @return whether the specified service class is availabe. + */ + public boolean hasService(Class serviceClass); + + /** + * Add a listener on all adds and removes of services. + * @param listener the listener to add. + */ + public void addBeanContextServicesListener(BeanContextServicesListener listener); + + /** + * Remove a listener on all adds and removes of services. + * @specnote it is not certain whether this should remove this + * listener if it was specified in + * <code>getService()</code>. + * @param listener the listener to add. + */ + public void removeBeanContextServicesListener(BeanContextServicesListener listener); +} diff --git a/libjava/java/beans/beancontext/BeanContextServicesListener.java b/libjava/java/beans/beancontext/BeanContextServicesListener.java new file mode 100644 index 0000000..bb55f8d --- /dev/null +++ b/libjava/java/beans/beancontext/BeanContextServicesListener.java @@ -0,0 +1,45 @@ +/* java.beans.beancontext.BeanContextServicesListener + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.beans.beancontext; + +/** + * Listens for service add and revoke events. + * + * @author John Keiser + * @since JDK1.2 + */ + +public interface BeanContextServicesListener extends BeanContextServiceRevokedListener { + /** + * Called by <code>BeanContextServices</code> whenever a service is made available. + * + * @param event the service revoked event, with useful information + * about the new service. + */ + public void serviceAvailable(BeanContextServiceAvailableEvent event); +} |